📄 evt.c
字号:
destroyNotify ( JNIEnv* env, Toolkit* tk ){ /* * We should get this just for windows which have been destroyed from an * external client, since removeNotify() calls evtUnregisterSource() (i.e. * removes windows properly from the dispatch table) */ tk->windows[tk->srcIdx].flags &= ~WND_MAPPED; return (*env)->CallStaticObjectMethod( env, WMEvent, getWMEvent, tk->srcIdx, (tk->evtId = WM_KILLED));}static jobjectmapNotify ( JNIEnv* env, Toolkit* tk ){ int id = 0; if ( tk->event.xany.type == MapNotify ) { if ( (tk->windows[tk->srcIdx].flags & WND_MAPPED) == 0 ){ id = WINDOW_DEICONIFIED; tk->windows[tk->srcIdx].flags |= WND_MAPPED; } } else { if ( (tk->windows[tk->srcIdx].flags & WND_MAPPED) != 0 ){ id = WINDOW_ICONIFIED; tk->windows[tk->srcIdx].flags &= ~WND_MAPPED; } } if ( id ) { return (*env)->CallStaticObjectMethod( env, WindowEvent, getWindowEvent, tk->srcIdx, id); } else { /* we do the ComponentEvent show/hide in Java */ return 0; }}static jobjectconfigureNotify ( JNIEnv* env, Toolkit* tk ){ Window child; int x, y, w, h; /* * some window managers are rather loquacious when doing opaque moves */ while ( XCheckTypedWindowEvent( tk->dsp, tk->event.xany.window, ConfigureNotify, &tk->event) ){ tk->pending--; } if ( (tk->event.xconfigure.x == 0) && (tk->event.xconfigure.y == 0) ) { XTranslateCoordinates( tk->dsp, tk->event.xconfigure.window, DefaultRootWindow( tk->dsp), tk->event.xconfigure.x, tk->event.xconfigure.y, &tk->event.xconfigure.x, &tk->event.xconfigure.y, &child); } x = tk->event.xconfigure.x; y = tk->event.xconfigure.y; w = tk->event.xconfigure.width; h = tk->event.xconfigure.height; X->evtId = COMPONENT_RESIZED; return (*env)->CallStaticObjectMethod( env, ComponentEvent, getComponentEvent, tk->srcIdx, tk->evtId, x, y, w, h);}static jobjectclientMessage ( JNIEnv* env, Toolkit* tk ){ if ( tk->windows[tk->srcIdx].flags & WND_DESTROYED ){ /* we lost him, Jim */ return 0; } if ( tk->event.xclient.message_type == WM_PROTOCOLS ) { if ( tk->event.xclient.data.l[0] == WM_DELETE_WINDOW ) { return (*env)->CallStaticObjectMethod( env, WindowEvent, getWindowEvent, tk->srcIdx, (tk->evtId = WINDOW_CLOSING)); } else if ( tk->event.xclient.data.l[0] == WM_TAKE_FOCUS ) { XSetInputFocus( tk->dsp, tk->event.xany.window, RevertToParent, CurrentTime); } } /* * This is a workaround for the common problem of requesting the focus for not * yet mapped windows (resulting in BadMatch errors) */ else if ( tk->event.xclient.message_type == RETRY_FOCUS ) { if ( tk->windows[tk->srcIdx].flags & WND_MAPPED ) { XSetInputFocus( tk->dsp, tk->event.xclient.window, RevertToParent, CurrentTime); if ( tk->event.xclient.data.l[1] ) { /* we have a pending forward request, too */ forwardFocus( FWD_SET, tk->event.xclient.data.l[1]); } } } /* * This is a workaround for X not having "owned" windows (popups), which do * not "shade" the titlebar of their owner (i.e. don't indicate a change in * the activeWindow). The only way to implement this reliable (w/o playing * around with a window manager) is to not let these popups select on * key events at all. But rather than to expose this to the Java side (like * the JDK does), we hide this in the native layer */ else if ( tk->event.xclient.message_type == FORWARD_FOCUS ) { switch ( tk->event.xclient.data.l[0] ){ case FWD_SET: DBG( AWT_EVT, printf("FWD_SET: %lx (%d) %lx\n", tk->event.xany.window, tk->srcIdx, tk->windows[tk->srcIdx].owner)); if ( (tk->srcIdx != tk->fwdIdx) && (tk->focus == tk->windows[tk->srcIdx].owner) ){ tk->fwdIdx = tk->srcIdx; tk->focusFwd = tk->event.xany.window; return (*env)->CallStaticObjectMethod( env, FocusEvent, getFocusEvent, tk->srcIdx, FOCUS_GAINED, JNI_TRUE); } else { return 0; } case FWD_CLEAR: DBG( AWT_EVT, printf("FWD_CLEAR: %lx (%d) %lx\n", tk->event.xany.window, tk->srcIdx, tk->windows[tk->srcIdx].owner)); if ( tk->fwdIdx >= 0 ) { resetFocusForwarding( tk); return (*env)->CallStaticObjectMethod( env, FocusEvent, getFocusEvent, tk->srcIdx, FOCUS_LOST, JNI_FALSE); } else { return 0; } case FWD_REVERT: DBG( AWT_EVT, printf("FWD_REVERT: %lx\n", tk->event.xany.window)); if ( tk->event.xany.window == tk->focus ) { resetFocusForwarding( tk); return (*env)->CallStaticObjectMethod( env, FocusEvent, getFocusEvent, tk->srcIdx, FOCUS_GAINED, JNI_FALSE); } } } return 0;}static jobjectreparentNotify ( JNIEnv* env, Toolkit* tk ){ Window window, parent, root; jclass clazz = 0; jmethodID setDecoInsets = 0; int left, top, right, bottom; int x, y, w, h, bw, d; int xc, yc, wc, hc; DecoInset *in = 0; XSizeHints wmHints; long supHints; if ( tk->frameInsets.guess || tk->dialogInsets.guess ) { window = tk->event.xreparent.window; parent = tk->event.xreparent.parent; XGetGeometry( tk->dsp, parent, &root, &x, &y, &w, &h, &bw, &d); XGetGeometry( tk->dsp, window, &root, &xc, &yc, &wc, &hc, &bw, &d); left = tk->event.xreparent.x; top = tk->event.xreparent.y; right = w - wc - left; bottom = h - hc - top; if ( (tk->windows[tk->srcIdx].flags & WND_DIALOG) && tk->dialogInsets.guess ) { in = &(tk->dialogInsets); if ( (left != in->left) || (top != in->top) || (right != in->right) || (bottom != in->bottom) ){ clazz = (*env)->FindClass( env, "java/awt/Dialog"); setDecoInsets = (*env)->GetStaticMethodID( env, clazz, "setDecoInsets","(IIIII)V"); } in->guess = 0; } else if ( tk->frameInsets.guess ) { in = &(tk->frameInsets); if ( (left != in->left) || (top != in->top) || (right != in->right) || (bottom != in->bottom) ){ clazz = (*env)->FindClass( env, "java/awt/Frame"); setDecoInsets = (*env)->GetStaticMethodID( env, clazz, "setDecoInsets","(IIIII)V"); } in->guess = 0; } if ( clazz ) { wc -= (left + right) - (in->left + in->right); hc -= (top + bottom) - (in->top + in->bottom); XCheckTypedWindowEvent( tk->dsp, window, ConfigureNotify, &X->event); XCheckTypedWindowEvent( tk->dsp, window, Expose, &X->event); XResizeWindow( tk->dsp, window, wc, hc); in->left = left; in->top = top; in->right = right; in->bottom = bottom; (*env)->CallStaticVoidMethod( env, clazz, setDecoInsets, in->top, in->left, in->bottom, in->right, tk->srcIdx); /* check if this was a resize locked window (which has to be locked again) */ XGetWMNormalHints( tk->dsp, window, &wmHints, &supHints); if ( wmHints.min_width == wmHints.max_width ){ wmHints.min_width = wmHints.max_width = wc; wmHints.min_height = wmHints.max_height = hc; XSetWMNormalHints( tk->dsp, window, &wmHints); } } } return NULL;}typedef jobject (*EventFunc)(JNIEnv*,Toolkit*);static EventFunc processEvent[LASTEvent] = { skip, skip, /* 0, 1 are reserved by X */ keyNotify, /* KeyPress 2 */ keyNotify, /* KeyRelease 3 */ buttonNotify, /* ButtonPress 4 */ buttonNotify, /* ButtonRelease 5 */ motionNotify, /* MotionNotify 6 */ mouseNotify, /* EnterNotify 7 */ mouseNotify, /* LeaveNotify 8 */ focusNotify, /* FocusIn 9 */ focusNotify, /* FocusOut 10 */ skip, /* KeymapNotify 11 */ expose, /* Expose 12 */ skip, /* GraphicsExpose 13 */ skip, /* NoExpose 14 */ skip, /* VisibilityNotify 15 */ skip, /* CreateNotify 16 */ destroyNotify, /* DestroyNotify 17 */ mapNotify, /* UnmapNotify 18 */ mapNotify, /* MapNotify 19 */ skip, /* MapRequest 20 */ reparentNotify, /* ReparentNotify 21 */ configureNotify, /* ConfigureNotify 22 */ skip, /* ConfigureRequest 23 */ skip, /* GravityNotify 24 */ skip, /* ResizeRequest 25 */ skip, /* CirculateNotify 26 */ skip, /* CirculateRequest 27 */ skip, /* PropertyNotify 28 */ selectionClear, /* SelectionClear 29 */ selectionRequest, /* SelectionRequest 30 */ skip, /* SelectionNotify 31 */ skip, /* ColormapNotify 32 */ clientMessage, /* ClientMessage 33 */ skip /* MappingNotify 34 */};/******************************************************************************* * */jobjectJava_java_awt_Toolkit_evtInit ( JNIEnv* env, jclass clazz UNUSED ){ jclass Component;#if !defined(USE_POLLING_AWT) unsigned long mask; XSetWindowAttributes attrs;#endif if ( ComponentEvent != NULL ){ DBG( AWT_EVT, printf("evtInit called twice\n")); return NULL; } ComponentEvent = (*env)->FindClass( env, "java/awt/ComponentEvt"); assert(ComponentEvent != NULL); MouseEvent = (*env)->FindClass( env, "java/awt/MouseEvt"); assert(MouseEvent != NULL); FocusEvent = (*env)->FindClass( env, "java/awt/FocusEvt"); assert(FocusEvent != NULL); WindowEvent = (*env)->FindClass( env, "java/awt/WindowEvt"); assert(WindowEvent != NULL); KeyEvent = (*env)->FindClass( env, "java/awt/KeyEvt"); assert(KeyEvent != NULL); PaintEvent = (*env)->FindClass( env, "java/awt/PaintEvt"); assert(PaintEvent != NULL); WMEvent = (*env)->FindClass( env, "java/awt/WMEvent"); assert(WMEvent != NULL); getComponentEvent = (*env)->GetStaticMethodID( env, ComponentEvent, "getEvent", "(IIIIII)Ljava/awt/ComponentEvt;"); getMouseEvent = (*env)->GetStaticMethodID( env, MouseEvent, "getEvent", "(IIIII)Ljava/awt/MouseEvt;"); getFocusEvent = (*env)->GetStaticMethodID( env, FocusEvent, "getEvent", "(IIZ)Ljava/awt/FocusEvt;"); getWindowEvent = (*env)->GetStaticMethodID( env, WindowEvent, "getEvent", "(II)Ljava/awt/WindowEvt;"); getKeyEvent = (*env)->GetStaticMethodID( env, KeyEvent, "getEvent", "(IIIII)Ljava/awt/KeyEvt;"); getPaintEvent = (*env)->GetStaticMethodID( env, PaintEvent, "getEvent", "(IIIIII)Ljava/awt/PaintEvt;"); getWMEvent = (*env)->GetStaticMethodID( env, WMEvent, "getEvent", "(II)Ljava/awt/WMEvent;");#if !defined(USE_POLLING_AWT) /* * we need a target for evtWakeup(), which is used to unblock nextEvent() in * case we post a event to the localqueue */ mask = CWEventMask; attrs.override_redirect = True; attrs.event_mask = StructureNotifyMask; X->wakeUp = XCreateWindow( X->dsp, X->root, -1000, -1000, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attrs); /* * make X connection non-blocking (to get SIGIOs) * NOTE: this requires all Xlib calls doing IO via the X conn to be synced! In addition, * no Xlib function doing blocked reads on the connection should be called without * ensuring that there is input available. */#if defined (UNIX_JTHREADS) jthreadedFileDescriptor( ConnectionNumber(X->dsp));#elif defined (UNIX_PTHREADS) FD_ZERO( &X->rfds); FD_SET( ConnectionNumber(X->dsp), &X->rfds);#endif#endif /* !USE_POLLING_AWT */ Component = (*env)->FindClass( env, "java/awt/Component"); return (*env)->NewObjectArray( env, X->nWindows, Component, NULL);}jobjectJava_java_awt_Toolkit_evtGetNextEvent ( JNIEnv* env, jclass clazz ){ jobject jEvt = NULL; DBG( AWT_EVT, printf("getNextEvent..\n")); while ( nextEvent( env, clazz, X, True) && ((getSourceIdx( X, X->event.xany.window) >= 0) || (X->event.xany.window == X->cbdOwner)) ) { X->preFetched = 0; if ( (jEvt = (processEvent[X->event.xany.type])( env, X)) ){ break; } } DBG( AWT_EVT, printf("..getNextEvent: %d (%s) %d, %p, %lx\n", X->evtId, eventStr( X->evtId), X->srcIdx, jEvt, X->event.xany.window)); return jEvt;}jobjectJava_java_awt_Toolkit_evtPeekEvent ( JNIEnv* env, jclass clazz ){ jobject jEvt = NULL; DBG( AWT_EVT, printf("peekEvent..\n")); if ( nextEvent( env, clazz, X, False) && ((getSourceIdx( X, X->event.xany.window) >= 0)) ) { if ( (jEvt = (processEvent[X->event.xany.type])( env, X)) ) X->preFetched = 1; } DBG( AWT_EVT, printf("..peekEvent: %s %p, %lx\n", eventStr(X->evtId), jEvt, X->event.xany.window)); return jEvt;}/* * We can't do a XPeekIfEvent here because it would block until such an event * comes in */jobjectJava_java_awt_Toolkit_evtPeekEventId ( JNIEnv* env, jclass clazz, jint id ){ jobject jEvt; if ( (jEvt = Java_java_awt_Toolkit_evtPeekEvent( env, clazz)) && (X->evtId == id) ){ return jEvt; } return NULL;}/* * This is just used to wakeup the getNextEvent call if we are multithreaded, * and we post an event from outside the dispatcher thread (which might be blocked * in a native getNextEvent). This is a tribute to the fact that we actually have * two different queues - the native one, and the queue for self-posted events. * We could also do a round trip here, but this would wake up the event dispatcher * immediately (i.e. before this func returns), which is probably a crude side effect * of postEvent(). * Using a ClientMessage might be a bit dangerous if Xlib tries to be too smart by * just dispatching this to the local queue (without passing to the server) */voidJava_java_awt_Toolkit_evtWakeup ( JNIEnv* env UNUSED, jclass clazz UNUSED ){ XEvent event; DBG( AWT_EVT, printf("evtWakeup\n")); DBG_ACTION( awt, XSynchronize( X->dsp, False)); event.xclient.type = ClientMessage; event.xclient.message_type = WAKEUP; event.xclient.format = 8; event.xclient.window = X->wakeUp; XSendEvent( X->dsp, X->wakeUp, False, 0, &event); XFlush( X->dsp); DBG_ACTION( awt, XSynchronize( X->dsp, True));}/* * This is a helper for (IS_DISPATCH_EXCLUSIVE | NATIVE_DISPATCHER_LOOP) windowing * systems, where we need to execute certain requests (e.g. window creation) to * the native event thread. Not required here */voidJava_java_awt_Toolkit_evtSendWMEvent ( JNIEnv* env UNUSED, jclass clazz UNUSED, jobject wmEvt UNUSED ){}jintJava_java_awt_Toolkit_evtRegisterSource ( JNIEnv* env UNUSED, jclass clazz UNUSED, jobject nativeWnd ){ Window wnd = UNVEIL_WND(nativeWnd); /* * We have done that already during the various wndCreateXX() */ int i = getSourceIdx( X, wnd); DBG( AWT_EVT, printf("registerSource( %lx) -> %d\n", wnd, i)); return i;}jintJava_java_awt_Toolkit_evtUnregisterSource ( JNIEnv* env UNUSED, jclass clazz UNUSED, jobject nativeWnd ){ Window wnd = UNVEIL_WND(nativeWnd); int i = getSourceIdx( X, wnd); if ( i >= 0 ){ X->windows[i].w = -1; X->windows[i].flags = 0; X->windows[i].owner = 0; } if ( X->lastWindow == wnd ) X->lastWindow = 0; DBG( AWT_EVT, printf("unregisterSource( %lx) -> %d\n", wnd, i)); return i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -