src/video/directfb/SDL_DirectFB_mouse.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 30 Oct 2016 21:01:33 +0100
changeset 10563 e3d84016cb79
parent 9998 f67cf37e9cd4
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed outdated info in README.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_DIRECTFB
    24 
    25 #include "SDL_assert.h"
    26 
    27 #include "SDL_DirectFB_video.h"
    28 #include "SDL_DirectFB_mouse.h"
    29 #include "SDL_DirectFB_modes.h"
    30 #include "SDL_DirectFB_window.h"
    31 
    32 #include "../SDL_sysvideo.h"
    33 #include "../../events/SDL_mouse_c.h"
    34 
    35 static SDL_Cursor *DirectFB_CreateDefaultCursor(void);
    36 static SDL_Cursor *DirectFB_CreateCursor(SDL_Surface * surface,
    37                                          int hot_x, int hot_y);
    38 static int DirectFB_ShowCursor(SDL_Cursor * cursor);
    39 static void DirectFB_MoveCursor(SDL_Cursor * cursor);
    40 static void DirectFB_FreeCursor(SDL_Cursor * cursor);
    41 static void DirectFB_WarpMouse(SDL_Window * window, int x, int y);
    42 static void DirectFB_FreeMouse(SDL_Mouse * mouse);
    43 
    44 static const char *arrow[] = {
    45     /* pixels */
    46     "X                               ",
    47     "XX                              ",
    48     "X.X                             ",
    49     "X..X                            ",
    50     "X...X                           ",
    51     "X....X                          ",
    52     "X.....X                         ",
    53     "X......X                        ",
    54     "X.......X                       ",
    55     "X........X                      ",
    56     "X.....XXXXX                     ",
    57     "X..X..X                         ",
    58     "X.X X..X                        ",
    59     "XX  X..X                        ",
    60     "X    X..X                       ",
    61     "     X..X                       ",
    62     "      X..X                      ",
    63     "      X..X                      ",
    64     "       XX                       ",
    65     "                                ",
    66     "                                ",
    67     "                                ",
    68     "                                ",
    69     "                                ",
    70     "                                ",
    71     "                                ",
    72     "                                ",
    73     "                                ",
    74     "                                ",
    75     "                                ",
    76     "                                ",
    77     "                                ",
    78 };
    79 
    80 static SDL_Cursor *
    81 DirectFB_CreateDefaultCursor(void)
    82 {
    83     SDL_VideoDevice *dev = SDL_GetVideoDevice();
    84 
    85     SDL_DFB_DEVICEDATA(dev);
    86     DFB_CursorData *curdata;
    87     DFBResult ret;
    88     DFBSurfaceDescription dsc;
    89     SDL_Cursor *cursor;
    90     Uint32 *dest;
    91     Uint32 *p;
    92     int pitch, i, j;
    93 
    94     SDL_DFB_ALLOC_CLEAR( cursor, sizeof(*cursor));
    95     SDL_DFB_ALLOC_CLEAR(curdata, sizeof(*curdata));
    96 
    97     dsc.flags =
    98         DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
    99     dsc.caps = DSCAPS_VIDEOONLY;
   100     dsc.width = 32;
   101     dsc.height = 32;
   102     dsc.pixelformat = DSPF_ARGB;
   103 
   104     SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   105                                                  &curdata->surf));
   106     curdata->hotx = 0;
   107     curdata->hoty = 0;
   108     cursor->driverdata = curdata;
   109 
   110     SDL_DFB_CHECKERR(curdata->surf->Lock(curdata->surf, DSLF_WRITE,
   111                                          (void *) &dest, &pitch));
   112 
   113     /* Relies on the fact that this is only called with ARGB surface. */
   114     for (i = 0; i < 32; i++)
   115     {
   116         for (j = 0; j < 32; j++)
   117         {
   118             switch (arrow[i][j])
   119             {
   120             case ' ': dest[j] = 0x00000000; break;
   121             case '.': dest[j] = 0xffffffff; break;
   122             case 'X': dest[j] = 0xff000000; break;
   123             }
   124         }
   125         dest += (pitch >> 2);
   126     }
   127 
   128     curdata->surf->Unlock(curdata->surf);
   129     return cursor;
   130   error:
   131     return NULL;
   132 }
   133 
   134 /* Create a cursor from a surface */
   135 static SDL_Cursor *
   136 DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
   137 {
   138     SDL_VideoDevice *dev = SDL_GetVideoDevice();
   139 
   140     SDL_DFB_DEVICEDATA(dev);
   141     DFB_CursorData *curdata;
   142     DFBResult ret;
   143     DFBSurfaceDescription dsc;
   144     SDL_Cursor *cursor;
   145     Uint32 *dest;
   146     Uint32 *p;
   147     int pitch, i;
   148 
   149     SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
   150     SDL_assert(surface->pitch == surface->w * 4);
   151 
   152     SDL_DFB_ALLOC_CLEAR( cursor, sizeof(*cursor));
   153     SDL_DFB_ALLOC_CLEAR(curdata, sizeof(*curdata));
   154 
   155     dsc.flags =
   156         DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   157     dsc.caps = DSCAPS_VIDEOONLY;
   158     dsc.width = surface->w;
   159     dsc.height = surface->h;
   160     dsc.pixelformat = DSPF_ARGB;
   161 
   162     SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   163                                                  &curdata->surf));
   164     curdata->hotx = hot_x;
   165     curdata->hoty = hot_y;
   166     cursor->driverdata = curdata;
   167 
   168     SDL_DFB_CHECKERR(curdata->surf->Lock(curdata->surf, DSLF_WRITE,
   169                                          (void *) &dest, &pitch));
   170 
   171     p = surface->pixels;
   172     for (i = 0; i < surface->h; i++)
   173         memcpy((char *) dest + i * pitch,
   174                (char *) p + i * surface->pitch, 4 * surface->w);
   175 
   176     curdata->surf->Unlock(curdata->surf);
   177     return cursor;
   178   error:
   179     return NULL;
   180 }
   181 
   182 /* Show the specified cursor, or hide if cursor is NULL */
   183 static int
   184 DirectFB_ShowCursor(SDL_Cursor * cursor)
   185 {
   186     SDL_DFB_CURSORDATA(cursor);
   187     DFBResult ret;
   188     SDL_Window *window;
   189 
   190     window = SDL_GetFocusWindow();
   191     if (!window)
   192         return -1;
   193     else {
   194         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   195 
   196         if (display) {
   197             DFB_DisplayData *dispdata =
   198                 (DFB_DisplayData *) display->driverdata;
   199             DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
   200 
   201             if (cursor)
   202                 SDL_DFB_CHECKERR(windata->dfbwin->
   203                                  SetCursorShape(windata->dfbwin,
   204                                                 curdata->surf, curdata->hotx,
   205                                                 curdata->hoty));
   206 
   207             SDL_DFB_CHECKERR(dispdata->layer->
   208                              SetCooperativeLevel(dispdata->layer,
   209                                                  DLSCL_ADMINISTRATIVE));
   210             SDL_DFB_CHECKERR(dispdata->layer->
   211                              SetCursorOpacity(dispdata->layer,
   212                                               cursor ? 0xC0 : 0x00));
   213             SDL_DFB_CHECKERR(dispdata->layer->
   214                              SetCooperativeLevel(dispdata->layer,
   215                                                  DLSCL_SHARED));
   216         }
   217     }
   218 
   219     return 0;
   220   error:
   221     return -1;
   222 }
   223 
   224 /* Free a window manager cursor */
   225 static void
   226 DirectFB_FreeCursor(SDL_Cursor * cursor)
   227 {
   228     SDL_DFB_CURSORDATA(cursor);
   229 
   230     SDL_DFB_RELEASE(curdata->surf);
   231     SDL_DFB_FREE(cursor->driverdata);
   232     SDL_DFB_FREE(cursor);
   233 }
   234 
   235 /* Warp the mouse to (x,y) */
   236 static void
   237 DirectFB_WarpMouse(SDL_Window * window, int x, int y)
   238 {
   239     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   240     DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   241     DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
   242     DFBResult ret;
   243     int cx, cy;
   244 
   245     SDL_DFB_CHECKERR(windata->dfbwin->GetPosition(windata->dfbwin, &cx, &cy));
   246     SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer,
   247                                                  cx + x + windata->client.x,
   248                                                  cy + y + windata->client.y));
   249 
   250   error:
   251     return;
   252 }
   253 
   254 #if USE_MULTI_API
   255 
   256 static void DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window,
   257                                int x, int y);
   258 
   259 static int id_mask;
   260 
   261 static DFBEnumerationResult
   262 EnumMice(DFBInputDeviceID device_id, DFBInputDeviceDescription desc,
   263          void *callbackdata)
   264 {
   265     DFB_DeviceData *devdata = callbackdata;
   266 
   267     if ((desc.type & DIDTF_MOUSE) && (device_id & id_mask)) {
   268         SDL_Mouse mouse;
   269 
   270         SDL_zero(mouse);
   271         mouse.id = device_id;
   272         mouse.CreateCursor = DirectFB_CreateCursor;
   273         mouse.ShowCursor = DirectFB_ShowCursor;
   274         mouse.MoveCursor = DirectFB_MoveCursor;
   275         mouse.FreeCursor = DirectFB_FreeCursor;
   276         mouse.WarpMouse = DirectFB_WarpMouse;
   277         mouse.FreeMouse = DirectFB_FreeMouse;
   278         mouse.cursor_shown = 1;
   279 
   280         SDL_AddMouse(&mouse, desc.name, 0, 0, 1);
   281         devdata->mouse_id[devdata->num_mice++] = device_id;
   282     }
   283     return DFENUM_OK;
   284 }
   285 
   286 void
   287 DirectFB_InitMouse(_THIS)
   288 {
   289     SDL_DFB_DEVICEDATA(_this);
   290 
   291     devdata->num_mice = 0;
   292     if (devdata->use_linux_input) {
   293         /* try non-core devices first */
   294         id_mask = 0xF0;
   295         devdata->dfb->EnumInputDevices(devdata->dfb, EnumMice, devdata);
   296         if (devdata->num_mice == 0) {
   297             /* try core devices */
   298             id_mask = 0x0F;
   299             devdata->dfb->EnumInputDevices(devdata->dfb, EnumMice, devdata);
   300         }
   301     }
   302     if (devdata->num_mice == 0) {
   303         SDL_Mouse mouse;
   304 
   305         SDL_zero(mouse);
   306         mouse.CreateCursor = DirectFB_CreateCursor;
   307         mouse.ShowCursor = DirectFB_ShowCursor;
   308         mouse.MoveCursor = DirectFB_MoveCursor;
   309         mouse.FreeCursor = DirectFB_FreeCursor;
   310         mouse.WarpMouse = DirectFB_WarpMouse;
   311         mouse.FreeMouse = DirectFB_FreeMouse;
   312         mouse.cursor_shown = 1;
   313 
   314         SDL_AddMouse(&mouse, "Mouse", 0, 0, 1);
   315         devdata->num_mice = 1;
   316     }
   317 }
   318 
   319 void
   320 DirectFB_QuitMouse(_THIS)
   321 {
   322     SDL_DFB_DEVICEDATA(_this);
   323 
   324     if (devdata->use_linux_input) {
   325         SDL_MouseQuit();
   326     } else {
   327         SDL_DelMouse(0);
   328     }
   329 }
   330 
   331 
   332 /* This is called when a mouse motion event occurs */
   333 static void
   334 DirectFB_MoveCursor(SDL_Cursor * cursor)
   335 {
   336 
   337 }
   338 
   339 /* Warp the mouse to (x,y) */
   340 static void
   341 DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window, int x, int y)
   342 {
   343     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   344     DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   345     DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
   346     DFBResult ret;
   347     int cx, cy;
   348 
   349     SDL_DFB_CHECKERR(windata->dfbwin->GetPosition(windata->dfbwin, &cx, &cy));
   350     SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer,
   351                                                  cx + x + windata->client.x,
   352                                                  cy + y + windata->client.y));
   353 
   354   error:
   355     return;
   356 }
   357 
   358 /* Free the mouse when it's time */
   359 static void
   360 DirectFB_FreeMouse(SDL_Mouse * mouse)
   361 {
   362     /* nothing yet */
   363 }
   364 
   365 #else /* USE_MULTI_API */
   366 
   367 void
   368 DirectFB_InitMouse(_THIS)
   369 {
   370     SDL_DFB_DEVICEDATA(_this);
   371 
   372     SDL_Mouse *mouse = SDL_GetMouse();
   373 
   374     mouse->CreateCursor = DirectFB_CreateCursor;
   375     mouse->ShowCursor = DirectFB_ShowCursor;
   376     mouse->WarpMouse = DirectFB_WarpMouse;
   377     mouse->FreeCursor = DirectFB_FreeCursor;
   378 
   379     SDL_SetDefaultCursor(DirectFB_CreateDefaultCursor());
   380 
   381     devdata->num_mice = 1;
   382 }
   383 
   384 void
   385 DirectFB_QuitMouse(_THIS)
   386 {
   387 }
   388 
   389 
   390 #endif
   391 
   392 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
   393 
   394 /* vi: set ts=4 sw=4 expandtab: */