/* * X events handling functions * * Copyright 1993 Alexandre Julliard */ static char Copyright[] = "Copyright Alexandre Julliard, 1993"; #include #include #include #include #include #include "windows.h" #include "win.h" #include "class.h" #include "message.h" #ifndef FamilyAmoeba typedef char *XPointer; #endif #define NB_BUTTONS 3 /* Windows can handle 3 buttons */ extern int desktopX, desktopY; /* misc/main.c */ extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/ /* X context to associate a hwnd to an X window */ static XContext winContext = 0; /* State variables */ BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE }; static WORD ALTKeyState; static HWND captureWnd = 0; Window winHasCursor = 0; /* Keyboard translation tables */ static int special_key[] = { VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */ 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */ 0, 0, 0, VK_ESCAPE /* FF18 */ }; static cursor_key[] = { VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END /* FF50 */ }; static misc_key[] = { VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */ VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */ }; static keypad_key[] = { VK_MENU, VK_NUMLOCK, /* FF7E */ 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */ 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */ 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */ 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */ 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */ 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE, /* FFA8 */ VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */ VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */ }; static function_key[] = { VK_F1, VK_F2, /* FFBE */ VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */ VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */ }; static modifier_key[] = { VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, 0, /* FFE1 */ 0, VK_MENU, VK_MENU /* FFE8 */ }; typedef union { struct { unsigned long count : 16; unsigned long code : 8; unsigned long extended : 1; unsigned long : 4; unsigned long context : 1; unsigned long previous : 1; unsigned long transition : 1; } lp1; unsigned long lp2; } KEYLP; static BOOL KeyDown = FALSE; #ifdef DEBUG_EVENT static char *event_names[] = { "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify" }; #endif /* Event handlers */ static void EVENT_key( HWND hwnd, XKeyEvent *event ); static void EVENT_ButtonPress( XButtonEvent *event ); static void EVENT_ButtonRelease( XButtonEvent *event ); static void EVENT_MotionNotify( XMotionEvent *event ); static void EVENT_EnterNotify( XCrossingEvent *event ); static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event ); static void EVENT_Expose( HWND hwnd, XExposeEvent *event ); static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event ); /*********************************************************************** * EVENT_ProcessEvent * * Process an X event. */ void EVENT_ProcessEvent( XEvent *event ) { HWND hwnd; XPointer ptr; XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr ); hwnd = (HWND) (int)ptr; #ifdef DEBUG_EVENT printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd ); #endif switch(event->type) { case KeyPress: case KeyRelease: EVENT_key( hwnd, (XKeyEvent*)event ); break; case ButtonPress: EVENT_ButtonPress( (XButtonEvent*)event ); break; case ButtonRelease: EVENT_ButtonRelease( (XButtonEvent*)event ); break; case MotionNotify: EVENT_MotionNotify( (XMotionEvent*)event ); break; case EnterNotify: EVENT_EnterNotify( (XCrossingEvent*)event ); break; case FocusOut: EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event ); break; case Expose: EVENT_Expose( hwnd, (XExposeEvent*)event ); break; case ConfigureNotify: EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event ); break; #ifdef DEBUG_EVENT default: printf( "Unprocessed event %s for hwnd %d\n", event_names[event->type], hwnd ); break; #endif } } /*********************************************************************** * EVENT_RegisterWindow * * Associate an X window to a HWND. */ void EVENT_RegisterWindow( Window w, HWND hwnd ) { if (!winContext) winContext = XUniqueContext(); XSaveContext( display, w, winContext, (XPointer)(int)hwnd ); } /*********************************************************************** * EVENT_XStateToKeyState * * Translate a X event state (Button1Mask, ShiftMask, etc...) to * a Windows key state (MK_SHIFT, MK_CONTROL, etc...) */ static WORD EVENT_XStateToKeyState( int state ) { int kstate = 0; if (state & Button1Mask) kstate |= MK_LBUTTON; if (state & Button2Mask) kstate |= MK_MBUTTON; if (state & Button3Mask) kstate |= MK_RBUTTON; if (state & ShiftMask) kstate |= MK_SHIFT; if (state & ControlMask) kstate |= MK_CONTROL; return kstate; } /*********************************************************************** * EVENT_Expose */ static void EVENT_Expose( HWND hwnd, XExposeEvent *event ) { RECT rect; UINT flags; WND * wndPtr = WIN_FindWndPtr( hwnd ); if (!wndPtr) return; /* Make position relative to client area instead of window */ rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left); rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top); rect.right = rect.left + event->width; rect.bottom = rect.top + event->height; winHasCursor = event->window; flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME; /* Erase desktop background synchronously */ if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN; RedrawWindow( hwnd, &rect, 0, flags ); } /*********************************************************************** * EVENT_key * * Handle a X key event */ static void EVENT_key( HWND hwnd, XKeyEvent *event ) { char Str[24]; XComposeStatus cs; KeySym keysym; WORD xkey, vkey, key_type, key; KEYLP keylp; BOOL extended = FALSE; int count = XLookupString(event, Str, 1, &keysym, &cs); Str[count] = '\0'; #ifdef DEBUG_KEY printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n", keysym, count, Str[0], Str); #endif xkey = LOWORD(keysym); key_type = HIBYTE(xkey); key = LOBYTE(xkey); #ifdef DEBUG_KEY printf(" key_type=%X, key=%X\n", key_type, key); #endif if (key_type == 0xFF) /* non-character key */ { if (key >= 0x08 && key <= 0x1B) /* special key */ vkey = special_key[key - 0x08]; else if (key >= 0x50 && key <= 0x57) /* cursor key */ vkey = cursor_key[key - 0x50]; else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */ vkey = misc_key[key - 0x60]; else if (key >= 0x7E && key <= 0xB9) /* keypad key */ { vkey = keypad_key[key - 0x7E]; extended = TRUE; } else if (key >= 0xBE && key <= 0xCD) /* function key */ { vkey = function_key[key - 0xBE]; extended = TRUE; } else if (key >= 0xE1 && key <= 0xEA) /* modifier key */ vkey = modifier_key[key - 0xE1]; else if (key == 0xFF) /* DEL key */ vkey = VK_DELETE; } else if (key_type == 0) /* character key */ { if (key >= 0x61 && key <= 0x7A) vkey = key - 0x20; /* convert lower to uppercase */ else vkey = key; } if (event->type == KeyPress) { if (vkey == VK_MENU) ALTKeyState = TRUE; keylp.lp1.count = 1; keylp.lp1.code = LOBYTE(event->keycode); keylp.lp1.extended = (extended ? 1 : 0); keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0); keylp.lp1.previous = (KeyDown ? 0 : 1); keylp.lp1.transition = 0; #ifdef DEBUG_KEY printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 ); #endif hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN, vkey, keylp.lp2, event->x_root - desktopX, event->y_root - desktopY, event->time, 0 ); KeyDown = TRUE; /* The key translation ought to take place in TranslateMessage(). * However, there is no way of passing the required information * in a Windows message, so TranslateMessage does not currently * do anything and the translation is done here. */ if (count == 1) /* key has an ASCII representation */ { #ifdef DEBUG_KEY printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] ); #endif PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 ); } } else { if (vkey == VK_MENU) ALTKeyState = FALSE; keylp.lp1.count = 1; keylp.lp1.code = LOBYTE(event->keycode); keylp.lp1.extended = (extended ? 1 : 0); keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0); keylp.lp1.previous = 1; keylp.lp1.transition = 1; #ifdef DEBUG_KEY printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 ); #endif hardware_event( ((ALTKeyState || vkey == VK_MENU) ? WM_SYSKEYUP : WM_KEYUP), vkey, keylp.lp2, event->x_root - desktopX, event->y_root - desktopY, event->time, 0 ); KeyDown = FALSE; } } /*********************************************************************** * EVENT_MotionNotify */ static void EVENT_MotionNotify( XMotionEvent *event ) { hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L, event->x_root - desktopX, event->y_root - desktopY, event->time, 0 ); } /*********************************************************************** * EVENT_ButtonPress */ static void EVENT_ButtonPress( XButtonEvent *event ) { static WORD messages[NB_BUTTONS] = { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN }; int buttonNum = event->button - 1; if (buttonNum >= NB_BUTTONS) return; MouseButtonsStates[buttonNum] = TRUE; winHasCursor = event->window; hardware_event( messages[buttonNum], EVENT_XStateToKeyState( event->state ), 0L, event->x_root - desktopX, event->y_root - desktopY, event->time, 0 ); } /*********************************************************************** * EVENT_ButtonRelease */ static void EVENT_ButtonRelease( XButtonEvent *event ) { static const WORD messages[NB_BUTTONS] = { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP }; int buttonNum = event->button - 1; if (buttonNum >= NB_BUTTONS) return; MouseButtonsStates[buttonNum] = FALSE; winHasCursor = event->window; hardware_event( messages[buttonNum], EVENT_XStateToKeyState( event->state ), 0L, event->x_root - desktopX, event->y_root - desktopY, event->time, 0 ); } /********************************************************************** * EVENT_FocusOut * * Note: only top-level override-redirect windows get FocusOut events. */ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event ) { if (event->detail == NotifyPointer) return; if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE ); if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 ); } /********************************************************************** * EVENT_EnterNotify */ static void EVENT_EnterNotify( XCrossingEvent *event ) { if (captureWnd != 0) return; winHasCursor = event->window; } /********************************************************************** * EVENT_ConfigureNotify * * The ConfigureNotify event is only selected on the desktop window. */ static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event ) { desktopX = event->x; desktopY = event->y; } /********************************************************************** * SetCapture (USER.18) */ HWND SetCapture(HWND wnd) { int rv; HWND old_capture_wnd = captureWnd; WND *wnd_p = WIN_FindWndPtr(wnd); if (wnd_p == NULL) return 0; rv = XGrabPointer(display, wnd_p->window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); if (rv == GrabSuccess) { captureWnd = wnd; return old_capture_wnd; } else return 0; } /********************************************************************** * ReleaseCapture (USER.19) */ void ReleaseCapture() { if (captureWnd == 0) return; XUngrabPointer( display, CurrentTime ); captureWnd = 0; } /********************************************************************** * GetCapture (USER.236) */ HWND GetCapture() { return captureWnd; }