📄 evt.c
字号:
/** * evt.c - * * Copyright (c) 1998 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include "toolkit.h"#include "keysyms.h"#include "jcl.h"#if !defined (USE_POLLING_AWT)#include "jsyscall.h"#include "locks.h"#if defined(UNIX_JTHREADS)void jthreadedBlockEAGAIN(int fd); /* move to SysCallInterface ? */int jthreadedFileDescriptor(int fd);#endif#endif /* !USE_POLLING_AWT *//******************************************************************************* * */static int nextEvent ( JNIEnv* env UNUSED, jclass clazz UNUSED, Toolkit *tk, int blockIt UNUSED ){ if ( tk->preFetched ) return 1;#if !defined(USE_POLLING_AWT) && !defined(SUN_AWT_FIX) /* * We can't use QueuedAfterFlush since it seems to rely on blocked IO. At least * XFree86-3.3.2 subsequently hangs in _XFlushInt. This is the weak point of * our multithreaded X support, which depends on the Xlib in use */ if ( blockIt ) { /* this is from a getNextEvent */ while ( tk->pending <= 0 ) { XFlush( tk->dsp); if ( (tk->pending = XEventsQueued( tk->dsp, QueuedAlready)) == 0 ) { tk->blocking = 1; /* Note that we might get blocked here, but we still have the Toolkit.class * lock. Since the new locking interface requires locks to occur symmetrical * inside of the same stack frame, we have to backup to some VM specific * functionality, here. */#if defined (UNIX_JTHREADS) UNBLOCK_EXECUTE( clazz, (jthreadedBlockEAGAIN( ConnectionNumber( tk->dsp))));#elif defined (UNIX_PTHREADS) /* * Even with pthreads, don't simply do a XNextEvent, because we most probably * would get "unexpected async replies" X errors when doing roundtrips (e.g. * direct or indirect XSyncs) from other threads while still being blocked in * XNextEvent, here. The only thing done outside the Toolkit lock should be * to check availability of X input */ { int stat; do { UNBLOCK_EXECUTE( clazz, (stat =select( ConnectionNumber(tk->dsp)+1, &tk->rfds, NULL,NULL,NULL))); } while ( stat != 1 ); }#endif /* * getting here just means we got input, it doesn't mean we have events. It also * doesn't mean there currently is no other thread doing X requests */ tk->blocking = 0; tk->pending = XEventsQueued( tk->dsp, QueuedAfterReading); } } } else { /* this is from a peekEvent */ if ( tk->blocking ){ /* nothing to expect, there is a pending getNextEvent */ return 0; } if ( tk->pending <= 0 ) { XFlush( tk->dsp); if ( (tk->pending = XEventsQueued( tk->dsp, QueuedAlready)) == 0 ){ return 0; } } }#else /* USE_POLLING_AWT */ /* * We need to use this one for Solaris. We have problems trying to unblock the * AWT thread off the X server connection. */ if ( tk->pending <= 0 ) { if ( (tk->pending = XEventsQueued( tk->dsp, QueuedAfterFlush)) == 0 ) return 0; }#endif /* !USE_POLLING_AWT */ XNextEvent( tk->dsp, &tk->event); tk->pending--; return 1;}/* X-to-Java key modifier mapping * altGr : PC * shift - ctrl alt meta : Java * Shift Lock Ctrl Mod1 Mod3 : X symbol * ---------------------------------------------------------- * 1 1 2 8 4 : Java value * 1 2 4 8 32 : X */static inline int keyMod ( int keyState ){ int mod = 0; if ( keyState & 3 ) mod |= 1; /* shift or lock */ if ( keyState & 4 ) mod |= 2; if ( keyState & 8 ) mod |= 8; return mod;}jclass AWTEvent;jclass ComponentEvent;jclass MouseEvent;jclass FocusEvent;jclass WindowEvent;jclass KeyEvent;jclass PaintEvent;jclass WMEvent;jmethodID getComponentEvent;jmethodID getMouseEvent;jmethodID getFocusEvent;jmethodID getWindowEvent;jmethodID getKeyEvent;jmethodID getPaintEvent;jmethodID getWMEvent;#define COMPONENT_RESIZED 101#define WINDOW_CLOSING 201#define WINDOW_CLOSED 202#define WINDOW_ICONIFIED 203#define WINDOW_DEICONIFIED 204#define KEY_PRESSED 401#define KEY_RELEASED 402#define MOUSE_PRESSED 501#define MOUSE_RELEASED 502#define MOUSE_MOVED 503#define MOUSE_ENTERED 504#define MOUSE_EXITED 505#define PAINT 800#define UPDATE 801#define FOCUS_GAINED 1004#define FOCUS_LOST 1005#define WM_KILLED 1905#if defined(KAFFE_VMDEBUG) && !defined(NDEBUG)static const char *eventStr ( int evtId ){ switch (evtId) { case COMPONENT_RESIZED: return "ComponentResized"; case WINDOW_CLOSING: return "WindowClosing"; case WINDOW_CLOSED: return "WindowClosed"; case WINDOW_ICONIFIED: return "WindowIconified"; case WINDOW_DEICONIFIED: return "WindowDeiconified"; case KEY_PRESSED: return "KeyPressed"; case KEY_RELEASED: return "KeyReleased"; case MOUSE_PRESSED: return "MousePressed"; case MOUSE_RELEASED: return "MouseReleased"; case MOUSE_MOVED: return "MouseMoved"; case MOUSE_ENTERED: return "MouseEntered"; case MOUSE_EXITED: return "MouseExited"; case PAINT: return "Paint"; case UPDATE: return "Update"; case FOCUS_GAINED: return "FocusGained"; case FOCUS_LOST: return "FocusLost"; case WM_KILLED: return "WMKilled"; default: return "<unknown>"; }};#endif /* defined(KAFFE_VMDEBUG) && !defined(NDEBUG) */static jobjectskip ( JNIEnv* env UNUSED, Toolkit* tk UNUSED ){ return NULL;}static jobjectkeyNotify ( JNIEnv* env, Toolkit* tk ){ KeySym keysym; KeySym keysym2; XComposeStatus ioStatus; int n, keyCode, keyChar, mod, idx, nchar; /* * We should eventually support input methods here. * Note that 'keysym' is queried separately (with a standard state), to * ensure the "one physical key -> one keycode" invariant */ n = XLookupString( &tk->event.xkey, tk->buf, tk->nBuf, &keysym2, &ioStatus); keysym = XKeycodeToKeysym( tk->dsp, tk->event.xkey.keycode, 0); /* Bug fix: the keypad numbers where not handled correctly. * In X, numlock is a modifier, and XKeycodeToKeysym do * not do any modifier interpretation (in order to * build the correct Java KeyEvent). * But, as a result, since there is no NumLock modifier * in Java, the information was lost, and the keypad could * not work with NumLock selected. * The "solution" is to use the returned keysym from XLookupString * (which interpret the modifiers) if and only if it * the original keysym correspond to the keypad; this should * code will all the case where the numlock alter the interpretation * of the keypad; also, if the keysums are the xk_xp_<num> * we set the keychar to the correspoding digit. */ if ((keysym >= XK_KP_Space) && (keysym <= XK_KP_9)) { keysym = keysym2; switch (keysym) { case XK_KP_Multiply: nchar = '*'; break; case XK_KP_Add: nchar = '+'; break; case XK_KP_Separator: nchar = ','; break; case XK_KP_Subtract: nchar = '-'; break; case XK_KP_Decimal: nchar = '.'; break; case XK_KP_Divide: nchar = '/'; break; case XK_KP_0: nchar = '0'; break; case XK_KP_1: nchar = '1'; break; case XK_KP_2: nchar = '2'; break; case XK_KP_3: nchar = '3'; break; case XK_KP_4: nchar = '4'; break; case XK_KP_5: nchar = '5'; break; case XK_KP_6: nchar = '6'; break; case XK_KP_7: nchar = '7'; break; case XK_KP_8: nchar = '8'; break; case XK_KP_9: nchar = '9'; break; default: nchar = -1; break; } } else nchar = -1; if ( (keysym >= 0xff00) || (n == 0) ) { keyCode = FKeyCode[keysym & 0xff]; /* * There are some "control keys" that should generate KEY_TYPED events * (enter, cancel, backspace, del, tab). This is flagged by a negative keyCode * value and leads to non-zero keyChars */ if ( keyCode < 0 ){ keyChar = keyCode = -keyCode; } else if (nchar >= 0) { keyChar = nchar; } else { /* a "pure" function key */ keyChar = 0; } } else { keyChar = (unsigned char)X->buf[0]; keyCode = LKeyCode[keysym & 0xff]; } tk->evtId = (tk->event.xany.type == KeyPress)? KEY_PRESSED : KEY_RELEASED; mod = keyMod( tk->event.xkey.state); if ( tk->fwdIdx >= 0 ) { /* * watch out - we still might have key events for a already * unregistered forwardee in the queue (since we fake X, we can't rely on it * to remove key events for a destroyed forwardee) */ if ( !checkSource( tk, tk->fwdIdx) ) return 0; idx = tk->fwdIdx; } else { idx = tk->srcIdx; } return (*env)->CallStaticObjectMethod( env, KeyEvent, getKeyEvent, idx, tk->evtId, keyCode, keyChar, mod);}static jobjectbuttonNotify ( JNIEnv* env, Toolkit* tk ){ if ( tk->event.xany.type == ButtonPress ) { tk->evtId = MOUSE_PRESSED; if ( (tk->windows[tk->srcIdx].w == tk->focus) && (tk->fwdIdx >= 0) ) forwardFocus( FWD_REVERT, tk->event.xany.window); } else { tk->evtId = MOUSE_RELEASED; } return (*env)->CallStaticObjectMethod( env, MouseEvent, getMouseEvent, tk->srcIdx, tk->evtId, tk->event.xbutton.button, tk->event.xbutton.x, tk->event.xbutton.y);}static jobjectmotionNotify ( JNIEnv* env, Toolkit* tk ){ return (*env)->CallStaticObjectMethod( env, MouseEvent, getMouseEvent, tk->srcIdx, (tk->evtId = MOUSE_MOVED), 0, tk->event.xmotion.x, tk->event.xmotion.y);}static jobjectmouseNotify ( JNIEnv* env, Toolkit* tk ){ tk->evtId = (tk->event.xany.type == EnterNotify) ? MOUSE_ENTERED : MOUSE_EXITED; return (*env)->CallStaticObjectMethod( env, MouseEvent, getMouseEvent, tk->srcIdx, tk->evtId, 0, tk->event.xcrossing.x, tk->event.xcrossing.y);}static jobjectfocusNotify ( JNIEnv* env, Toolkit* tk ){ int et = tk->event.xany.type; int idx = (tk->focusFwd) ? tk->fwdIdx : tk->srcIdx; /* * get rid of all these fancy intermediate focus events (the real thing should * come last), but be aware of that we might get events for already unregistered windows * (in case the app isn't particulary careful with disposing windows), ending up in * ArrayOutOfBoundsExceptions in the getFocusEvent */ while ( XCheckMaskEvent( tk->dsp, FocusChangeMask, &tk->event) ){ tk->pending--; if ( getSourceIdx( tk, tk->event.xfocus.window) >= 0 ) { et = tk->event.xany.type; idx = (tk->focusFwd) ? tk->fwdIdx : tk->srcIdx; } } if ( et == FocusIn ) { tk->evtId = FOCUS_GAINED; tk->focus = tk->event.xany.window; } else { tk->evtId = FOCUS_LOST; tk->focus = 0; } /* * No matter what the focus change is - if we get a REAL focus notification, * it means that we will end focus forwarding (which is done on the owner-basis, * not by means of a global grab mode) */ resetFocusForwarding( tk); if ( checkSource( tk, idx) ){ return (*env)->CallStaticObjectMethod( env, FocusEvent, getFocusEvent, idx, tk->evtId, JNI_FALSE); } else { return 0; }}static jobjectexpose ( JNIEnv* env, Toolkit* tk ){ Window wnd = tk->event.xany.window; int x = tk->event.xexpose.x; int y = tk->event.xexpose.y; int w = tk->event.xexpose.width; int h = tk->event.xexpose.height; int xw, yh, exw, eyh; while ( XCheckWindowEvent( tk->dsp, wnd, ExposureMask | StructureNotifyMask, &tk->event) ){ tk->pending--; if ( tk->event.xany.type == Expose ) { xw = x + w; yh = y + h; exw = tk->event.xexpose.x + tk->event.xexpose.width; eyh = tk->event.xexpose.y + tk->event.xexpose.height; if ( tk->event.xexpose.x < x ) x = tk->event.xexpose.x; if ( tk->event.xexpose.y < y ) y = tk->event.xexpose.y; w = (exw > xw) ? exw - x : xw - x; h = (eyh > yh) ? eyh - y : yh - y; } else { tk->preFetched = 1; break; } } return (*env)->CallStaticObjectMethod( env, PaintEvent, getPaintEvent, tk->srcIdx, (tk->evtId = UPDATE), x, y, w, h);}static jobject
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -