1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2004 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public 16 License along with this library; if not, write to the Free 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* 25 File added by Alan Buckley (alan_baa (at) hotmail.com) for RISC OS compatability 26 27 March 2003 27 28 Implements mouse cursor shape definitions and positioning 29 */ 30 31 #include "SDL_mouse.h" 32 #include "../../events/SDL_events_c.h" 33 34 #include "SDL_riscosmouse_c.h" 35 36 #include "kernel.h" 37 #include "swis.h" 38 39 static WMcursor *current_cursor = NULL; 40 static WMcursor *defined_cursor = NULL; 41 42 extern int mouseInWindow; 43 44 /* Area to save cursor palette colours changed by SDL. 45 Actual values will be read before we change to the SDL cursor */ 46 static Uint8 wimp_cursor_palette[2][5] = { 47 {1, 25, 255, 255, 255}, 48 {3, 25, 255, 255, 255} 49 }; 50 51 static int cursor_palette_saved = 0; 52 53 void WIMP_SaveCursorPalette(); 54 void WIMP_RestoreWimpCursor(); 55 void WIMP_SetSDLCursorPalette(); 56 57 58 void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor) 59 { 60 SDL_free(cursor->data); 61 SDL_free(cursor); 62 } 63 64 WMcursor *RISCOS_CreateWMCursor(_THIS, 65 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) 66 { 67 WMcursor *cursor; 68 Uint8 *cursor_data; 69 Uint8 *ptr; 70 int i,j,k; 71 int data_byte, mask_byte; 72 73 /* Check to make sure the cursor size is okay */ 74 if ( (w > 32) || (h > 32) ) { 75 SDL_SetError("Only with width and height <= 32 pixels are allowed"); 76 return(NULL); 77 } 78 79 /* Allocate the cursor */ 80 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); 81 if ( cursor == NULL ) { 82 SDL_SetError("Out of memory"); 83 return(NULL); 84 } 85 86 /* Note: SDL says width must be a multiple of 8 */ 87 cursor_data = SDL_malloc(w/4 * h); 88 if (cursor_data == NULL) 89 { 90 SDL_free(cursor); 91 SDL_SetError("Out of memory"); 92 return(NULL); 93 } 94 95 cursor->w = w; 96 cursor->h = h; 97 cursor->hot_x = hot_x; 98 cursor->hot_y = hot_y; 99 cursor->data = cursor_data; 100 101 102 /* Data / Mask Resulting pixel on screen 103 0 / 1 White 104 1 / 1 Black 105 0 / 0 Transparent 106 1 / 0 Inverted color if possible, black if not. 107 */ 108 ptr = cursor_data; 109 110 for ( i=0; i<h; ++i ) 111 { 112 for (j = 0; j < w/8; ++j) 113 { 114 data_byte = *data; 115 mask_byte = *mask; 116 *ptr++ = 0; /* Sets whole byte transparent */ 117 *ptr = 0; 118 for (k = 0; k < 8; k++) 119 { 120 (*ptr) <<= 2; 121 if (data_byte & 1) *ptr |= 3; /* Black or inverted */ 122 else if(mask_byte & 1) *ptr |= 1; /* White */ 123 if ((k&3) == 3) ptr--; 124 data_byte >>= 1; 125 mask_byte >>= 1; 126 } 127 128 ptr+=3; 129 data++; 130 mask++; 131 } 132 } 133 134 return(cursor); 135 } 136 137 int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor) 138 { 139 current_cursor = cursor; 140 141 if (cursor == NULL) 142 { 143 _kernel_osbyte(106,0,0); 144 defined_cursor = NULL; 145 } else 146 { 147 WMcursor *old_cursor = defined_cursor; 148 149 if (cursor != defined_cursor) 150 { 151 Uint8 cursor_def[10]; 152 153 cursor_def[0] = 0; 154 cursor_def[1] = 2; /* Use shape number 2 */ 155 cursor_def[2] = cursor->w/4; /* Width in bytes */ 156 cursor_def[3] = cursor->h; /* Height (h) in pixels */ 157 cursor_def[4] = cursor->hot_x; /* ActiveX in pixels from left */ 158 cursor_def[5] = cursor->hot_y; /* ActiveY in pixels from top */ 159 cursor_def[6] = ((int)(cursor->data) & 0xFF); /* Least significant byte of pointer to data */ 160 cursor_def[7] = ((int)(cursor->data) >> 8) & 0xFF; /* ... */ 161 cursor_def[8] = ((int)(cursor->data) >> 16) & 0xFF; /* ... */ 162 cursor_def[9] = ((int)(cursor->data) >> 24) & 0xFF; /* Most significant byte of pointer to data */ 163 164 if (_kernel_osword(21, (int *)cursor_def) != 0) 165 { 166 SDL_SetError("RISCOS couldn't create the cursor to show"); 167 return(0); 168 } 169 defined_cursor = cursor; 170 } 171 172 if (old_cursor == NULL) 173 { 174 /* First time or reshow in window, so save/setup palette */ 175 if (!cursor_palette_saved) 176 { 177 WIMP_SaveCursorPalette(); 178 } 179 WIMP_SetSDLCursorPalette(); 180 } 181 182 _kernel_osbyte(106, 2, 0); 183 } 184 185 return(1); 186 } 187 188 void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) 189 { 190 Uint8 move_block[5]; 191 int eig_block[3]; 192 _kernel_swi_regs regs; 193 int os_x, os_y; 194 195 eig_block[0] = 4; /* X eig factor */ 196 eig_block[1] = 5; /* Y eig factor */ 197 eig_block[2] = -1; /* End of list of variables to request */ 198 199 regs.r[0] = (int)eig_block; 200 regs.r[1] = (int)eig_block; 201 _kernel_swi(OS_ReadVduVariables, ®s, ®s); 202 203 os_x = x << eig_block[0]; 204 os_y = y << eig_block[1]; 205 206 move_block[0] = 3; /* Move cursor */ 207 move_block[1] = os_x & 0xFF; 208 move_block[2] = (os_x >> 8) & 0xFF; 209 move_block[3] = os_y & 0xFF; 210 move_block[4] = (os_y >> 8) & 0xFF; 211 212 _kernel_osword(21, (int *)move_block); 213 SDL_PrivateMouseMotion(0, 0, x, y); 214 } 215 216 217 /* Reshow cursor when mouse re-enters the window */ 218 void WIMP_ReshowCursor(_THIS) 219 { 220 defined_cursor = NULL; 221 cursor_palette_saved = 0; 222 RISCOS_ShowWMCursor(this, current_cursor); 223 } 224 225 void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y) 226 { 227 _kernel_swi_regs regs; 228 int window_state[9]; 229 char block[5]; 230 int osX, osY; 231 232 window_state[0] = this->hidden->window_handle; 233 regs.r[1] = (unsigned int)window_state; 234 _kernel_swi(Wimp_GetWindowState, ®s, ®s); 235 236 osX = (x << this->hidden->xeig) + window_state[1]; 237 osY = window_state[4] - (y << this->hidden->yeig); 238 239 block[0] = 3; 240 block[1] = osX & 0xFF; 241 block[2] = (osX >> 8) & 0xFF; 242 block[3] = osY & 0xFF; 243 block[4] = (osY >> 8) & 0xFF; 244 245 regs.r[0] = 21; 246 regs.r[1] = (int)block; 247 _kernel_swi(OS_Word, ®s, ®s); 248 SDL_PrivateMouseMotion(0, 0, x, y); 249 } 250 251 int WIMP_ShowWMCursor(_THIS, WMcursor *cursor) 252 { 253 if (mouseInWindow) return RISCOS_ShowWMCursor(this, cursor); 254 else current_cursor = cursor; 255 256 return 1; 257 } 258 259 SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode) 260 { 261 /* In fullscreen mode we don't need to do anything */ 262 if (mode < SDL_GRAB_FULLSCREEN) 263 { 264 _kernel_swi_regs regs; 265 unsigned char block[9]; 266 block[0] = 1; /* Define mouse cursor bounding block */ 267 268 if ( mode == SDL_GRAB_OFF ) 269 { 270 /* Clip to whole screen */ 271 272 int r = (this->hidden->screen_width << this->hidden->xeig) - 1; 273 int t = (this->hidden->screen_height << this->hidden->yeig) - 1; 274 275 block[1] = 0; block[2] = 0; /* Left*/ 276 block[3] = 0; block[4] = 0; /* Bottom */ 277 block[5] = r & 0xFF; block[6] = (r >> 8) & 0xFF; /* Right */ 278 block[7] = t & 0xFF; block[8] = (t >> 8) & 0xFF; /* Top */ 279 } else 280 { 281 /* Clip to window */ 282 unsigned char window_state[36]; 283 284 *((int *)window_state) = this->hidden->window_handle; 285 regs.r[1] = (unsigned int)window_state; 286 _kernel_swi(Wimp_GetWindowState, ®s, ®s); 287 288 block[1] = window_state[4]; 289 block[2] = window_state[5]; 290 block[3] = window_state[8]; 291 block[4] = window_state[9]; 292 block[5] = window_state[12]; 293 block[6] = window_state[13]; 294 block[7] = window_state[16]; 295 block[8] = window_state[17]; 296 297 } 298 299 regs.r[0] = 21; /* OS word code */ 300 regs.r[1] = (int)block; 301 _kernel_swi(OS_Word, ®s, ®s); 302 } 303 304 return mode; 305 } 306 307 /* Save mouse cursor palette to be restore when we are no longer 308 defining a cursor */ 309 310 void WIMP_SaveCursorPalette() 311 { 312 _kernel_swi_regs regs; 313 int colour; 314 315 for (colour = 0; colour < 2; colour++) 316 { 317 regs.r[0] = (int)wimp_cursor_palette[colour][0]; 318 regs.r[1] = 25; 319 /* Read settings with OS_ReadPalette */ 320 if (_kernel_swi(0x2f, ®s, ®s) == NULL) 321 { 322 wimp_cursor_palette[colour][2] = (unsigned char)((regs.r[2] >> 8) & 0xFF); 323 wimp_cursor_palette[colour][3] = (unsigned char)((regs.r[2] >> 16) & 0xFF); 324 wimp_cursor_palette[colour][4] = (unsigned char)((regs.r[2] >> 24) & 0xFF); 325 } 326 } 327 328 cursor_palette_saved = 1; 329 } 330 331 /* Restore the WIMP's cursor when we leave the SDL window */ 332 void WIMP_RestoreWimpCursor() 333 { 334 int colour; 335 336 /* Reset to pointer shape 1 */ 337 _kernel_osbyte(106, 1, 0); 338 339 /* Reset pointer colours */ 340 if (cursor_palette_saved) 341 { 342 for (colour = 0; colour < 2; colour++) 343 { 344 _kernel_osword(12, (int *)wimp_cursor_palette[colour]); 345 } 346 } 347 cursor_palette_saved = 0; 348 } 349 350 /* Set palette used for SDL mouse cursors */ 351 void WIMP_SetSDLCursorPalette() 352 { 353 /* First time set up the mouse colours */ 354 Uint8 block[5]; 355 356 /* Set up colour 1 as white */ 357 block[0] = 1; /* Colour to change 1 - 3 */ 358 block[1] = 25; /* Set pointer colour */ 359 block[2] = 255; /* red component*/ 360 block[3] = 255; /* green component */ 361 block[4] = 255; /* blue component*/ 362 _kernel_osword(12, (int *)block); 363 364 /* Set colour 3 to back */ 365 block[0] = 3; /* Colour to change 1 - 3 */ 366 block[1] = 25; /* Set pointer colour*/ 367 block[2] = 0; /* red component*/ 368 block[3] = 0; /* green component */ 369 block[4] = 0; /* blue component*/ 370 _kernel_osword(12, (int *)block); 371 } 372