Home | History | Annotate | Download | only in riscos
      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, &regs, &regs);
    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, &regs, &regs);
    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, &regs, &regs);
    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, &regs, &regs);
    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, &regs, &regs);
    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, &regs, &regs) == 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