Logo Search packages:      
Sourcecode: blender version File versions

GHOST_SystemX11.cpp

/**
 * $Id: GHOST_SystemX11.cpp,v 1.7 2004/08/24 03:30:16 kester Exp $
 * ***** 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: GHOST_SystemX11.cpp,v 1.7 2004/08/24 03:30:16 kester Exp $
 * ***** 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 *****
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#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_EventWheel.h"
#include "GHOST_DisplayManagerX11.h"

#include "GHOST_Debug.h"

#include <X11/Xatom.h>
#include <X11/keysym.h>

#ifdef __sgi

#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
#include <X11/SGIFastAtom.h>
#else
#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
#endif

#endif

// For timing

#include <sys/time.h>
#include <unistd.h>

#include <vector>

using namespace std;

GHOST_SystemX11::
00102 GHOST_SystemX11(
) : 
      GHOST_System(),
      m_start_time(0)
{
      m_display = XOpenDisplay(NULL);
      
      if (!m_display) return;
      
#ifdef __sgi
      m_delete_window_atom 
        = XSGIFastInternAtom(m_display,
                         "WM_DELETE_WINDOW", 
                         SGI_XA_WM_DELETE_WINDOW, False);
#else
      m_delete_window_atom 
        = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
#endif

      // 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::
00132 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::
00153 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::
00165 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::
00176 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::
00201 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, stereoVisual
      );

      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::
00243 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_TInt64 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::
00290 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:
            {
                  /* process wheel mouse events and break */
                  if (xe->xbutton.button == 4) {
                        g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1);
                        break;
                  }
                  if (xe->xbutton.button == 5) {
                        g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1);
                        break;
                  }
            }
            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;

#ifndef __sgi                 
                  if (xcme.data.l[0] == m_delete_window_atom) {
                        g_event = new 
                        GHOST_Event(      
                              getMilliSeconds(),
                              GHOST_kEventWindowClose,
                              window
                        );
                  } else {
                        /* Unknown client message, ignore */
                  }
#endif
                  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::
00521 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::
00582 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::
00627 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::
00656 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::
00682 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



Generated by  Doxygen 1.6.0   Back to index