src/video/riscos/SDL_riscosmouse.c
author Cameron Cawley <ccawley2011@gmail.com>
Tue, 18 Jun 2019 23:55:01 +0100
branchSDL-1.2
changeset 12913 d07b4feae69c
parent 12786 4e73be7b4787
permissions -rw-r--r--
riscos: Improve error reporting
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2012 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@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /*
    25      File added by Alan Buckley (alan_baa@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 /* Area to save cursor palette colours changed by SDL.
    43    Actual values will be read before we change to the SDL cursor */
    44 static Uint8 wimp_cursor_palette[2][5] = {
    45   {1, 25, 255, 255, 255},
    46   {3, 25, 255, 255, 255}
    47 };
    48 
    49 static int cursor_palette_saved = 0;
    50 
    51 static void WIMP_SaveCursorPalette();
    52 static void WIMP_SetSDLCursorPalette();
    53 
    54 
    55 void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor)
    56 {
    57     SDL_free(cursor->data);
    58 	SDL_free(cursor);
    59 }
    60 
    61 WMcursor *RISCOS_CreateWMCursor(_THIS,
    62 		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
    63 {
    64 	WMcursor *cursor;
    65 	Uint8 *cursor_data;
    66 	Uint8 *ptr;
    67 	int i,j,k;
    68 	int data_byte, mask_byte;
    69 
    70 	/* Check to make sure the cursor size is okay */
    71 	if ( (w > 32) || (h > 32) ) {
    72 		SDL_SetError("Only cursors with width and height <= 32 pixels are allowed");
    73 		return(NULL);
    74 	}
    75 
    76 	/* Allocate the cursor */
    77 	cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
    78 	if ( cursor == NULL ) {
    79 		SDL_OutOfMemory();
    80 		return(NULL);
    81 	}
    82 
    83 	/* Note: SDL says width must be a multiple of 8 */
    84 	cursor_data = SDL_malloc(w/4 * h);
    85 	if (cursor_data == NULL)
    86 	{
    87 		SDL_free(cursor);
    88 		SDL_OutOfMemory();
    89 		return(NULL);
    90 	}
    91 
    92 	cursor->w = w;
    93 	cursor->h = h;
    94 	cursor->hot_x = hot_x;
    95 	cursor->hot_y = hot_y;
    96 	cursor->data = cursor_data;
    97 
    98 
    99 /* Data / Mask Resulting pixel on screen 
   100    0 / 1 White 
   101    1 / 1 Black 
   102    0 / 0 Transparent 
   103    1 / 0 Inverted color if possible, black if not. 
   104 */
   105 	ptr = cursor_data;
   106 
   107 	for ( i=0; i<h; ++i )
   108 	{
   109 		for (j = 0; j < w/8; ++j)
   110 		{
   111 			data_byte = *data;
   112 			mask_byte = *mask;
   113 			*ptr++ = 0; /* Sets whole byte transparent */
   114 			*ptr = 0;
   115 			for (k = 0; k < 8; k++)
   116 			{
   117 				(*ptr) <<= 2;
   118 				if (data_byte & 1) *ptr |= 3; /* Black or inverted */
   119 				else if(mask_byte & 1) *ptr |= 1; /* White */
   120 				if ((k&3) == 3) ptr--;
   121 				data_byte >>= 1;
   122 				mask_byte >>= 1;
   123 			}
   124 
   125             ptr+=3;
   126 		    data++;
   127 		    mask++;
   128 		}
   129 	}
   130 
   131 	return(cursor);
   132 }
   133 
   134 int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor)
   135 {
   136 	current_cursor = cursor;
   137 
   138 	if (cursor == NULL)
   139 	{
   140 		_kernel_osbyte(106,0,0);
   141 		defined_cursor = NULL;
   142 	} else
   143 	{
   144         WMcursor *old_cursor = defined_cursor;
   145 
   146 		if (cursor != defined_cursor)
   147 		{
   148 			Uint8 cursor_def[10];
   149 
   150 			cursor_def[0] = 0;
   151 			cursor_def[1] = 2; /* Use shape number 2 */
   152 			cursor_def[2] = cursor->w/4; /* Width in bytes */
   153 			cursor_def[3] = cursor->h; /* Height (h) in pixels */
   154 			cursor_def[4] = cursor->hot_x; /* ActiveX in pixels from left */
   155 			cursor_def[5] = cursor->hot_y; /* ActiveY in pixels from top */
   156 			cursor_def[6] = ((int)(cursor->data) & 0xFF);       /* Least significant byte of pointer to data */
   157 			cursor_def[7] = ((int)(cursor->data) >> 8) & 0xFF;  /* ... */
   158 			cursor_def[8] = ((int)(cursor->data) >> 16) & 0xFF; /* ... */
   159 			cursor_def[9] = ((int)(cursor->data) >> 24) & 0xFF; /* Most significant byte of pointer to data */
   160 
   161 			if (_kernel_osword(21, (int *)cursor_def) != 0)
   162 			{
   163 				SDL_SetError("RISC OS couldn't create the cursor to show");
   164 				return(0);
   165 			}
   166 			defined_cursor = cursor;
   167 		}
   168 
   169         if (old_cursor == NULL)
   170         {
   171             /* First time or reshow in window, so save/setup palette */
   172             if (!cursor_palette_saved)
   173             {
   174                 WIMP_SaveCursorPalette();
   175             }
   176             WIMP_SetSDLCursorPalette();
   177         }
   178 
   179         _kernel_osbyte(106, 2, 0);        
   180 	}
   181 	
   182 	return(1);
   183 }
   184 
   185 void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
   186 {
   187 	Uint8 move_block[5];
   188 	int os_x, os_y;
   189 	int topLeftY;
   190 
   191 	topLeftY = (this->hidden->height << this->hidden->yeig) - 1; /* As per RISCOS_PollMouseHelper */
   192 
   193 	os_x = x << this->hidden->xeig;
   194 	os_y = topLeftY - (y << this->hidden->yeig);
   195 
   196 	move_block[0] = 3; /* Move cursor */
   197 	move_block[1] = os_x & 0xFF;
   198 	move_block[2] = (os_x >> 8) & 0xFF;
   199 	move_block[3] = os_y & 0xFF;
   200 	move_block[4] = (os_y >> 8) & 0xFF;
   201 
   202 	_kernel_osword(21, (int *)move_block);
   203 	SDL_PrivateMouseMotion(0, 0, x, y);
   204 }
   205 
   206 
   207 /* Reshow cursor when mouse re-enters the window */
   208 void WIMP_ReshowCursor(_THIS)
   209 {
   210 	defined_cursor = NULL;
   211     cursor_palette_saved = 0;
   212 	RISCOS_ShowWMCursor(this, current_cursor);
   213 }
   214 
   215 void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
   216 {
   217 	_kernel_swi_regs regs;
   218 	int window_state[9];
   219 	char block[5];
   220 	int osX, osY;
   221 
   222 	window_state[0] = this->hidden->window_handle;
   223 	regs.r[1] = (unsigned int)window_state;
   224 	_kernel_swi(Wimp_GetWindowState, &regs, &regs);
   225 
   226 	/* 90 DPI mapping from SDL pixels to OS units */
   227 	 osX = (x << 1) + window_state[1];
   228 	 osY = window_state[4] - (y << 1);
   229 
   230 	block[0] = 3;
   231 	block[1] = osX & 0xFF;
   232 	block[2] = (osX >> 8) & 0xFF;
   233 	block[3] = osY & 0xFF;
   234 	block[4] = (osY >> 8) & 0xFF;
   235 
   236 	_kernel_osword(21, (int *)block);
   237 	SDL_PrivateMouseMotion(0, 0, x, y);
   238 }
   239 
   240 int WIMP_ShowWMCursor(_THIS, WMcursor *cursor)
   241 {
   242 	if (mouseInWindow) return RISCOS_ShowWMCursor(this, cursor);
   243 	else current_cursor = cursor;
   244 
   245 	return 1;
   246 }
   247 
   248 SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode)
   249 {
   250    /* In fullscreen mode we don't need to do anything */
   251    if (mode < SDL_GRAB_FULLSCREEN)
   252    {
   253       _kernel_swi_regs regs;
   254       unsigned char block[9];
   255       block[0] = 1; /* Define mouse cursor bounding block */
   256 
   257       if ( mode == SDL_GRAB_OFF )
   258       {
   259          /* Clip to whole screen */
   260 
   261          int r = (this->hidden->screen_width << this->hidden->xeig) - 1;
   262          int t = (this->hidden->screen_height << this->hidden->yeig) - 1;
   263 
   264 	 block[1] = 0; block[2] = 0; /* Left*/
   265          block[3] = 0; block[4] = 0; /* Bottom */
   266          block[5] = r & 0xFF; block[6] = (r >> 8) & 0xFF; /* Right */
   267          block[7] = t & 0xFF; block[8] = (t >> 8) & 0xFF; /* Top */
   268       } else
   269       {
   270         /* Clip to window */
   271        	unsigned char window_state[36];
   272 
   273 	*((int *)window_state) = this->hidden->window_handle;
   274 	regs.r[1] = (unsigned int)window_state;
   275 	_kernel_swi(Wimp_GetWindowState, &regs, &regs);
   276 
   277         block[1] = window_state[4];
   278         block[2] = window_state[5];
   279         block[3] = window_state[8];
   280         block[4] = window_state[9];
   281         block[5] = window_state[12];
   282         block[6] = window_state[13];
   283         block[7] = window_state[16];
   284         block[8] = window_state[17];
   285 
   286       }
   287 
   288       _kernel_osword(21, (int *)block);
   289    }
   290 
   291    return mode;
   292 }
   293 
   294 /* Save mouse cursor palette to be restore when we are no longer
   295    defining a cursor */
   296 
   297 void WIMP_SaveCursorPalette()
   298 {
   299     _kernel_swi_regs regs;
   300     int colour;
   301 
   302     for (colour = 0; colour < 2; colour++)
   303     {
   304       regs.r[0] = (int)wimp_cursor_palette[colour][0];
   305       regs.r[1] = 25;
   306       /* Read settings with OS_ReadPalette */
   307       if (_kernel_swi(OS_ReadPalette, &regs, &regs) == NULL)
   308       {
   309         wimp_cursor_palette[colour][2] = (unsigned char)((regs.r[2] >> 8) & 0xFF);
   310         wimp_cursor_palette[colour][3] = (unsigned char)((regs.r[2] >> 16) & 0xFF);
   311         wimp_cursor_palette[colour][4] = (unsigned char)((regs.r[2] >> 24) & 0xFF);
   312       }
   313     }
   314 
   315     cursor_palette_saved = 1;
   316 }
   317 
   318 /* Restore the WIMP's cursor when we leave the SDL window */
   319 void WIMP_RestoreWimpCursor()
   320 {
   321     int colour;
   322 
   323     /* Reset to pointer shape 1 */
   324     _kernel_osbyte(106, 1, 0);
   325 
   326     /* Reset pointer colours */
   327     if (cursor_palette_saved)
   328     {
   329       for (colour = 0; colour < 2; colour++)
   330       {
   331         _kernel_osword(12, (int *)wimp_cursor_palette[colour]);
   332       }
   333     }
   334     cursor_palette_saved = 0;
   335 }
   336 
   337 /* Set palette used for SDL mouse cursors */
   338 void WIMP_SetSDLCursorPalette()
   339 {
   340   /* First time set up the mouse colours */
   341   Uint8 block[5];
   342 
   343   /* Set up colour 1 as white */
   344   block[0] = 1;   /* Colour to change 1 - 3 */
   345   block[1] = 25;  /* Set pointer colour */
   346   block[2] = 255; /* red component*/
   347   block[3] = 255; /* green component */
   348   block[4] = 255; /* blue component*/
   349  _kernel_osword(12, (int *)block);
   350 		
   351  /* Set colour 3 to back */
   352  block[0] = 3;   /* Colour to change 1 - 3 */
   353  block[1] = 25;  /* Set pointer colour*/
   354  block[2] = 0; /* red component*/
   355  block[3] = 0; /* green component */
   356  block[4] = 0; /* blue component*/
   357  _kernel_osword(12, (int *)block);
   358 }