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