SDL_DirectFB_mouse.c (11707B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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 35static SDL_Cursor *DirectFB_CreateDefaultCursor(void); 36static SDL_Cursor *DirectFB_CreateCursor(SDL_Surface * surface, 37 int hot_x, int hot_y); 38static int DirectFB_ShowCursor(SDL_Cursor * cursor); 39static void DirectFB_MoveCursor(SDL_Cursor * cursor); 40static void DirectFB_FreeCursor(SDL_Cursor * cursor); 41static void DirectFB_WarpMouse(SDL_Window * window, int x, int y); 42static void DirectFB_FreeMouse(SDL_Mouse * mouse); 43 44static 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 80static SDL_Cursor * 81DirectFB_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 */ 135static SDL_Cursor * 136DirectFB_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 */ 183static int 184DirectFB_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 */ 225static void 226DirectFB_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) */ 236static void 237DirectFB_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 256static void DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window, 257 int x, int y); 258 259static int id_mask; 260 261static DFBEnumerationResult 262EnumMice(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 286void 287DirectFB_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 319void 320DirectFB_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 */ 333static void 334DirectFB_MoveCursor(SDL_Cursor * cursor) 335{ 336 337} 338 339/* Warp the mouse to (x,y) */ 340static void 341DirectFB_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 */ 359static void 360DirectFB_FreeMouse(SDL_Mouse * mouse) 361{ 362 /* nothing yet */ 363} 364 365#else /* USE_MULTI_API */ 366 367void 368DirectFB_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 384void 385DirectFB_QuitMouse(_THIS) 386{ 387} 388 389 390#endif 391 392#endif /* SDL_VIDEO_DRIVER_DIRECTFB */ 393 394/* vi: set ts=4 sw=4 expandtab: */