Home | History | Annotate | Line # | Download | only in ximcp
      1 /******************************************************************
      2 
      3            Copyright 1992, 1993, 1994 by FUJITSU LIMITED
      4 
      5 Permission to use, copy, modify, distribute, and sell this software
      6 and its documentation for any purpose is hereby granted without fee,
      7 provided that the above copyright notice appear in all copies and
      8 that both that copyright notice and this permission notice appear
      9 in supporting documentation, and that the name of FUJITSU LIMITED
     10 not be used in advertising or publicity pertaining to distribution
     11 of the software without specific, written prior permission.
     12 FUJITSU LIMITED makes no representations about the suitability of
     13 this software for any purpose.
     14 It is provided "as is" without express or implied warranty.
     15 
     16 FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18 EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
     20 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     21 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     22 PERFORMANCE OF THIS SOFTWARE.
     23 
     24   Author: Takashi Fujiwara     FUJITSU LIMITED
     25                                fujiwara (at) a80.tech.yk.fujitsu.co.jp
     26 
     27 ******************************************************************/
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include <config.h>
     31 #endif
     32 #include <X11/Xatom.h>
     33 #include "Xlibint.h"
     34 #include "Xutil.h"
     35 #include "Xlcint.h"
     36 #include "Ximint.h"
     37 
     38 static long
     39 _XimTriggerCheck(
     40     Xim			 im,
     41     XKeyEvent		*ev,
     42     INT32		 len,
     43     CARD32		*keylist)
     44 {
     45     register long	 i;
     46     KeySym	 	 keysym;
     47     CARD32	 	 buf32[BUFSIZE/4];
     48     char	 	*buf = (char *)buf32;
     49     int			 modifier;
     50     int			 modifier_mask;
     51     CARD32		 min_len = sizeof(CARD32)   /* sizeof keysym */
     52 				 + sizeof(CARD32)   /* sizeof modifier */
     53 				 + sizeof(CARD32);  /* sizeof modifier mask */
     54 
     55     XLookupString(ev, buf, BUFSIZE, &keysym, NULL);
     56     if (!keysym)
     57 	return -1;
     58 
     59     for (i = 0; len >= min_len; i += 3, len -= min_len) {
     60 	modifier      = keylist[i + 1];
     61 	modifier_mask = keylist[i + 2];
     62 	if (((KeySym)keylist[i] == keysym)
     63 	 && ((ev->state & modifier_mask) == modifier))
     64 	    return i;
     65     }
     66     return -1;
     67 }
     68 
     69 static long
     70 _XimTriggerOnCheck(
     71     Xim		 im,
     72     XKeyEvent	*ev)
     73 {
     74     return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_onkeylist[0],
     75 					&im->private.proto.im_onkeylist[1]);
     76 }
     77 
     78 static long
     79 _XimTriggerOffCheck(
     80     Xim		 im,
     81     XKeyEvent	*ev)
     82 {
     83     return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_offkeylist[0],
     84 					&im->private.proto.im_offkeylist[1]);
     85 }
     86 
     87 static Bool
     88 _XimOnKeysCheck(
     89     Xic		 ic,
     90     XKeyEvent	*ev)
     91 {
     92     Xim		 im = (Xim)ic->core.im;
     93     long	 idx;
     94 
     95     if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
     96 	    im->private.proto.im_onkeylist &&
     97 	    im->private.proto.im_onkeylist[0]) {
     98 	if ((idx = _XimTriggerOnCheck(im, ev)) >= 0) {
     99 	    (void)_XimTriggerNotify(im, ic, 0, (CARD32)idx); /* Trigger on */
    100 	    return True;
    101 	}
    102     }
    103     return False;
    104 }
    105 
    106 static Bool
    107 _XimOffKeysCheck(
    108     Xic		 ic,
    109     XKeyEvent	*ev)
    110 {
    111     Xim		 im = (Xim)ic->core.im;
    112     long	 idx;
    113 
    114     if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
    115 	    im->private.proto.im_offkeylist &&
    116 	    im->private.proto.im_offkeylist[0]) {
    117 	if ((idx = _XimTriggerOffCheck(im, ev)) >= 0) {
    118 	    _XimTriggerNotify(im, ic, 1, (CARD32)idx); /* Trigger off */
    119 	    return True;
    120 	}
    121     }
    122     return False;
    123 }
    124 
    125 void
    126 _XimPendingFilter(
    127     Xic	 	 ic)
    128 {
    129     Xim          im = (Xim)ic->core.im;
    130 
    131     if (IS_NEED_SYNC_REPLY(im)) {
    132 	(void)_XimProcSyncReply(im, ic);
    133 	UNMARK_NEED_SYNC_REPLY(im);
    134     }
    135     return;
    136 }
    137 
    138 static Bool
    139 _XimProtoKeypressFilter(
    140     Xic		 ic,
    141     XKeyEvent	*ev,
    142     Window	 w)
    143 {
    144     Xim		im = (Xim)ic->core.im;
    145 
    146     if (_XimIsFabricatedSerial(im, ev)) {
    147 	_XimPendingFilter(ic);
    148 	_XimUnfabricateSerial(im, ic, ev);
    149 	return NOTFILTERD;
    150     }
    151     /* w=0 is used for _XimIsFabricatedSerial() only */
    152     if (!w)
    153 	return NOTFILTERD;
    154 
    155     if (IS_NEGLECT_EVENT(ic, KeyPressMask))
    156 	return FILTERD;
    157 
    158 #ifdef XIM_CONNECTABLE
    159     if (!IS_IC_CONNECTED(ic)) {
    160 	if (IS_CONNECTABLE(im)) {
    161 	    if (_XimConnectServer(im)) {
    162 		if (!_XimReCreateIC(ic)) {
    163 		    _XimDelayModeSetAttr(im);
    164 		    return NOTFILTERD;
    165 		}
    166 	    } else {
    167 		return NOTFILTERD;
    168 	    }
    169 	} else {
    170 	    return NOTFILTERD;
    171 	}
    172     }
    173 #else
    174     if (!IS_IC_CONNECTED(ic))
    175 	return NOTFILTERD;
    176 #endif /* XIM_CONNECTABLE */
    177 
    178     if (!IS_FORWARD_EVENT(ic, KeyPressMask)) {
    179 	if (_XimOnKeysCheck(ic, ev))
    180 	    return FILTERD;
    181 	return NOTFILTERD;
    182     }
    183     if (_XimOffKeysCheck(ic, ev))
    184 	return FILTERD;
    185 
    186     if (_XimForwardEvent(ic, (XEvent *)ev,
    187 				IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
    188 	return FILTERD;
    189 
    190     return NOTFILTERD;
    191 }
    192 
    193 static Bool
    194 _XimFilterKeypress(
    195     Display		*d,
    196     Window		 w,
    197     XEvent		*ev,
    198     XPointer		 client_data)
    199 {
    200     return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev, w);
    201 }
    202 
    203 static Bool
    204 _XimProtoKeyreleaseFilter(
    205     Xic		 ic,
    206     XKeyEvent	*ev,
    207     Window	 w)
    208 {
    209     Xim		im = (Xim)ic->core.im;
    210 
    211     if (_XimIsFabricatedSerial(im, ev)) {
    212 	_XimPendingFilter(ic);
    213 	_XimUnfabricateSerial(im, ic, ev);
    214 	return NOTFILTERD;
    215     }
    216     /* w=0 is used for _XimIsFabricatedSerial() only */
    217     if (!w)
    218 	return NOTFILTERD;
    219 
    220     if (IS_NEGLECT_EVENT(ic, KeyReleaseMask))
    221 	return FILTERD;
    222 
    223 #ifdef XIM_CONNECTABLE
    224     if (!IS_IC_CONNECTED(ic)) {
    225 	if (IS_CONNECTABLE(im)) {
    226 	    if (_XimConnectServer(im)) {
    227 		if (!_XimReCreateIC(ic)) {
    228 		    _XimDelayModeSetAttr(im);
    229 		    return NOTFILTERD;
    230 		}
    231 	    } else {
    232 		return NOTFILTERD;
    233 	    }
    234 	} else {
    235 	    return NOTFILTERD;
    236 	}
    237     }
    238 #else
    239     if (!IS_IC_CONNECTED(ic))
    240 	return NOTFILTERD;
    241 #endif /* XIM_CONNECTABLE */
    242 
    243     if (!IS_FORWARD_EVENT(ic, KeyReleaseMask)) {
    244 	if (_XimOnKeysCheck(ic, ev))
    245 	    return FILTERD;
    246 	return NOTFILTERD;
    247     }
    248     if (_XimOffKeysCheck(ic, ev))
    249 	    return FILTERD;
    250 
    251     if (_XimForwardEvent(ic, (XEvent *)ev,
    252 				IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
    253 	return FILTERD;
    254 
    255     return NOTFILTERD;
    256 }
    257 
    258 static Bool
    259 _XimFilterKeyrelease(
    260     Display		*d,
    261     Window		 w,
    262     XEvent		*ev,
    263     XPointer		 client_data)
    264 {
    265     return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev, w);
    266 }
    267 
    268 static void
    269 _XimRegisterKeyPressFilter(
    270     Xic		 ic)
    271 {
    272     if (ic->core.focus_window) {
    273 	if (!(ic->private.proto.registed_filter_event & KEYPRESS_MASK)) {
    274 	    _XRegisterFilterByType (ic->core.im->core.display,
    275 				    0,
    276 				    KeyPress, KeyPress,
    277 				    _XimFilterKeypress,
    278 				    (XPointer)ic);
    279 	    _XRegisterFilterByType (ic->core.im->core.display,
    280 				    ic->core.focus_window,
    281 				    KeyPress, KeyPress,
    282 				    _XimFilterKeypress,
    283 				    (XPointer)ic);
    284 	    ic->private.proto.registed_filter_event |= KEYPRESS_MASK;
    285 	}
    286     }
    287     return;
    288 }
    289 
    290 static void
    291 _XimRegisterKeyReleaseFilter(
    292     Xic		 ic)
    293 {
    294     if (ic->core.focus_window) {
    295 	if (!(ic->private.proto.registed_filter_event & KEYRELEASE_MASK)) {
    296 	    _XRegisterFilterByType (ic->core.im->core.display,
    297 				    0,
    298 				    KeyRelease, KeyRelease,
    299 				    _XimFilterKeyrelease,
    300 				    (XPointer)ic);
    301 	    _XRegisterFilterByType (ic->core.im->core.display,
    302 				    ic->core.focus_window,
    303 				    KeyRelease, KeyRelease,
    304 				    _XimFilterKeyrelease,
    305 				    (XPointer)ic);
    306 	    ic->private.proto.registed_filter_event |= KEYRELEASE_MASK;
    307 	}
    308     }
    309     return;
    310 }
    311 
    312 static void
    313 _XimUnregisterKeyPressFilter(
    314     Xic		 ic)
    315 {
    316     if (ic->core.focus_window) {
    317 	if (ic->private.proto.registed_filter_event & KEYPRESS_MASK) {
    318 	    _XUnregisterFilter (ic->core.im->core.display,
    319 				ic->core.focus_window,
    320 				_XimFilterKeypress,
    321 				(XPointer)ic);
    322 	    _XUnregisterFilter (ic->core.im->core.display,
    323 				0,
    324 				_XimFilterKeypress,
    325 				(XPointer)ic);
    326 	    ic->private.proto.registed_filter_event &= ~KEYPRESS_MASK;
    327 	}
    328     }
    329     return;
    330 }
    331 
    332 static void
    333 _XimUnregisterKeyReleaseFilter(
    334     Xic		 ic)
    335 {
    336     if (ic->core.focus_window) {
    337 	if (ic->private.proto.registed_filter_event & KEYRELEASE_MASK) {
    338 	    _XUnregisterFilter (ic->core.im->core.display,
    339 				ic->core.focus_window,
    340 				_XimFilterKeyrelease,
    341 				(XPointer)ic);
    342 	    _XUnregisterFilter (ic->core.im->core.display,
    343 				0,
    344 				_XimFilterKeyrelease,
    345 				(XPointer)ic);
    346 	    ic->private.proto.registed_filter_event &= ~KEYRELEASE_MASK;
    347 	}
    348     }
    349     return;
    350 }
    351 
    352 void
    353 _XimRegisterFilter(
    354     Xic		 ic)
    355 {
    356     _XimRegisterKeyPressFilter(ic);
    357     if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
    358 	_XimRegisterKeyReleaseFilter(ic);
    359     return;
    360 }
    361 
    362 void
    363 _XimUnregisterFilter(
    364     Xic		 ic)
    365 {
    366     Xim		 im = (Xim)ic->core.im;
    367     _XimUnregisterKeyPressFilter(ic);
    368     _XimUnregisterKeyReleaseFilter(ic);
    369     /* It is possible that the event from IM is received after unregister
    370      * the filter.
    371      * Reset any existing fabricated state since we will not be able to
    372      * clear the fabricated state for those event in filter.
    373      */
    374     im->private.proto.fabricated_serial = 0;
    375     im->private.proto.fabricated_time = 0;
    376     UNMARK_FABRICATED(im);
    377     _XimPendingFilter(ic);
    378     return;
    379 }
    380 
    381 void
    382 _XimReregisterFilter(
    383     Xic		 ic)
    384 {
    385     if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
    386 	_XimRegisterKeyReleaseFilter(ic);
    387     else
    388 	_XimUnregisterKeyReleaseFilter(ic);
    389 
    390     return;
    391 }
    392 
    393 static Bool
    394 _XimFilterServerDestroy(
    395     Display		*d,
    396     Window		 w,
    397     XEvent		*ev,
    398     XPointer		 client_data)
    399 {
    400     Xim			 im = (Xim)client_data;
    401 
    402     if (ev->type == DestroyNotify) {
    403 	UNMARK_SERVER_CONNECTED(im);
    404 #ifdef XIM_CONNECTABLE
    405 	if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
    406 	    _XimServerReconectableDestroy();
    407 	    return True;
    408 	}
    409 #endif /* XIM_CONNECTABLE */
    410 	_XimServerDestroy(im);
    411     }
    412     return True;
    413 }
    414 
    415 void
    416 _XimRegisterServerFilter(
    417     Xim		 im)
    418 {
    419     if (im->private.proto.im_window) {
    420 	if (!(im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK)) {
    421 	    _XRegisterFilterByMask(im->core.display,
    422 		    im->private.proto.im_window,
    423 		    StructureNotifyMask,
    424 		    _XimFilterServerDestroy,
    425 		    (XPointer)im);
    426 	    XSelectInput(im->core.display, im->private.proto.im_window,
    427 			 StructureNotifyMask);
    428 	    im->private.proto.registed_filter_event |= DESTROYNOTIFY_MASK;
    429 	}
    430     }
    431     return;
    432 }
    433 
    434 void
    435 _XimUnregisterServerFilter(
    436     Xim		 im)
    437 {
    438     if (im->private.proto.im_window) {
    439 	if (im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK) {
    440 	    _XUnregisterFilter(im->core.display,
    441 		    im->private.proto.im_window,
    442 		    _XimFilterServerDestroy,
    443 		    (XPointer)im);
    444 	    im->private.proto.registed_filter_event &= ~DESTROYNOTIFY_MASK;
    445 	}
    446     }
    447     return;
    448 }
    449 
    450