aboutsummaryrefslogtreecommitdiff
path: root/src/windowing/WinEventsX11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/windowing/WinEventsX11.cpp')
-rw-r--r--src/windowing/WinEventsX11.cpp737
1 files changed, 737 insertions, 0 deletions
diff --git a/src/windowing/WinEventsX11.cpp b/src/windowing/WinEventsX11.cpp
new file mode 100644
index 0000000000..869fb1d582
--- /dev/null
+++ b/src/windowing/WinEventsX11.cpp
@@ -0,0 +1,737 @@
+/*
+* Copyright (C) 2005-2012 Team XBMC
+* http://www.xbmc.org
+*
+* This Program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with XBMC; see the file COPYING. If not, write to
+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+* http://www.gnu.org/copyleft/gpl.html
+*
+*/
+
+#include "system.h"
+
+#ifdef HAS_X11_WIN_EVENTS
+
+#include "WinEvents.h"
+#include "WinEventsX11.h"
+#include "Application.h"
+#include "ApplicationMessenger.h"
+#include <X11/Xlib.h>
+#include "X11/WinSystemX11GL.h"
+#include "X11/WinSystemX11GLES.h"
+#include "X11/keysymdef.h"
+#include "X11/XF86keysym.h"
+#include "utils/log.h"
+#include "utils/CharsetConverter.h"
+#include "guilib/GUIWindowManager.h"
+#include "input/MouseStat.h"
+
+#if defined(HAS_XRANDR)
+#include <X11/extensions/Xrandr.h>
+#endif
+
+#ifdef HAS_SDL_JOYSTICK
+#include "input/SDLJoystick.h"
+#endif
+
+CWinEventsX11Imp* CWinEventsX11Imp::WinEvents = 0;
+
+static uint32_t SymMappingsX11[][2] =
+{
+ {XK_BackSpace, XBMCK_BACKSPACE}
+, {XK_Tab, XBMCK_TAB}
+, {XK_Clear, XBMCK_CLEAR}
+, {XK_Return, XBMCK_RETURN}
+, {XK_Pause, XBMCK_PAUSE}
+, {XK_Escape, XBMCK_ESCAPE}
+, {XK_Delete, XBMCK_DELETE}
+// multi-media keys
+, {XF86XK_Back, XBMCK_BROWSER_BACK}
+, {XF86XK_Forward, XBMCK_BROWSER_FORWARD}
+, {XF86XK_Refresh, XBMCK_BROWSER_REFRESH}
+, {XF86XK_Stop, XBMCK_BROWSER_STOP}
+, {XF86XK_Search, XBMCK_BROWSER_SEARCH}
+, {XF86XK_Favorites, XBMCK_BROWSER_FAVORITES}
+, {XF86XK_HomePage, XBMCK_BROWSER_HOME}
+, {XF86XK_AudioMute, XBMCK_VOLUME_MUTE}
+, {XF86XK_AudioLowerVolume, XBMCK_VOLUME_DOWN}
+, {XF86XK_AudioRaiseVolume, XBMCK_VOLUME_UP}
+, {XF86XK_AudioNext, XBMCK_MEDIA_NEXT_TRACK}
+, {XF86XK_AudioPrev, XBMCK_MEDIA_PREV_TRACK}
+, {XF86XK_AudioStop, XBMCK_MEDIA_STOP}
+, {XF86XK_AudioPause, XBMCK_MEDIA_PLAY_PAUSE}
+, {XF86XK_Mail, XBMCK_LAUNCH_MAIL}
+, {XF86XK_Select, XBMCK_LAUNCH_MEDIA_SELECT}
+, {XF86XK_Launch0, XBMCK_LAUNCH_APP1}
+, {XF86XK_Launch1, XBMCK_LAUNCH_APP2}
+, {XF86XK_WWW, XBMCK_LAUNCH_FILE_BROWSER}
+, {XF86XK_AudioMedia, XBMCK_LAUNCH_MEDIA_CENTER }
+ // Numeric keypad
+, {XK_KP_0, XBMCK_KP0}
+, {XK_KP_1, XBMCK_KP1}
+, {XK_KP_2, XBMCK_KP2}
+, {XK_KP_3, XBMCK_KP3}
+, {XK_KP_4, XBMCK_KP4}
+, {XK_KP_5, XBMCK_KP5}
+, {XK_KP_6, XBMCK_KP6}
+, {XK_KP_7, XBMCK_KP7}
+, {XK_KP_8, XBMCK_KP8}
+, {XK_KP_9, XBMCK_KP9}
+, {XK_KP_Separator, XBMCK_KP_PERIOD}
+, {XK_KP_Divide, XBMCK_KP_DIVIDE}
+, {XK_KP_Multiply, XBMCK_KP_MULTIPLY}
+, {XK_KP_Subtract, XBMCK_KP_MINUS}
+, {XK_KP_Add, XBMCK_KP_PLUS}
+, {XK_KP_Enter, XBMCK_KP_ENTER}
+, {XK_KP_Equal, XBMCK_KP_EQUALS}
+ // Arrows + Home/End pad
+, {XK_Up, XBMCK_UP}
+, {XK_Down, XBMCK_DOWN}
+, {XK_Right, XBMCK_RIGHT}
+, {XK_Left, XBMCK_LEFT}
+, {XK_Insert, XBMCK_INSERT}
+, {XK_Home, XBMCK_HOME}
+, {XK_End, XBMCK_END}
+, {XK_Page_Up, XBMCK_PAGEUP}
+, {XK_Page_Down, XBMCK_PAGEDOWN}
+ // Function keys
+, {XK_F1, XBMCK_F1}
+, {XK_F2, XBMCK_F2}
+, {XK_F3, XBMCK_F3}
+, {XK_F4, XBMCK_F4}
+, {XK_F5, XBMCK_F5}
+, {XK_F6, XBMCK_F6}
+, {XK_F7, XBMCK_F7}
+, {XK_F8, XBMCK_F8}
+, {XK_F9, XBMCK_F9}
+, {XK_F10, XBMCK_F10}
+, {XK_F11, XBMCK_F11}
+, {XK_F12, XBMCK_F12}
+, {XK_F13, XBMCK_F13}
+, {XK_F14, XBMCK_F14}
+, {XK_F15, XBMCK_F15}
+ // Key state modifier keys
+, {XK_Num_Lock, XBMCK_NUMLOCK}
+, {XK_Caps_Lock, XBMCK_CAPSLOCK}
+, {XK_Scroll_Lock, XBMCK_SCROLLOCK}
+, {XK_Shift_R, XBMCK_RSHIFT}
+, {XK_Shift_L, XBMCK_LSHIFT}
+, {XK_Control_R, XBMCK_RCTRL}
+, {XK_Control_L, XBMCK_LCTRL}
+, {XK_Alt_R, XBMCK_RALT}
+, {XK_Alt_L, XBMCK_LALT}
+, {XK_Meta_R, XBMCK_RMETA}
+, {XK_Meta_L, XBMCK_LMETA}
+, {XK_Super_L, XBMCK_LSUPER}
+, {XK_Super_R, XBMCK_RSUPER}
+, {XK_Mode_switch, XBMCK_MODE}
+, {XK_Multi_key, XBMCK_COMPOSE}
+ // Miscellaneous function keys
+, {XK_Help, XBMCK_HELP}
+, {XK_Print, XBMCK_PRINT}
+//, {0, XBMCK_SYSREQ}
+, {XK_Break, XBMCK_BREAK}
+, {XK_Menu, XBMCK_MENU}
+, {XF86XK_PowerOff, XBMCK_POWER}
+, {XF86XK_Sleep, XBMCK_SLEEP}
+, {XK_EcuSign, XBMCK_EURO}
+, {XK_Undo, XBMCK_UNDO}
+ /* Media keys */
+, {XF86XK_Eject, XBMCK_EJECT}
+, {XF86XK_Stop, XBMCK_STOP}
+, {XF86XK_AudioRecord, XBMCK_RECORD}
+, {XF86XK_AudioRewind, XBMCK_REWIND}
+, {XF86XK_Phone, XBMCK_PHONE}
+, {XF86XK_AudioPlay, XBMCK_PLAY}
+, {XF86XK_AudioRandomPlay, XBMCK_SHUFFLE}
+, {XF86XK_AudioForward, XBMCK_FASTFORWARD}
+};
+
+bool CWinEventsX11::MessagePump()
+{
+ return CWinEventsX11Imp::MessagePump();
+}
+
+size_t CWinEventsX11::GetQueueSize()
+{
+ return CWinEventsX11Imp::GetQueueSize();
+}
+
+CWinEventsX11Imp::CWinEventsX11Imp()
+{
+ m_display = 0;
+ m_window = 0;
+ m_keybuf = 0;
+ m_keybuf_len = 0;
+}
+
+CWinEventsX11Imp::~CWinEventsX11Imp()
+{
+ free(m_keybuf);
+ m_keybuf = 0;
+
+ if (m_xic)
+ {
+ XUnsetICFocus(m_xic);
+ XDestroyIC(m_xic);
+ m_xic = 0;
+ }
+
+ if (m_xim)
+ {
+ XCloseIM(m_xim);
+ m_xim = 0;
+ }
+
+ m_symLookupTable.clear();
+}
+
+bool CWinEventsX11Imp::Init(Display *dpy, Window win)
+{
+ if (WinEvents)
+ return true;
+
+ WinEvents = new CWinEventsX11Imp();
+ WinEvents->m_display = dpy;
+ WinEvents->m_window = win;
+ WinEvents->m_keybuf_len = 32*sizeof(char);
+ WinEvents->m_keybuf = (char*)malloc(WinEvents->m_keybuf_len);
+ WinEvents->m_keymodState = 0;
+ WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ WinEvents->m_structureChanged = false;
+ WinEvents->m_xrrEventPending = false;
+
+ // open input method
+ char *old_locale = NULL, *old_modifiers = NULL;
+ char res_name[8];
+ const char *p;
+
+ // set resource name to xbmc, not used
+ strcpy(res_name, "xbmc");
+
+ // save current locale, this should be "C"
+ p = setlocale(LC_ALL, NULL);
+ if (p)
+ {
+ old_locale = (char*)malloc(strlen(p) +1);
+ strcpy(old_locale, p);
+ }
+ p = XSetLocaleModifiers(NULL);
+ if (p)
+ {
+ old_modifiers = (char*)malloc(strlen(p) +1);
+ strcpy(old_modifiers, p);
+ }
+
+ // set users preferences and open input method
+ p = setlocale(LC_ALL, "");
+ XSetLocaleModifiers("");
+ WinEvents->m_xim = XOpenIM(WinEvents->m_display, NULL, res_name, res_name);
+
+ // restore old locale
+ if (old_locale)
+ {
+ setlocale(LC_ALL, old_locale);
+ free(old_locale);
+ }
+ if (old_modifiers)
+ {
+ XSetLocaleModifiers(old_modifiers);
+ free(old_modifiers);
+ }
+
+ WinEvents->m_xic = NULL;
+ if (WinEvents->m_xim)
+ {
+ WinEvents->m_xic = XCreateIC(WinEvents->m_xim,
+ XNClientWindow, WinEvents->m_window,
+ XNFocusWindow, WinEvents->m_window,
+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ XNResourceName, res_name,
+ XNResourceClass, res_name,
+ NULL);
+ }
+
+ if (!WinEvents->m_xic)
+ CLog::Log(LOGWARNING,"CWinEventsX11::Init - no input method found");
+
+ // build Keysym lookup table
+ for (unsigned int i = 0; i < sizeof(SymMappingsX11)/(2*sizeof(uint32_t)); ++i)
+ {
+ WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1];
+ }
+
+ // register for xrandr events
+#if defined(HAS_XRANDR)
+ int iReturn;
+ XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn);
+ int numScreens = XScreenCount(WinEvents->m_display);
+ for (int i = 0; i < numScreens; i++)
+ {
+ XRRSelectInput(WinEvents->m_display, RootWindow(WinEvents->m_display, i), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
+ }
+#endif
+
+ return true;
+}
+
+void CWinEventsX11Imp::Quit()
+{
+ if (!WinEvents)
+ return;
+
+ delete WinEvents;
+ WinEvents = 0;
+}
+
+bool CWinEventsX11Imp::HasStructureChanged()
+{
+ if (!WinEvents)
+ return false;
+
+ bool ret = WinEvents->m_structureChanged;
+ WinEvents->m_structureChanged = false;
+ return ret;
+}
+
+void CWinEventsX11Imp::SetXRRFailSafeTimer(int millis)
+{
+ if (!WinEvents)
+ return;
+
+ WinEvents->m_xrrFailSafeTimer.Set(millis);
+ WinEvents->m_xrrEventPending = true;
+}
+
+bool CWinEventsX11Imp::MessagePump()
+{
+ if (!WinEvents)
+ return false;
+
+ bool ret = false;
+ XEvent xevent;
+ unsigned long serial = 0;
+
+ while (WinEvents && XPending(WinEvents->m_display))
+ {
+ memset(&xevent, 0, sizeof (XEvent));
+ XNextEvent(WinEvents->m_display, &xevent);
+
+#if defined(HAS_XRANDR)
+ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify))
+ {
+ XRRUpdateConfiguration(&xevent);
+ if (xevent.xgeneric.serial != serial)
+ g_Windowing.NotifyXRREvent();
+ WinEvents->m_xrrEventPending = false;
+ serial = xevent.xgeneric.serial;
+ continue;
+ }
+ else if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRNotify))
+ {
+ if (xevent.xgeneric.serial != serial)
+ g_Windowing.NotifyXRREvent();
+ WinEvents->m_xrrEventPending = false;
+ serial = xevent.xgeneric.serial;
+ continue;
+ }
+#endif
+
+ if (XFilterEvent(&xevent, WinEvents->m_window))
+ continue;
+
+ switch (xevent.type)
+ {
+ case MapNotify:
+ {
+ g_application.SetRenderGUI(true);
+ break;
+ }
+
+ case UnmapNotify:
+ {
+ g_application.SetRenderGUI(false);
+ break;
+ }
+
+ case FocusIn:
+ {
+ if (WinEvents->m_xic)
+ XSetICFocus(WinEvents->m_xic);
+ g_application.m_AppFocused = true;
+ WinEvents->m_keymodState = 0;
+ if (serial == xevent.xfocus.serial)
+ break;
+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
+ break;
+ }
+
+ case FocusOut:
+ {
+ if (WinEvents->m_xic)
+ XUnsetICFocus(WinEvents->m_xic);
+ g_application.m_AppFocused = false;
+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
+ serial = xevent.xfocus.serial;
+ break;
+ }
+
+ case Expose:
+ {
+ g_windowManager.MarkDirty();
+ break;
+ }
+
+ case ConfigureNotify:
+ {
+ if (xevent.xconfigure.window != WinEvents->m_window)
+ break;
+
+ WinEvents->m_structureChanged = true;
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_VIDEORESIZE;
+ newEvent.resize.w = xevent.xconfigure.width;
+ newEvent.resize.h = xevent.xconfigure.height;
+ ret |= g_application.OnEvent(newEvent);
+ g_windowManager.MarkDirty();
+ break;
+ }
+
+ case ClientMessage:
+ {
+ if ((unsigned int)xevent.xclient.data.l[0] == WinEvents->m_wmDeleteMessage)
+ if (!g_application.m_bStop) CApplicationMessenger::Get().Quit();
+ break;
+ }
+
+ case KeyPress:
+ {
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_KEYDOWN;
+ KeySym xkeysym;
+
+ // fallback if we have no IM
+ if (!WinEvents->m_xic)
+ {
+ static XComposeStatus state;
+ char keybuf[32];
+ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL);
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
+ newEvent.key.state = xevent.xkey.state;
+ newEvent.key.type = xevent.xkey.type;
+ if (XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state))
+ {
+ newEvent.key.keysym.unicode = keybuf[0];
+ }
+ ret |= ProcessKey(newEvent);
+ break;
+ }
+
+ Status status;
+ int len;
+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
+ WinEvents->m_keybuf, WinEvents->m_keybuf_len,
+ &xkeysym, &status);
+ if (status == XBufferOverflow)
+ {
+ WinEvents->m_keybuf_len = len;
+ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, WinEvents->m_keybuf_len);
+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
+ WinEvents->m_keybuf, WinEvents->m_keybuf_len,
+ &xkeysym, &status);
+ }
+ switch (status)
+ {
+ case XLookupNone:
+ break;
+ case XLookupChars:
+ case XLookupBoth:
+ {
+ CStdString data(WinEvents->m_keybuf, len);
+ CStdStringW keys;
+ g_charsetConverter.utf8ToW(data, keys, false);
+
+ if (keys.length() == 0)
+ {
+ break;
+ }
+
+ for (unsigned int i = 0; i < keys.length() - 1; i++)
+ {
+ newEvent.key.keysym.sym = XBMCK_UNKNOWN;
+ newEvent.key.keysym.unicode = keys[i];
+ newEvent.key.state = xevent.xkey.state;
+ newEvent.key.type = xevent.xkey.type;
+ ret |= ProcessKey(newEvent);
+ }
+ if (keys.length() > 0)
+ {
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
+ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL);
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
+ newEvent.key.keysym.unicode = keys[keys.length() - 1];
+ newEvent.key.state = xevent.xkey.state;
+ newEvent.key.type = xevent.xkey.type;
+
+ ret |= ProcessKey(newEvent);
+ }
+ break;
+ }
+
+ case XLookupKeySym:
+ {
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
+ newEvent.key.state = xevent.xkey.state;
+ newEvent.key.type = xevent.xkey.type;
+ ret |= ProcessKey(newEvent);
+ break;
+ }
+
+ }// switch status
+ break;
+ } //KeyPress
+
+ case KeyRelease:
+ {
+ // if we have a queued press directly after, this is a repeat
+ if( XEventsQueued( WinEvents->m_display, QueuedAfterReading ) )
+ {
+ XEvent next_event;
+ XPeekEvent( WinEvents->m_display, &next_event );
+ if(next_event.type == KeyPress
+ && next_event.xkey.window == xevent.xkey.window
+ && next_event.xkey.keycode == xevent.xkey.keycode
+ && (next_event.xkey.time - xevent.xkey.time < 2) )
+ continue;
+ }
+
+ XBMC_Event newEvent;
+ KeySym xkeysym;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_KEYUP;
+ xkeysym = XLookupKeysym(&xevent.xkey, 0);
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
+ newEvent.key.state = xevent.xkey.state;
+ newEvent.key.type = xevent.xkey.type;
+ ret |= ProcessKey(newEvent);
+ break;
+ }
+
+ case EnterNotify:
+ {
+ break;
+ }
+
+ // lose mouse coverage
+ case LeaveNotify:
+ {
+ g_Mouse.SetActive(false);
+ break;
+ }
+
+ case MotionNotify:
+ {
+ if (xevent.xmotion.window != WinEvents->m_window)
+ break;
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_MOUSEMOTION;
+ newEvent.motion.xrel = (int16_t)xevent.xmotion.x_root;
+ newEvent.motion.yrel = (int16_t)xevent.xmotion.y_root;
+ newEvent.motion.x = (int16_t)xevent.xmotion.x;
+ newEvent.motion.y = (int16_t)xevent.xmotion.y;
+ ret |= g_application.OnEvent(newEvent);
+ break;
+ }
+
+ case ButtonPress:
+ {
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_MOUSEBUTTONDOWN;
+ newEvent.button.button = (unsigned char)xevent.xbutton.button;
+ newEvent.button.state = XBMC_PRESSED;
+ newEvent.button.x = (int16_t)xevent.xbutton.x;
+ newEvent.button.y = (int16_t)xevent.xbutton.y;
+ ret |= g_application.OnEvent(newEvent);
+ break;
+ }
+
+ case ButtonRelease:
+ {
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+ newEvent.type = XBMC_MOUSEBUTTONUP;
+ newEvent.button.button = (unsigned char)xevent.xbutton.button;
+ newEvent.button.state = XBMC_RELEASED;
+ newEvent.button.x = (int16_t)xevent.xbutton.x;
+ newEvent.button.y = (int16_t)xevent.xbutton.y;
+ ret |= g_application.OnEvent(newEvent);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }// switch event.type
+ }// while
+
+#if defined(HAS_XRANDR)
+ if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast())
+ {
+ CLog::Log(LOGERROR,"CWinEventsX11::MessagePump - missed XRR Events");
+ g_Windowing.NotifyXRREvent();
+ WinEvents->m_xrrEventPending = false;
+ }
+#endif
+
+#ifdef HAS_SDL_JOYSTICK
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_JOYBUTTONUP:
+ case SDL_JOYBUTTONDOWN:
+ case SDL_JOYAXISMOTION:
+ case SDL_JOYBALLMOTION:
+ case SDL_JOYHATMOTION:
+ case SDL_JOYDEVICEADDED:
+ case SDL_JOYDEVICEREMOVED:
+ g_Joystick.Update(event);
+ ret = true;
+ break;
+
+ default:
+ break;
+ }
+ memset(&event, 0, sizeof(SDL_Event));
+ }
+#endif
+
+ return ret;
+}
+
+size_t CWinEventsX11Imp::GetQueueSize()
+{
+ int ret = 0;
+
+ if (WinEvents)
+ ret = XPending(WinEvents->m_display);
+
+ return ret;
+}
+
+bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event)
+{
+ if (event.type == XBMC_KEYDOWN)
+ {
+ // check key modifiers
+ switch(event.key.keysym.sym)
+ {
+ case XBMCK_LSHIFT:
+ WinEvents->m_keymodState |= XBMCKMOD_LSHIFT;
+ break;
+ case XBMCK_RSHIFT:
+ WinEvents->m_keymodState |= XBMCKMOD_RSHIFT;
+ break;
+ case XBMCK_LCTRL:
+ WinEvents->m_keymodState |= XBMCKMOD_LCTRL;
+ break;
+ case XBMCK_RCTRL:
+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL;
+ break;
+ case XBMCK_LALT:
+ WinEvents->m_keymodState |= XBMCKMOD_LALT;
+ break;
+ case XBMCK_RALT:
+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL;
+ break;
+ case XBMCK_LMETA:
+ WinEvents->m_keymodState |= XBMCKMOD_LMETA;
+ break;
+ case XBMCK_RMETA:
+ WinEvents->m_keymodState |= XBMCKMOD_RMETA;
+ break;
+ case XBMCK_MODE:
+ WinEvents->m_keymodState |= XBMCKMOD_MODE;
+ break;
+ default:
+ break;
+ }
+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
+ }
+ else if (event.type == XBMC_KEYUP)
+ {
+ switch(event.key.keysym.sym)
+ {
+ case XBMCK_LSHIFT:
+ WinEvents->m_keymodState &= ~XBMCKMOD_LSHIFT;
+ break;
+ case XBMCK_RSHIFT:
+ WinEvents->m_keymodState &= ~XBMCKMOD_RSHIFT;
+ break;
+ case XBMCK_LCTRL:
+ WinEvents->m_keymodState &= ~XBMCKMOD_LCTRL;
+ break;
+ case XBMCK_RCTRL:
+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL;
+ break;
+ case XBMCK_LALT:
+ WinEvents->m_keymodState &= ~XBMCKMOD_LALT;
+ break;
+ case XBMCK_RALT:
+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL;
+ break;
+ case XBMCK_LMETA:
+ WinEvents->m_keymodState &= ~XBMCKMOD_LMETA;
+ break;
+ case XBMCK_RMETA:
+ WinEvents->m_keymodState &= ~XBMCKMOD_RMETA;
+ break;
+ case XBMCK_MODE:
+ WinEvents->m_keymodState &= ~XBMCKMOD_MODE;
+ break;
+ default:
+ break;
+ }
+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
+ }
+
+ return g_application.OnEvent(event);
+}
+
+XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym)
+{
+ // try direct mapping first
+ std::map<uint32_t, uint32_t>::iterator it;
+ it = WinEvents->m_symLookupTable.find(keysym);
+ if (it != WinEvents->m_symLookupTable.end())
+ {
+ return (XBMCKey)(it->second);
+ }
+
+ // try ascii mappings
+ if (keysym>>8 == 0x00)
+ return (XBMCKey)tolower(keysym & 0xFF);
+
+ return (XBMCKey)keysym;
+}
+#endif