// XIM プロトコルで定義されるIMの処理を行う。 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "xim.h" #include #define NEED_EVENTS // xEventの宣言のため、 #include #ifndef __GNUC__ # ifdef HAVE_ALLOCA_H # include # endif #endif static std::map g_ims; class XimIM_impl : public XimIM { public: XimIM_impl(Connection *c,int id); virtual ~XimIM_impl(); void create_ic(RxPacket *); void destroy_ic(int ); void set_ic_focus(int icid); void set_ic_values(RxPacket *, int icid); void get_ic_values(RxPacket *); void unset_ic_focus(int icid); void forward_event(RxPacket *); XimIC *get_ic_by_id(int id); void onSendPacket(); private: int unused_ic_id(); void free_all_ic(); void delete_ic(XimIC *); std::map m_ics; }; XimIM_impl::XimIM_impl(Connection *c,int id) : XimIM(c,id) { } XimIM_impl::~XimIM_impl() { if (g_option_mask & OPT_TRACE) { printf("imid=%d im deleted.\n", mID); } free_all_ic(); } void XimIM_impl::create_ic(RxPacket *p) { XimIC *ic; int icid= unused_ic_id(); ic = ::create_ic(mConn,p,mID,icid); if (!ic) { mConn->push_error_packet(mID,icid, ERR_Style,"invalid im style"); mConn->terminate(); return ; } std::pair n(ic->get_icid(),ic); m_ics.insert(n); TxPacket *t; t = createTxPacket(XIM_CREATE_IC_REPLY,0); t->pushC16(mID); t->pushC16(ic->get_icid()); mConn->push_packet(t); } void XimIM_impl::destroy_ic(int icid) { //ICを破壊 XimIC *ic = get_ic_by_id(icid); delete_ic(ic); } void XimIM_impl::set_ic_values(RxPacket *p, int icid) { // imid, icid p->rewind(); (void)p->getC16(); (void)p->getC16(); XimIC *ic = get_ic_by_id(icid); int atr_len; atr_len = p->getC16(); p->getC16(); unsigned char *v; v = (unsigned char *)alloca(atr_len); int i; for ( i = 0 ; i < atr_len ; i++){ v[i] = p->getC8(); } if (ic) { ic->set_ic_attrs((void *)v, atr_len); } } void XimIM_impl::get_ic_values(RxPacket *p) { int icid; XimIC *ic; p->rewind(); p->getC16(); icid = p->getC16(); ic = get_ic_by_id(icid); int len; len = p->getC16(); TxPacket *t = createTxPacket(XIM_GET_IC_VALUES_REPLY,0); t->pushC16(mID); t->pushC16(icid); int i,id,l; l = 0; for (i = 0; i < len /2 ; i++) { id = p->getC16(); l += ic->get_ic_atr(id, 0); l += 4; } t->pushC16(l); t->pushC16(0); p->rewind(); p->getC16();//imid p->getC16();//icid p->getC16();// n for (i = 0; i < len /2 ; i++) { id = p->getC16(); t->pushC16(id); t->pushC16(ic->get_ic_atr(id, 0)); l += ic->get_ic_atr(id, t); } mConn->push_packet(t); } int XimIM_impl::unused_ic_id() { std::map::iterator i; int max_id=1; // input-context IDは1から使う? for (i = m_ics.begin(); i != m_ics.end(); i++) { if (max_id <= (*i).first) { max_id = (*i).first+1; } } return max_id; } void XimIM_impl::set_ic_focus(int icid) { XimIC *ic = get_ic_by_id(icid); if (ic) { ic->set_focus(); } } void XimIM_impl::unset_ic_focus(int icid) { XimIC *ic = get_ic_by_id(icid); if (ic) { ic->unset_focus(); } } XimIC *XimIM_impl::get_ic_by_id(int icid) { std::map::iterator it; it = m_ics.find(icid); if (it == m_ics.end()) { return 0; } return it->second; } void XimIM_impl::forward_event(RxPacket *p) { unsigned char *c; int i; keyEventX k; xEvent ev_raw; int imid,icid,flag; XimIC *ic; imid = p->getC16(); icid = p->getC16(); flag = p->getC16(); ic = get_ic_by_id(icid); k.serial = p->getC16(); //xEventのコピーを取る。 c = (unsigned char *)&ev_raw; for (i = 0 ; i < (int)sizeof(ev_raw); i++) { *c = p->getC8(); c++; } k.ev.type = ev_raw.u.u.type &0x7f; k.ev.xany.serial = (k.serial << 16)| ev_raw.u.u.sequenceNumber; k.ev.xany.display = gDpy; k.ev.xany.send_event = ev_raw.u.u.type>127; switch (k.ev.type) { case KeyPress: //case KeyRelease: k.ev.xkey.window = mConn->to_hl(ev_raw.u.keyButtonPointer.event); k.ev.xkey.root = mConn->to_hl(ev_raw.u.keyButtonPointer.root); k.ev.xkey.subwindow = mConn->to_hl(ev_raw.u.keyButtonPointer.child); k.ev.xkey.time = mConn->to_hs(ev_raw.u.keyButtonPointer.time); k.ev.xkey.x = mConn->to_hl(ev_raw.u.keyButtonPointer.eventX); k.ev.xkey.y = mConn->to_hs(ev_raw.u.keyButtonPointer.eventY); k.ev.xkey.x_root = mConn->to_hs(ev_raw.u.keyButtonPointer.rootX); k.ev.xkey.y_root = mConn->to_hs(ev_raw.u.keyButtonPointer.rootY); k.ev.xkey.state = ev_raw.u.keyButtonPointer.state; k.ev.xkey.keycode = ev_raw.u.u.detail; k.ev.xkey.same_screen = ev_raw.u.keyButtonPointer.sameScreen; char buf[10]; KeySym ks; XLookupString(&k.ev.xkey,buf,10,&ks,0); k.state = mConn->to_hs(ev_raw.u.keyButtonPointer.state); k.press = (k.ev.type == KeyPress); k.key_sym = ks; if (ic) { ic->OnKeyEvent(k); } break; default: printf("unknown type of forwarded event.(%d)\n", k.ev.type); break; } } void XimIM_impl::free_all_ic() { std::map::iterator i; for ( i = m_ics.begin() ; i!= m_ics.end() ; i++){ (*i).second->unset_focus(); delete (*i).second; } m_ics.erase(m_ics.begin(),m_ics.end()); } void XimIM_impl::delete_ic(XimIC *ic) { std::map::iterator it; for (it = m_ics.begin(); it != m_ics.end(); it++) { if (it->second == ic) { it->second->unset_focus(); delete it->second; m_ics.erase(it); return ; } } } void XimIM_impl::onSendPacket() { std::map::iterator i; for ( i = m_ics.begin() ; i!= m_ics.end() ; i++){ (*i).second->onSendPacket(); } } XimIM::XimIM(Connection *c,int id) { mConn = c; mID = id; } int unused_im_id() { int max_id; std::map::iterator i; max_id = 1; for ( i = g_ims.begin() ; i != g_ims.end() ; i++){ if ( (*i).first == max_id ){ max_id = (*i).first +1; } } return max_id; } XimIM *create_im(Connection *c,int id) { XimIM *im; im = new XimIM_impl(c,id); std::pair p(id,im); g_ims.insert(p); return im; } XimIM *get_im_by_id(int id) { std::map::iterator it; it = g_ims.find(id); if (it == g_ims.end()) { return NULL; } return it->second; } void close_im(int id) { XimIM *im; im = get_im_by_id(id); if (im) { delete im; } std::map::iterator it; it = g_ims.find(id); if (it != g_ims.end()) { g_ims.erase(it); } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */