view src/video/photon/SDL_photon_input.c @ 3108:aa1897bee1e9

Continue working on QNX Photon with OpenGL ES support
author Mike Gorchak <lestat@i.com.ua>
date Tue, 28 Apr 2009 04:30:52 +0000
parents
children 1102a3305928
line wrap: on
line source

/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2009 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Sam Lantinga
    slouken@libsdl.org

    QNX Photon GUI SDL driver
    Copyright (C) 2009 Mike Gorchak
    (mike@malva.ua, lestat@i.com.ua)
*/

#include "SDL_photon_input.h"

#include "SDL_config.h"
#include "SDL_events.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_keyboard_c.h"

#include "SDL_photon_keycodes.h"

/* Mouse related functions */
SDL_Cursor* photon_createcursor(SDL_Surface* surface, int hot_x, int hot_y);
int  photon_showcursor(SDL_Cursor* cursor);
void photon_movecursor(SDL_Cursor* cursor);
void photon_freecursor(SDL_Cursor* cursor);
void photon_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y);
void photon_freemouse(SDL_Mouse* mouse);

int32_t photon_addinputdevices(_THIS)
{
   SDL_VideoData*    phdata=(SDL_VideoData*)_this->driverdata;
   SDL_DisplayData*  didata=NULL;
   struct SDL_Mouse  photon_mouse;
   SDL_MouseData*    mdata=NULL;
   SDL_Keyboard      photon_keyboard;
   SDLKey   keymap[SDL_NUM_SCANCODES];
   uint32_t it;

   for (it=0; it<_this->num_displays; it++)
   {
      /* Clear SDL mouse structure */
      SDL_memset(&photon_mouse, 0x00, sizeof(struct SDL_Mouse));

      /* Allocate SDL_MouseData structure */
      mdata=(SDL_MouseData*)SDL_calloc(1, sizeof(SDL_MouseData));
      if (mdata==NULL)
      {
         SDL_OutOfMemory();
         return -1;
      }

      /* Mark this mouse with ID 0 */
      photon_mouse.id=it;
      photon_mouse.driverdata=(void*)mdata;
      photon_mouse.CreateCursor=photon_createcursor;
      photon_mouse.ShowCursor=photon_showcursor;
      photon_mouse.MoveCursor=photon_movecursor;
      photon_mouse.FreeCursor=photon_freecursor;
      photon_mouse.WarpMouse=photon_warpmouse;
      photon_mouse.FreeMouse=photon_freemouse;

      /* Get display data */
      didata=(SDL_DisplayData*)_this->displays[it].driverdata;

      /* Store SDL_DisplayData pointer in the mouse driver internals */
      mdata->didata=didata;

      /* Register mouse cursor in SDL */
      SDL_AddMouse(&photon_mouse, "Photon mouse cursor", 0, 0, 1);
   }

   /* Photon maps all keyboards to one */
   SDL_zero(photon_keyboard);
   SDL_AddKeyboard(&photon_keyboard, -1);

   /* Add default scancode to key mapping */
   SDL_GetDefaultKeymap(keymap);
   SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);

   return 0;
}

int32_t photon_delinputdevices(_THIS)
{
   /* Destroy all of the mice */
   SDL_MouseQuit();
}

/*****************************************************************************/
/* Photon mouse related functions                                            */
/*****************************************************************************/
SDL_Cursor* photon_createcursor(SDL_Surface* surface, int hot_x, int hot_y)
{
   PhCursorDef_t* internal_cursor;
   SDL_Cursor*    sdl_cursor;
   uint8_t*       image0=NULL;
   uint8_t*       image1=NULL;
   uint32_t       it;
   uint32_t       jt;
   uint32_t       shape_color;

   /* SDL converts monochrome cursor shape to 32bpp cursor shape      */
   /* and we must convert it back to monochrome, this routine handles */
   /* 24/32bpp surfaces only                                          */
   if ((surface->format->BitsPerPixel!=32) && (surface->format->BitsPerPixel!=24))
   {
      SDL_SetError("Photon: Cursor shape is not 24/32bpp.");
      return NULL;
   }

   /* Checking data parameters */
   if ((surface->w==0) || (surface->h==0))
   {
      SDL_SetError("Photon: Cursor shape dimensions are zero");
      return NULL;
   }

   /* Allocate memory for the internal cursor format */
   internal_cursor=(PhCursorDef_t*)SDL_calloc(1, sizeof(PhCursorDef_t)+
      ((((surface->w+7)>>3)*surface->h)*2)-1);
   if (internal_cursor==NULL)
   {
      SDL_OutOfMemory();
      return NULL;
   }

   /* Allocate memory for the SDL cursor */
   sdl_cursor=(SDL_Cursor*)SDL_calloc(1, sizeof(SDL_Cursor));
   if (sdl_cursor==NULL)
   {
      SDL_free(internal_cursor);
      SDL_OutOfMemory();
      return NULL;
   }

   /* Set driverdata as photon cursor format */
   image0=(uint8_t*)internal_cursor;
   image0+=sizeof(PhCursorDef_t)-1;
   image1=image0;
   image1+=((surface->w+7)>>3)*surface->h;
   sdl_cursor->driverdata=(void*)internal_cursor;
   internal_cursor->hdr.len=(sizeof(PhCursorDef_t)-sizeof(PhRegionDataHdr_t))+
                            ((((surface->w+7)>>3)*surface->h)*2)-1;
   internal_cursor->hdr.type=Ph_RDATA_CURSOR;
   internal_cursor->size1.x=surface->w;
   internal_cursor->size1.y=surface->h;
   internal_cursor->size2.x=surface->w;
   internal_cursor->size2.y=surface->h;
   internal_cursor->offset1.x=hot_x;
   internal_cursor->offset1.y=hot_y;
   internal_cursor->offset2.x=hot_x;
   internal_cursor->offset2.y=hot_y;
   internal_cursor->bytesperline1=((surface->w+7)>>3);
   internal_cursor->bytesperline2=((surface->w+7)>>3);
   internal_cursor->color1=(SDL_PHOTON_MOUSE_COLOR_BLACK) & 0x00FFFFFF;
   internal_cursor->color2=(SDL_PHOTON_MOUSE_COLOR_WHITE) & 0x00FFFFFF;

   /* Convert cursor from 32 bpp */
   for (jt=0; jt<surface->h; jt++)
   {
      for (it=0; it<surface->w; it++)
      {
         shape_color=*((uint32_t*)((uint8_t*)surface->pixels+jt*surface->pitch+it*surface->format->BytesPerPixel));
         switch(shape_color)
         {
            case SDL_PHOTON_MOUSE_COLOR_BLACK:
                 {
                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))|=0x80>>(it%8);
                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
                 }
                 break;
            case SDL_PHOTON_MOUSE_COLOR_WHITE:
                 {
                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))|=0x80>>(it%8);
                 }
                 break;
            case SDL_PHOTON_MOUSE_COLOR_TRANS:
                 {
                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
                 }
                 break;
            default:
                 {
                    /* The same as transparent color, must not happen */
                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
                 }
                 break;
         }
      }
   }

   return sdl_cursor;
}

int photon_showcursor(SDL_Cursor* cursor)
{
   SDL_VideoDisplay* display;
   SDL_DisplayData*  didata;
   SDL_Window*       window;
   SDL_WindowData*   wdata;
   SDL_WindowID      window_id;
   PhCursorDef_t*    internal_cursor;
   int32_t status;

   /* Get current window id */
   window_id=SDL_GetFocusWindow();
   if (window_id<=0)
   {
      SDL_MouseData* mdata=NULL;

      /* If there is no current window, then someone calls this function */
      /* to set global mouse settings during SDL initialization          */
      if (cursor!=NULL)
      {
         /* Store cursor for future usage */
         mdata=(SDL_MouseData*)cursor->mouse->driverdata;
         didata=(SDL_DisplayData*)mdata->didata;
         internal_cursor=(PhCursorDef_t*)cursor->driverdata;

         if (didata->cursor_size>=(internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t)))
         {
            SDL_memcpy(didata->cursor, internal_cursor, internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
         }
         else
         {
            /* Partitial cursor image */
            SDL_memcpy(didata->cursor, internal_cursor, didata->cursor_size);
         }

         didata->cursor_visible=SDL_TRUE;
         return 0;
      }
      else
      {
         /* We can't get SDL_DisplayData at this point, return fake success */
         return 0;
      }
   }
   else
   {
      /* Sanity checks */
      window=SDL_GetWindowFromID(window_id);
      if (window!=NULL)
      {
         display=SDL_GetDisplayFromWindow(window);
         if (display!=NULL)
         {
            didata=(SDL_DisplayData*)display->driverdata;
            if (didata!=NULL)
            {
               wdata=(SDL_WindowData*)window->driverdata;
               if (wdata==NULL)
               {
                  return -1;
               }
            }
            else
            {
               return -1;
            }
         }
         else
         {
            return -1;
         }
      }
      else
      {
         return -1;
      }
   }

   /* return if window widget has been destroyed already */
   if (wdata->window==NULL)
   {
      return;
   }

   /* Check if we need to set new shape or disable cursor shape */
   if (cursor!=NULL)
   {
      /* Retrieve photon cursor shape */
      internal_cursor=(PhCursorDef_t*)cursor->driverdata;
      if (internal_cursor==NULL)
      {
         SDL_SetError("Photon: Internal cursor data is absent");
         return -1;
      }

      /* Setup cursor type */
      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0);
      if (status!=0)
      {
         SDL_SetError("Photon: Failed to set cursor type to bitmap");
         return -1;
      }

      /* Setup cursor color to default */
      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR, 0);
      if (status!=0)
      {
         SDL_SetError("Photon: Failed to set cursor color");
         return -1;
      }

      /* Setup cursor shape */
      status=PtSetResource(wdata->window, Pt_ARG_BITMAP_CURSOR, internal_cursor,
                           internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
      if (status!=0)
      {
         SDL_SetError("Photon: Failed to set cursor color");
         return -1;
      }

      /* Store current cursor for future usage */
      if (didata->cursor_size>=(internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t)))
      {
         SDL_memcpy(didata->cursor, internal_cursor, internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
      }
      else
      {
         /* Partitial cursor image */
         SDL_memcpy(didata->cursor, internal_cursor, didata->cursor_size);
      }

      /* Set cursor visible */
      didata->cursor_visible=SDL_TRUE;
   }
   else
   {
      /* SDL requests to disable cursor */
      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0);
      if (status!=0)
      {
         SDL_SetError("Photon: Can't disable cursor");
         return -1;
      }

      /* Set cursor invisible */
      didata->cursor_visible=SDL_FALSE;
   }

   /* Flush all pending widget data */
   PtFlush();

   /* New cursor shape is set */
   return 0;
}

void photon_movecursor(SDL_Cursor* cursor)
{
   SDL_VideoDisplay* display;
   SDL_DisplayData*  didata;
   SDL_Window*  window;
   SDL_WindowID window_id;
   int32_t status;

   /* Get current window id */
   window_id=SDL_GetFocusWindow();
   if (window_id<=0)
   {
      didata=(SDL_DisplayData*)cursor->mouse->driverdata;
   }
   else
   {
      /* Sanity checks */
      window=SDL_GetWindowFromID(window_id);
      if (window!=NULL)
      {
         display=SDL_GetDisplayFromWindow(window);
         if (display!=NULL)
         {
            didata=(SDL_DisplayData*)display->driverdata;
            if (didata==NULL)
            {
               return;
            }
         }
         else
         {
            return;
         }
      }
      else
      {
         return;
      }
   }

/*   cursor->mouse->x, cursor->mouse->y */
}

void photon_freecursor(SDL_Cursor* cursor)
{
   PhCursorDef_t* internal_cursor=NULL;

   if (cursor!=NULL)
   {
      internal_cursor=(PhCursorDef_t*)cursor->driverdata;
      if (internal_cursor!=NULL)
      {
         SDL_free(internal_cursor);
         cursor->driverdata=NULL;
      }
   }
}

void photon_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y)
{
   SDL_VideoDisplay* display;
   SDL_DisplayData*  didata;
   SDL_Window* window;
   int32_t status;

   /* Sanity checks */
   window=SDL_GetWindowFromID(windowID);
   if (window!=NULL)
   {
      display=SDL_GetDisplayFromWindow(window);
      if (display!=NULL)
      {
         didata=(SDL_DisplayData*)display->driverdata;
         if (didata==NULL)
         {
            return;
         }
      }
      else
      {
         return;
      }
   }
   else
   {
      return;
   }

}

void photon_freemouse(SDL_Mouse* mouse)
{
   if (mouse->driverdata==NULL)
   {
      return;
   }

   /* Mouse framework doesn't deletes automatically our driverdata */
   SDL_free(mouse->driverdata);
   mouse->driverdata=NULL;

   return;
}

SDL_scancode photon_to_sdl_keymap(uint32_t key)
{
   SDL_scancode scancode=SDL_SCANCODE_UNKNOWN;

   switch(key & 0x0000007F)
   {
      case PHOTON_SCANCODE_ESCAPE:
           scancode=SDL_SCANCODE_ESCAPE;
           break;
      case PHOTON_SCANCODE_F1:
           scancode=SDL_SCANCODE_F1;
           break;
      case PHOTON_SCANCODE_F2:
           scancode=SDL_SCANCODE_F2;
           break;
      case PHOTON_SCANCODE_F3:
           scancode=SDL_SCANCODE_F3;
           break;
      case PHOTON_SCANCODE_F4:
           scancode=SDL_SCANCODE_F4;
           break;
      case PHOTON_SCANCODE_F5:
           scancode=SDL_SCANCODE_F5;
           break;
      case PHOTON_SCANCODE_F6:
           scancode=SDL_SCANCODE_F6;
           break;
      case PHOTON_SCANCODE_F7:
           scancode=SDL_SCANCODE_F7;
           break;
      case PHOTON_SCANCODE_F8:
           scancode=SDL_SCANCODE_F8;
           break;
      case PHOTON_SCANCODE_F9:
           scancode=SDL_SCANCODE_F9;
           break;
      case PHOTON_SCANCODE_F10:
           scancode=SDL_SCANCODE_F10;
           break;
      case PHOTON_SCANCODE_F11:
           scancode=SDL_SCANCODE_F11;
           break;
      case PHOTON_SCANCODE_F12:
           scancode=SDL_SCANCODE_F12;
           break;
      case PHOTON_SCANCODE_BACKQOUTE:
           scancode=SDL_SCANCODE_GRAVE;
           break;
      case PHOTON_SCANCODE_1:
           scancode=SDL_SCANCODE_1;
           break;
      case PHOTON_SCANCODE_2:
           scancode=SDL_SCANCODE_2;
           break;
      case PHOTON_SCANCODE_3:
           scancode=SDL_SCANCODE_3;
           break;
      case PHOTON_SCANCODE_4:
           scancode=SDL_SCANCODE_4;
           break;
      case PHOTON_SCANCODE_5:
           scancode=SDL_SCANCODE_5;
           break;
      case PHOTON_SCANCODE_6:
           scancode=SDL_SCANCODE_6;
           break;
      case PHOTON_SCANCODE_7:
           scancode=SDL_SCANCODE_7;
           break;
      case PHOTON_SCANCODE_8:
           scancode=SDL_SCANCODE_8;
           break;
      case PHOTON_SCANCODE_9:
           scancode=SDL_SCANCODE_9;
           break;
      case PHOTON_SCANCODE_0:
           scancode=SDL_SCANCODE_0;
           break;
      case PHOTON_SCANCODE_MINUS:
           scancode=SDL_SCANCODE_MINUS;
           break;
      case PHOTON_SCANCODE_EQUAL:
           scancode=SDL_SCANCODE_EQUALS;
           break;
      case PHOTON_SCANCODE_BACKSPACE:
           scancode=SDL_SCANCODE_BACKSPACE;
           break;
      case PHOTON_SCANCODE_TAB:
           scancode=SDL_SCANCODE_TAB;
           break;
      case PHOTON_SCANCODE_Q:
           scancode=SDL_SCANCODE_Q;
           break;
      case PHOTON_SCANCODE_W:
           scancode=SDL_SCANCODE_W;
           break;
      case PHOTON_SCANCODE_E:
           scancode=SDL_SCANCODE_E;
           break;
      case PHOTON_SCANCODE_R:
           scancode=SDL_SCANCODE_R;
           break;
      case PHOTON_SCANCODE_T:
           scancode=SDL_SCANCODE_T;
           break;
      case PHOTON_SCANCODE_Y:
           scancode=SDL_SCANCODE_Y;
           break;
      case PHOTON_SCANCODE_U:
           scancode=SDL_SCANCODE_U;
           break;
      case PHOTON_SCANCODE_I:
           scancode=SDL_SCANCODE_I;
           break;
      case PHOTON_SCANCODE_O:
           scancode=SDL_SCANCODE_O;
           break;
      case PHOTON_SCANCODE_P:
           scancode=SDL_SCANCODE_P;
           break;
      case PHOTON_SCANCODE_LEFT_SQ_BR:
           scancode=SDL_SCANCODE_LEFTBRACKET;
           break;
      case PHOTON_SCANCODE_RIGHT_SQ_BR:
           scancode=SDL_SCANCODE_RIGHTBRACKET;
           break;
      case PHOTON_SCANCODE_ENTER:
           scancode=SDL_SCANCODE_RETURN;
           break;
      case PHOTON_SCANCODE_CAPSLOCK:
           scancode=SDL_SCANCODE_CAPSLOCK;
           break;
      case PHOTON_SCANCODE_A:
           scancode=SDL_SCANCODE_A;
           break;
      case PHOTON_SCANCODE_S:
           scancode=SDL_SCANCODE_S;
           break;
      case PHOTON_SCANCODE_D:
           scancode=SDL_SCANCODE_D;
           break;
      case PHOTON_SCANCODE_F:
           scancode=SDL_SCANCODE_F;
           break;
      case PHOTON_SCANCODE_G:
           scancode=SDL_SCANCODE_G;
           break;
      case PHOTON_SCANCODE_H:
           scancode=SDL_SCANCODE_H;
           break;
      case PHOTON_SCANCODE_J:
           scancode=SDL_SCANCODE_J;
           break;
      case PHOTON_SCANCODE_K:
           scancode=SDL_SCANCODE_K;
           break;
      case PHOTON_SCANCODE_L:
           scancode=SDL_SCANCODE_L;
           break;
      case PHOTON_SCANCODE_SEMICOLON:
           scancode=SDL_SCANCODE_SEMICOLON;
           break;
      case PHOTON_SCANCODE_QUOTE:
           scancode=SDL_SCANCODE_APOSTROPHE;
           break;
      case PHOTON_SCANCODE_BACKSLASH:
           scancode=SDL_SCANCODE_BACKSLASH;
           break;
      case PHOTON_SCANCODE_LEFT_SHIFT:
           scancode=SDL_SCANCODE_LSHIFT;
           break;
      case PHOTON_SCANCODE_Z:
           scancode=SDL_SCANCODE_Z;
           break;
      case PHOTON_SCANCODE_X:
           scancode=SDL_SCANCODE_X;
           break;
      case PHOTON_SCANCODE_C:
           scancode=SDL_SCANCODE_C;
           break;
      case PHOTON_SCANCODE_V:
           scancode=SDL_SCANCODE_V;
           break;
      case PHOTON_SCANCODE_B:
           scancode=SDL_SCANCODE_B;
           break;
      case PHOTON_SCANCODE_N:
           scancode=SDL_SCANCODE_N;
           break;
      case PHOTON_SCANCODE_M:
           scancode=SDL_SCANCODE_M;
           break;
      case PHOTON_SCANCODE_COMMA:
           scancode=SDL_SCANCODE_COMMA;
           break;
      case PHOTON_SCANCODE_POINT:
           scancode=SDL_SCANCODE_PERIOD;
           break;
      case PHOTON_SCANCODE_SLASH:
           scancode=SDL_SCANCODE_SLASH;
           break;
      case PHOTON_SCANCODE_RIGHT_SHIFT:
           scancode=SDL_SCANCODE_RSHIFT;
           break;
      case PHOTON_SCANCODE_CTRL:
           scancode=SDL_SCANCODE_LCTRL;
           break;
      case PHOTON_SCANCODE_WFLAG:
           scancode=SDL_SCANCODE_LGUI;
           break;
      case PHOTON_SCANCODE_ALT:
           scancode=SDL_SCANCODE_LALT;
           break;
      case PHOTON_SCANCODE_SPACE:
           scancode=SDL_SCANCODE_SPACE;
           break;
      case PHOTON_SCANCODE_MENU:
           scancode=SDL_SCANCODE_MENU;
           break;
      case PHOTON_SCANCODE_PRNSCR:
           scancode=SDL_SCANCODE_PRINTSCREEN;
           break;
      case PHOTON_SCANCODE_SCROLLLOCK:
           scancode=SDL_SCANCODE_SCROLLLOCK;
           break;
      case PHOTON_SCANCODE_INSERT:
           scancode=SDL_SCANCODE_INSERT;
           break;
      case PHOTON_SCANCODE_HOME:
           scancode=SDL_SCANCODE_HOME;
           break;
      case PHOTON_SCANCODE_PAGEUP:
           scancode=SDL_SCANCODE_PAGEUP;
           break;
      case PHOTON_SCANCODE_DELETE:
           scancode=SDL_SCANCODE_DELETE;
           break;
      case PHOTON_SCANCODE_END:
           scancode=SDL_SCANCODE_END;
           break;
      case PHOTON_SCANCODE_PAGEDOWN:
           scancode=SDL_SCANCODE_PAGEDOWN;
           break;
      case PHOTON_SCANCODE_UP:
           scancode=SDL_SCANCODE_UP;
           break;
      case PHOTON_SCANCODE_DOWN:
           scancode=SDL_SCANCODE_DOWN;
           break;
      case PHOTON_SCANCODE_LEFT:
           scancode=SDL_SCANCODE_LEFT;
           break;
      case PHOTON_SCANCODE_RIGHT:
           scancode=SDL_SCANCODE_RIGHT;
           break;
      case PHOTON_SCANCODE_NUMLOCK:
           scancode=SDL_SCANCODE_NUMLOCKCLEAR;
           break;
      default:
           break;
   }

   return scancode;
}