// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdopengl.h" #ifdef NL_OS_UNIX #include #include #include #include "nel/misc/debug.h" #include "unix_event_emitter.h" namespace NLMISC { CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _PreviousKey(KeyNOKEY) { } void CUnixEventEmitter::init (Display *dpy, Window win) { _dpy = dpy; _win = win; } void CUnixEventEmitter::submitEvents(CEventServer & server, bool allWindows) { while (XPending(_dpy)) { XEvent Event; XNextEvent(_dpy, &Event); if(Event.xany.window==_win) { // nlinfo("event: %d", Event.type); processMessage (Event, server); } } } #ifndef AltMask # ifdef NL_OS_MAC # define AltMask (8192) # else # define AltMask (Mod1Mask) # endif #endif TMouseButton getMouseButton (uint32 state) { uint32 button=noButton; if (state&Button1Mask) button|=leftButton; if (state&Button2Mask) button|=middleButton; if (state&Button3Mask) button|=rightButton; if (state&ControlMask) button|=ctrlButton; if (state&ShiftMask) button|=shiftButton; if (state&AltMask) button|=altButton; return (TMouseButton)button; } TKeyButton getKeyButton (uint32 state) { uint32 button=noKeyButton; if (state&ControlMask) button|=ctrlKeyButton; if (state&ShiftMask) button|=shiftKeyButton; if (state&AltMask) button|=altKeyButton; return (TKeyButton)button; } TKey getKey (KeySym keysym) { switch (keysym) { case XK_BackSpace: return KeyBACK; case XK_Tab: return KeyTAB; case XK_Return: return KeyRETURN; case XK_Sys_Req: return KeySNAPSHOT; case XK_Scroll_Lock: return KeySCROLL; case XK_Pause: return KeyPAUSE; case XK_Escape: return KeyESCAPE; case XK_Delete: return KeyDELETE; case XK_Home: return KeyHOME; case XK_Left: return KeyLEFT; case XK_Up: return KeyUP; case XK_Right: return KeyRIGHT; case XK_Down: return KeyDOWN; case XK_Page_Up: return KeyPRIOR; case XK_Page_Down: return KeyNEXT; case XK_End: return KeyEND; case XK_Print: return KeyPRINT; case XK_Insert: return KeyINSERT; case XK_Num_Lock: return KeyNUMLOCK; case XK_KP_0: return KeyNUMPAD0; case XK_KP_1: return KeyNUMPAD1; case XK_KP_2: return KeyNUMPAD2; case XK_KP_3: return KeyNUMPAD3; case XK_KP_4: return KeyNUMPAD4; case XK_KP_5: return KeyNUMPAD5; case XK_KP_6: return KeyNUMPAD6; case XK_KP_7: return KeyNUMPAD7; case XK_KP_8: return KeyNUMPAD8; case XK_KP_9: return KeyNUMPAD9; case XK_KP_Enter: return KeyRETURN; case XK_KP_Home: return KeyHOME; case XK_KP_Left: return KeyLEFT; case XK_KP_Up: return KeyUP; case XK_KP_Right: return KeyRIGHT; case XK_KP_Down: return KeyDOWN; case XK_KP_Page_Up: return KeyPRIOR; case XK_KP_Page_Down: return KeyNEXT; case XK_KP_End: return KeyEND; case XK_KP_Begin: return KeyCANCEL; case XK_KP_Insert: return KeyINSERT; case XK_KP_Delete: return KeyDELETE; case XK_KP_Multiply: return KeyMULTIPLY; case XK_KP_Add: return KeyADD; case XK_KP_Subtract: return KeySUBTRACT; case XK_KP_Decimal: return KeyDECIMAL; case XK_KP_Divide: return KeyDIVIDE; case XK_F1: return KeyF1; case XK_F2: return KeyF2; case XK_F3: return KeyF3; case XK_F4: return KeyF4; case XK_F5: return KeyF5; case XK_F6: return KeyF6; case XK_F7: return KeyF7; case XK_F8: return KeyF8; case XK_F9: return KeyF9; case XK_F10: return KeyF10; case XK_F11: return KeyF11; case XK_F12: return KeyF12; case XK_Shift_L: return KeySHIFT; case XK_Shift_R: return KeySHIFT; case XK_Control_L: return KeyCONTROL; case XK_Control_R: return KeyCONTROL; case XK_Caps_Lock: return KeyCAPITAL; case XK_Super_L: return KeyLWIN; case XK_Super_R: return KeyRWIN; case XK_Mode_switch: return KeyMENU; case XK_ISO_Level3_Shift: return KeyMENU; case XK_Menu: return KeyAPPS; case XK_Alt_L: return KeyMENU; case XK_Alt_R: return KeyMENU; case XK_space: return KeySPACE; case XK_0: return Key0; case XK_1: return Key1; case XK_2: return Key2; case XK_3: return Key3; case XK_4: return Key4; case XK_5: return Key5; case XK_6: return Key6; case XK_7: return Key7; case XK_8: return Key8; case XK_9: return Key9; case XK_A: case XK_a: return KeyA; case XK_B: case XK_b: return KeyB; case XK_C: case XK_c: return KeyC; case XK_D: case XK_d: return KeyD; case XK_E: case XK_e: return KeyE; case XK_F: case XK_f: return KeyF; case XK_G: case XK_g: return KeyG; case XK_H: case XK_h: return KeyH; case XK_I: case XK_i: return KeyI; case XK_J: case XK_j: return KeyJ; case XK_K: case XK_k: return KeyK; case XK_L: case XK_l: return KeyL; case XK_M: case XK_m: return KeyM; case XK_N: case XK_n: return KeyN; case XK_O: case XK_o: return KeyO; case XK_P: case XK_p: return KeyP; case XK_Q: case XK_q: return KeyQ; case XK_R: case XK_r: return KeyR; case XK_S: case XK_s: return KeyS; case XK_T: case XK_t: return KeyT; case XK_U: case XK_u: return KeyU; case XK_V: case XK_v: return KeyV; case XK_W: case XK_w: return KeyW; case XK_X: case XK_x: return KeyX; case XK_Y: case XK_y: return KeyY; case XK_Z: case XK_z: return KeyZ; default: //nldebug ("0x%x %d '%c'", keysym, keysym, keysym); break; } return KeyNOKEY; } #define Case(a) case(a): // nlinfo("event: "#a); void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server) { switch (event.type) { Case(ReparentNotify) Case(UnmapNotify) Case(VisibilityNotify) break; Case(ButtonPress) { //nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y); XWindowAttributes xwa; XGetWindowAttributes (_dpy, _win, &xwa); float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; TMouseButton button=getMouseButton(event.xbutton.state); switch(event.xbutton.button) { case Button1: server.postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(leftButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button2: server.postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(middleButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button3: server.postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(rightButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button4: server.postEvent(new CEventMouseWheel(fX, fY, button, true, this)); break; case Button5: server.postEvent(new CEventMouseWheel(fX, fY, button, false, this)); break; } break; } Case(ButtonRelease) { //nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y); XWindowAttributes xwa; XGetWindowAttributes (_dpy, _win, &xwa); float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; switch(event.xbutton.button) { case Button1: server.postEvent(new CEventMouseUp(fX, fY, leftButton, this)); break; case Button2: server.postEvent(new CEventMouseUp(fX, fY, middleButton, this)); break; case Button3: server.postEvent(new CEventMouseUp(fX, fY, rightButton, this)); break; } break; } Case(MotionNotify) { XWindowAttributes xwa; XGetWindowAttributes (_dpy, _win, &xwa); float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; if ((fX == 0.5f) && (fY == 0.5f)) break; TMouseButton button=getMouseButton (event.xbutton.state); server.postEvent (new CEventMouseMove (fX, fY, button, this)); break; } Case(KeyPress) { char Text[1024]; KeySym k; int c; c = XLookupString(&event.xkey, Text, 1024-1, &k, NULL); TKey key = getKey(XKeycodeToKeysym(_dpy, ((XKeyEvent*)&event)->keycode, 0)); if(key == KeyNOKEY) key = getKey(XKeycodeToKeysym(_dpy, ((XKeyEvent*)&event)->keycode, 1)); server.postEvent (new CEventKeyDown (key, getKeyButton(event.xbutton.state), _PreviousKey != key, this)); _PreviousKey = key; // don't send a control character when deleting if (key == KeyDELETE) c = 0; Text[c] = '\0'; if(c>0) { for (int i = 0; i < c; i++) { server.postEvent (new CEventChar ((ucchar)(unsigned char)Text[i], noKeyButton, this)); } } break; } Case (KeyRelease) { char Text[1024]; KeySym k; int c; c = XLookupString(&event.xkey, Text, 1024-1, &k, NULL); TKey key = getKey(XKeycodeToKeysym(_dpy, ((XKeyEvent*)&event)->keycode, 0)); if(key == KeyNOKEY) key = getKey(XKeycodeToKeysym(_dpy, ((XKeyEvent*)&event)->keycode, 1)); server.postEvent (new CEventKeyUp (key, getKeyButton(event.xbutton.state), this)); _PreviousKey = KeyNOKEY; break; } Case(FocusIn) return; Case(FocusOut) return; Case(Expose) break; Case(MappingNotify) XRefreshKeyboardMapping((XMappingEvent *)&event); break; Case(DestroyNotify) break; Case(ConfigureNotify) /* if (event.xconfigure.width==gmaxx && event.xconfigure.height==gmaxy) { UpdateGWin(); } else { XResizeWindow(display, gwindow, gmaxx, gmaxy); } */ break; default: nlinfo("UnknownEvent"); // XtDispatchEvent(&event); break; } } } // NLMISC #endif // NL_OS_UNIX