Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern/GHOST_SystemX11.cpp')
-rwxr-xr-xintern/ghost/intern/GHOST_SystemX11.cpp803
1 files changed, 803 insertions, 0 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
new file mode 100755
index 00000000000..77c13d66de2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -0,0 +1,803 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * 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
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * 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
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+#include "GHOST_SystemX11.h"
+#include "GHOST_WindowX11.h"
+#include "GHOST_WindowManager.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_DisplayManagerX11.h"
+
+#include "GHOST_Debug.h"
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+// For timing
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <vector>
+
+using namespace std;
+
+GHOST_SystemX11::
+GHOST_SystemX11(
+) :
+ GHOST_System(),
+ m_start_time(0)
+{
+ m_display = XOpenDisplay(NULL);
+
+ if (!m_display) return;
+
+ m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
+
+ // compute the initial time
+ timeval tv;
+ if (gettimeofday(&tv,NULL) == -1) {
+ GHOST_ASSERT(false,"Could not instantiate timer!");
+ }
+
+ m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000);
+}
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+init(
+){
+ GHOST_TSuccess success = GHOST_System::init();
+
+ if (success) {
+ m_keyboard_vector = new char[32];
+
+ m_displayManager = new GHOST_DisplayManagerX11(this);
+
+ if (m_keyboard_vector && m_displayManager) {
+ return GHOST_kSuccess;
+ }
+ }
+
+ return GHOST_kFailure;
+}
+
+
+
+ GHOST_TUns64
+GHOST_SystemX11::
+getMilliSeconds(
+) const {
+ timeval tv;
+ if (gettimeofday(&tv,NULL) == -1) {
+ GHOST_ASSERT(false,"Could not compute time!");
+ }
+
+ return GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time;
+}
+
+ GHOST_TUns8
+GHOST_SystemX11::
+getNumDisplays(
+) const {
+ return GHOST_TUns8(1);
+}
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ void
+GHOST_SystemX11::
+getMainDisplayDimensions(
+ GHOST_TUns32& width,
+ GHOST_TUns32& height
+) const {
+ if (m_display) {
+ width = DisplayWidth(m_display, DefaultScreen(m_display));
+ height = DisplayHeight(m_display, DefaultScreen(m_display));
+ }
+}
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @return The new window (or 0 if creation failed).
+ */
+ GHOST_IWindow*
+GHOST_SystemX11::
+createWindow(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ bool stereoVisual
+){
+ GHOST_WindowX11 * window = 0;
+
+ if (!m_display) return 0;
+
+ window = new GHOST_WindowX11 (
+ this,m_display,title, left, top, width, height, state, type
+ );
+
+ if (window) {
+
+ // Install a new protocol for this window - so we can overide
+ // the default window closure mechanism.
+
+ XSetWMProtocols(m_display, window->getXWindow(), &m_delete_window_atom, 1);
+
+ if (window->getValid()) {
+ // Store the pointer to the window
+ m_windowManager->addWindow(window);
+
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ }
+ else {
+ delete window;
+ window = 0;
+ }
+ }
+ return window;
+
+}
+
+ GHOST_WindowX11 *
+GHOST_SystemX11::
+findGhostWindow(
+ Window xwind
+) const {
+
+ if (xwind == 0) return NULL;
+
+ // It is not entirely safe to do this as the backptr may point
+ // to a window that has recently been removed.
+ // We should always check the window manager's list of windows
+ // and only process events on these windows.
+
+ vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
+
+ for (; win_it != win_end; ++win_it) {
+ GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
+ if (window->getXWindow() == xwind) {
+ return window;
+ }
+ }
+ return NULL;
+
+}
+
+static void SleepTillEvent(Display *display, GHOST_TUns64 maxSleep) {
+ int fd = ConnectionNumber(display);
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ if (maxSleep == -1) {
+ select(fd + 1, &fds, NULL, NULL, NULL);
+ } else {
+ timeval tv;
+
+ tv.tv_sec = maxSleep/1000;
+ tv.tv_usec = (maxSleep - tv.tv_sec*1000)*1000;
+
+ select(fd + 1, &fds, NULL, NULL, &tv);
+ }
+}
+
+ bool
+GHOST_SystemX11::
+processEvents(
+ bool waitForEvent
+){
+ // Get all the current events -- translate them into
+ // ghost events and call base class pushEvent() method.
+
+ bool anyProcessed = false;
+
+ do {
+ GHOST_TimerManager* timerMgr = getTimerManager();
+
+ if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+
+ if (next==GHOST_kFireTimeNever) {
+ SleepTillEvent(m_display, -1);
+ } else {
+ SleepTillEvent(m_display, next - getMilliSeconds());
+ }
+ }
+
+ if (timerMgr->fireTimers(getMilliSeconds())) {
+ anyProcessed = true;
+ }
+
+ while (XPending(m_display)) {
+ XEvent xevent;
+ XNextEvent(m_display, &xevent);
+ processEvent(&xevent);
+ anyProcessed = true;
+ }
+
+ if (generateWindowExposeEvents()) {
+ anyProcessed = true;
+ }
+ } while (waitForEvent && !anyProcessed);
+
+ return anyProcessed;
+}
+
+ void
+GHOST_SystemX11::
+processEvent(
+ XEvent *xe
+){
+ GHOST_WindowX11 * window = findGhostWindow(xe->xany.window);
+ GHOST_Event * g_event = NULL;
+
+ if (!window) {
+ return;
+ }
+
+ switch (xe->type) {
+ case Expose:
+ {
+ XExposeEvent & xee = xe->xexpose;
+
+ if (xee.count == 0) {
+ // Only generate a single expose event
+ // per read of the event queue.
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowUpdate,
+ window
+ );
+ }
+ break;
+ }
+ case MotionNotify:
+ {
+ XMotionEvent &xme = xe->xmotion;
+
+ g_event = new
+ GHOST_EventCursor(
+ getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ xme.x_root,
+ xme.y_root
+ );
+ break;
+ }
+
+ case KeyPress:
+ case KeyRelease:
+ {
+ XKeyEvent *xke = &(xe->xkey);
+
+ KeySym key_sym = XLookupKeysym(xke,0);
+ char ascii;
+
+ GHOST_TKey gkey = convertXKey(key_sym);
+ GHOST_TEventType type = (xke->type == KeyPress) ?
+ GHOST_kEventKeyDown : GHOST_kEventKeyUp;
+
+ if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
+ ascii = '\0';
+ }
+
+ g_event = new
+ GHOST_EventKey(
+ getMilliSeconds(),
+ type,
+ window,
+ gkey,
+ ascii
+ );
+
+ break;
+ }
+ case ButtonPress:
+ case ButtonRelease:
+ {
+
+ XButtonEvent & xbe = xe->xbutton;
+ GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
+
+ switch (xbe.button) {
+ case Button1 : gbmask = GHOST_kButtonMaskLeft; break;
+ case Button3 : gbmask = GHOST_kButtonMaskRight; break;
+ default:
+ case Button2 : gbmask = GHOST_kButtonMaskMiddle; break;
+ }
+
+ GHOST_TEventType type = (xbe.type == ButtonPress) ?
+ GHOST_kEventButtonDown : GHOST_kEventButtonUp;
+
+ g_event = new
+ GHOST_EventButton(
+ getMilliSeconds(),
+ type,
+ window,
+ gbmask
+ );
+ break;
+ }
+
+ // change of size, border, layer etc.
+ case ConfigureNotify:
+ {
+ /* XConfigureEvent & xce = xe->xconfigure; */
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowSize,
+ window
+ );
+ break;
+ }
+
+ case FocusIn:
+ case FocusOut:
+ {
+ XFocusChangeEvent &xfe = xe->xfocus;
+
+ // May have to look at the type of event and filter some
+ // out.
+
+ GHOST_TEventType gtype = (xfe.type == FocusIn) ?
+ GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ gtype,
+ window
+ );
+ break;
+
+ }
+ case ClientMessage:
+ {
+ XClientMessageEvent & xcme = xe->xclient;
+
+ if (xcme.data.l[0] == m_delete_window_atom) {
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowClose,
+ window
+ );
+ } else {
+ /* Unknown client message, ignore */
+ }
+
+ break;
+ }
+
+ // We're not interested in the following things.(yet...)
+ case NoExpose :
+ case GraphicsExpose :
+
+ case EnterNotify:
+ case LeaveNotify:
+ // XCrossingEvents pointer leave enter window.
+ break;
+ case MapNotify:
+ case UnmapNotify:
+ break;
+ case MappingNotify:
+ case ReparentNotify:
+ break;
+
+ default:
+ break;
+ }
+
+ if (g_event) {
+ pushEvent(g_event);
+ }
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getModifierKeys(
+ GHOST_ModifierKeys& keys
+) const {
+
+ // analyse the masks retuned from XQueryPointer.
+
+ memset(m_keyboard_vector,32,0);
+
+ XQueryKeymap(m_display,m_keyboard_vector);
+
+ // now translate key symobols into keycodes and
+ // test with vector.
+
+ const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L);
+ const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R);
+ const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L);
+ const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R);
+ const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L);
+ const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R);
+
+ // Shift
+ if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftShift,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftShift,false);
+ }
+ if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) {
+
+ keys.set(GHOST_kModifierKeyRightShift,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightShift,false);
+ }
+
+ // control (weep)
+ if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftControl,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftControl,false);
+ }
+ if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyRightControl,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightControl,false);
+ }
+
+ // Alt (yawn)
+ if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftAlt,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftAlt,false);
+ }
+ if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyRightAlt,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightAlt,false);
+ }
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getButtons(
+ GHOST_Buttons& buttons
+) const {
+
+ Window root_return, child_return;
+ int rx,ry,wx,wy;
+ unsigned int mask_return;
+
+ if (XQueryPointer(
+ m_display,
+ RootWindow(m_display,DefaultScreen(m_display)),
+ &root_return,
+ &child_return,
+ &rx,&ry,
+ &wx,&wy,
+ &mask_return
+ ) == False) {
+ return GHOST_kFailure;
+ } else {
+
+ if (mask_return & Button1Mask) {
+ buttons.set(GHOST_kButtonMaskLeft,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskLeft,false);
+ }
+
+ if (mask_return & Button2Mask) {
+ buttons.set(GHOST_kButtonMaskMiddle,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskMiddle,false);
+ }
+
+ if (mask_return & Button3Mask) {
+ buttons.set(GHOST_kButtonMaskRight,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskRight,false);
+ }
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getCursorPosition(
+ GHOST_TInt32& x,
+ GHOST_TInt32& y
+) const {
+
+ Window root_return, child_return;
+ int rx,ry,wx,wy;
+ unsigned int mask_return;
+
+ if (XQueryPointer(
+ m_display,
+ RootWindow(m_display,DefaultScreen(m_display)),
+ &root_return,
+ &child_return,
+ &rx,&ry,
+ &wx,&wy,
+ &mask_return
+ ) == False) {
+ return GHOST_kFailure;
+ } else {
+ x = rx;
+ y = ry;
+ }
+ return GHOST_kSuccess;
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+setCursorPosition(
+ GHOST_TInt32 x,
+ GHOST_TInt32 y
+) const {
+
+ // This is a brute force move in screen coordinates
+ // XWarpPointer does relative moves so first determine the
+ // current pointer position.
+
+ int cx,cy;
+ if (getCursorPosition(cx,cy) == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
+
+ int relx = x-cx;
+ int rely = y-cy;
+
+ XWarpPointer(m_display,None,None,0,0,0,0,relx,rely);
+ XFlush(m_display);
+
+ return GHOST_kSuccess;
+}
+
+
+ void
+GHOST_SystemX11::
+addDirtyWindow(
+ GHOST_WindowX11 * bad_wind
+){
+
+ GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
+
+ m_dirty_windows.push_back(bad_wind);
+}
+
+
+ bool
+GHOST_SystemX11::
+generateWindowExposeEvents(
+){
+
+ vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
+ vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
+ bool anyProcessed = false;
+
+ for (;w_start != w_end; ++w_start) {
+ GHOST_Event * g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowUpdate,
+ *w_start
+ );
+
+ (*w_start)->validate();
+
+ if (g_event) {
+ pushEvent(g_event);
+ anyProcessed = true;
+ }
+ }
+
+ m_dirty_windows.clear();
+ return anyProcessed;
+}
+
+#define GXMAP(k,x,y) case x: k = y; break;
+
+ GHOST_TKey
+GHOST_SystemX11::
+convertXKey(
+ unsigned int key
+){
+ GHOST_TKey type;
+
+ if ((key >= XK_A) && (key <= XK_Z)) {
+ type = GHOST_TKey( key - XK_A + int(GHOST_kKeyA));
+ } else if ((key >= XK_a) && (key <= XK_z)) {
+ type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
+ } else if ((key >= XK_0) && (key <= XK_9)) {
+ type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
+ } else if ((key >= XK_F1) && (key <= XK_F24)) {
+ type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
+ } else {
+ switch(key) {
+ GXMAP(type,XK_BackSpace, GHOST_kKeyBackSpace);
+ GXMAP(type,XK_Tab, GHOST_kKeyTab);
+ GXMAP(type,XK_Return, GHOST_kKeyEnter);
+ GXMAP(type,XK_Escape, GHOST_kKeyEsc);
+ GXMAP(type,XK_space, GHOST_kKeySpace);
+
+ GXMAP(type,XK_Linefeed, GHOST_kKeyLinefeed);
+ GXMAP(type,XK_semicolon, GHOST_kKeySemicolon);
+ GXMAP(type,XK_period, GHOST_kKeyPeriod);
+ GXMAP(type,XK_comma, GHOST_kKeyComma);
+ GXMAP(type,XK_quoteright, GHOST_kKeyQuote);
+ GXMAP(type,XK_quoteleft, GHOST_kKeyAccentGrave);
+ GXMAP(type,XK_minus, GHOST_kKeyMinus);
+ GXMAP(type,XK_slash, GHOST_kKeySlash);
+ GXMAP(type,XK_backslash, GHOST_kKeyBackslash);
+ GXMAP(type,XK_equal, GHOST_kKeyEqual);
+ GXMAP(type,XK_bracketleft, GHOST_kKeyLeftBracket);
+ GXMAP(type,XK_bracketright, GHOST_kKeyRightBracket);
+ GXMAP(type,XK_Pause, GHOST_kKeyPause);
+
+ GXMAP(type,XK_Shift_L, GHOST_kKeyLeftShift);
+ GXMAP(type,XK_Shift_R, GHOST_kKeyRightShift);
+ GXMAP(type,XK_Control_L, GHOST_kKeyLeftControl);
+ GXMAP(type,XK_Control_R, GHOST_kKeyRightControl);
+ GXMAP(type,XK_Alt_L, GHOST_kKeyLeftAlt);
+ GXMAP(type,XK_Alt_R, GHOST_kKeyRightAlt);
+
+ GXMAP(type,XK_Insert, GHOST_kKeyInsert);
+ GXMAP(type,XK_Delete, GHOST_kKeyDelete);
+ GXMAP(type,XK_Home, GHOST_kKeyHome);
+ GXMAP(type,XK_End, GHOST_kKeyEnd);
+ GXMAP(type,XK_Page_Up, GHOST_kKeyUpPage);
+ GXMAP(type,XK_Page_Down, GHOST_kKeyDownPage);
+
+ GXMAP(type,XK_Left, GHOST_kKeyLeftArrow);
+ GXMAP(type,XK_Right, GHOST_kKeyRightArrow);
+ GXMAP(type,XK_Up, GHOST_kKeyUpArrow);
+ GXMAP(type,XK_Down, GHOST_kKeyDownArrow);
+
+ GXMAP(type,XK_Caps_Lock, GHOST_kKeyCapsLock);
+ GXMAP(type,XK_Scroll_Lock, GHOST_kKeyScrollLock);
+ GXMAP(type,XK_Num_Lock, GHOST_kKeyNumLock);
+
+ /* keypad events */
+
+ GXMAP(type,XK_KP_0, GHOST_kKeyNumpad0);
+ GXMAP(type,XK_KP_1, GHOST_kKeyNumpad1);
+ GXMAP(type,XK_KP_2, GHOST_kKeyNumpad2);
+ GXMAP(type,XK_KP_3, GHOST_kKeyNumpad3);
+ GXMAP(type,XK_KP_4, GHOST_kKeyNumpad4);
+ GXMAP(type,XK_KP_5, GHOST_kKeyNumpad5);
+ GXMAP(type,XK_KP_6, GHOST_kKeyNumpad6);
+ GXMAP(type,XK_KP_7, GHOST_kKeyNumpad7);
+ GXMAP(type,XK_KP_8, GHOST_kKeyNumpad8);
+ GXMAP(type,XK_KP_9, GHOST_kKeyNumpad9);
+ GXMAP(type,XK_KP_Decimal, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type,XK_KP_Insert, GHOST_kKeyNumpad0);
+ GXMAP(type,XK_KP_End, GHOST_kKeyNumpad1);
+ GXMAP(type,XK_KP_Down, GHOST_kKeyNumpad2);
+ GXMAP(type,XK_KP_Page_Down, GHOST_kKeyNumpad3);
+ GXMAP(type,XK_KP_Left, GHOST_kKeyNumpad4);
+ GXMAP(type,XK_KP_Begin, GHOST_kKeyNumpad5);
+ GXMAP(type,XK_KP_Right, GHOST_kKeyNumpad6);
+ GXMAP(type,XK_KP_Home, GHOST_kKeyNumpad7);
+ GXMAP(type,XK_KP_Up, GHOST_kKeyNumpad8);
+ GXMAP(type,XK_KP_Page_Up, GHOST_kKeyNumpad9);
+ GXMAP(type,XK_KP_Delete, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type,XK_KP_Enter, GHOST_kKeyNumpadEnter);
+ GXMAP(type,XK_KP_Add, GHOST_kKeyNumpadPlus);
+ GXMAP(type,XK_KP_Subtract, GHOST_kKeyNumpadMinus);
+ GXMAP(type,XK_KP_Multiply, GHOST_kKeyNumpadAsterisk);
+ GXMAP(type,XK_KP_Divide, GHOST_kKeyNumpadSlash);
+
+ /* some extra sun cruft (NICE KEYBOARD!) */
+#ifdef __sun__
+ GXMAP(type,0xffde, GHOST_kKeyNumpad1);
+ GXMAP(type,0xffe0, GHOST_kKeyNumpad3);
+ GXMAP(type,0xffdc, GHOST_kKeyNumpad5);
+ GXMAP(type,0xffd8, GHOST_kKeyNumpad7);
+ GXMAP(type,0xffda, GHOST_kKeyNumpad9);
+
+ GXMAP(type,0xffd6, GHOST_kKeyNumpadSlash);
+ GXMAP(type,0xffd7, GHOST_kKeyNumpadAsterisk);
+#endif
+
+ default :
+ type = GHOST_kKeyUnknown;
+ break;
+ }
+ }
+
+ return type;
+}
+
+#undef GXMAP
+
+