src/video/riscos/SDL_riscosmouse.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 May 2003 04:44:13 +0000
changeset 630 550bccdf04bd
child 769 b8d311d90021
permissions -rw-r--r--
Added initial support for RISC OS (thanks Peter Naulls!)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001  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@devolution.com
    21 */
    22 
    23 /*
    24      File added by Alan Buckley (alan_baa@hotmail.com) for RISCOS compatability
    25 	 27 March 2003
    26 
    27      Implements mouse cursor shape definitions and positioning
    28 */
    29 
    30 #include <stdio.h>
    31 #include <stdlib.h>
    32 
    33 #include "SDL_error.h"
    34 #include "SDL_mouse.h"
    35 #include "SDL_events_c.h"
    36 
    37 #include "SDL_riscosmouse_c.h"
    38 
    39 #include "kernel.h"
    40 #include "swis.h"
    41 
    42 static WMcursor *current_cursor = NULL;
    43 
    44 extern int mouseInWindow;
    45 
    46 void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor)
    47 {
    48     free(cursor->data);
    49 	free(cursor);
    50 }
    51 
    52 WMcursor *RISCOS_CreateWMCursor(_THIS,
    53 		Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
    54 {
    55 	WMcursor *cursor;
    56 	Uint8 *cursor_data;
    57 	Uint8 *ptr;
    58 	int i,j,k;
    59 	int data_byte, mask_byte;
    60 
    61 	/* Check to make sure the cursor size is okay */
    62 	if ( (w > 32) || (h > 32) ) {
    63 		SDL_SetError("Only with width and height <= 32 pixels are allowed");
    64 		return(NULL);
    65 	}
    66 
    67 	/* Allocate the cursor */
    68 	cursor = (WMcursor *)malloc(sizeof(*cursor));
    69 	if ( cursor == NULL ) {
    70 		SDL_SetError("Out of memory");
    71 		return(NULL);
    72 	}
    73 
    74 	/* Note: SDL says width must be a multiple of 8 */
    75 	cursor_data = malloc(w/4 * h);
    76 	if (cursor_data == NULL)
    77 	{
    78 		free(cursor);
    79 		SDL_SetError("Out of memory");
    80 		return(NULL);
    81 	}
    82 
    83 	cursor->w = w;
    84 	cursor->h = h;
    85 	cursor->hot_x = hot_x;
    86 	cursor->hot_y = hot_y;
    87 	cursor->data = cursor_data;
    88 
    89 
    90 /* Data / Mask Resulting pixel on screen 
    91    0 / 1 White 
    92    1 / 1 Black 
    93    0 / 0 Transparent 
    94    1 / 0 Inverted color if possible, black if not. 
    95 */
    96 	ptr = cursor_data;
    97 
    98 	for ( i=0; i<h; ++i )
    99 	{
   100 		for (j = 0; j < w/8; ++j)
   101 		{
   102 			data_byte = *data;
   103 			mask_byte = *mask;
   104 			*ptr++ = 0; /* Sets whole byte transparent */
   105 			*ptr = 0;
   106 			for (k = 0; k < 8; k++)
   107 			{
   108 				(*ptr) <<= 2;
   109 				if (data_byte & 1) *ptr |= 3; /* Black or inverted */
   110 				else if(mask_byte & 1) *ptr |= 1; /* White */
   111 				if ((k&3) == 3) ptr--;
   112 				data_byte >>= 1;
   113 				mask_byte >>= 1;
   114 			}
   115 
   116             ptr+=3;
   117 		    data++;
   118 		    mask++;
   119 		}
   120 	}
   121 
   122 	return(cursor);
   123 }
   124 
   125 int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor)
   126 {
   127 	if (cursor == NULL)
   128 	{
   129 		_kernel_osbyte(106,0,0);
   130 		current_cursor = NULL;
   131 	} else
   132 	{
   133 		if (current_cursor == NULL)
   134 		{
   135 			/* First time set up the mouse colours */
   136 			Uint8 block[5];
   137 
   138 			/* Set up colour 1 as white */
   139 			block[0] = 1;   /* Colour to change 1 - 3 */
   140 			block[1] = 25;  /* Set pointer colour */
   141 			block[2] = 255; /* red component*/
   142 			block[3] = 255; /* green component */
   143 			block[4] = 255; /* blue component*/
   144 			_kernel_osword(12, (int *)block);
   145 		
   146 			/* Set colour 3 to back */
   147 			block[0] = 3;   /* Colour to change 1 - 3 */
   148 			block[1] = 25;  /* Set pointer colour*/
   149 			block[2] = 0; /* red component*/
   150 			block[3] = 0; /* green component */
   151 			block[4] = 0; /* blue component*/
   152 			_kernel_osword(12, (int *)block);
   153 		}
   154 
   155 		if (cursor != current_cursor)
   156 		{
   157 			Uint8 cursor_def[10];
   158 
   159 			cursor_def[0] = 0;
   160 			cursor_def[1] = 2; /* Use shape number 2 */
   161 			cursor_def[2] = cursor->w/4; /* Width in bytes */
   162 			cursor_def[3] = cursor->h; /* Height (h) in pixels */
   163 			cursor_def[4] = cursor->hot_x; /* ActiveX in pixels from left */
   164 			cursor_def[5] = cursor->hot_y; /* ActiveY in pixels from top */
   165 			cursor_def[6] = ((int)(cursor->data) & 0xFF);       /* Least significant byte of pointer to data */
   166 			cursor_def[7] = ((int)(cursor->data) >> 8) & 0xFF;  /* ... */
   167 			cursor_def[8] = ((int)(cursor->data) >> 16) & 0xFF; /* ... */
   168 			cursor_def[9] = ((int)(cursor->data) >> 24) & 0xFF; /* Most significant byte of pointer to data */
   169 
   170 			if (_kernel_osword(21, (int *)cursor_def) == 0)
   171 			{
   172 				SDL_SetError("RISCOS couldn't create the cursor to show");
   173 				return(0);
   174 			}
   175 			current_cursor = cursor;
   176 		}
   177 
   178 		if ((this->screen->flags & SDL_FULLSCREEN) || mouseInWindow) _kernel_osbyte(106, 2, 0);
   179 	}
   180 	
   181 	return(1);
   182 }
   183 
   184 void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
   185 {
   186 	Uint8 move_block[5];
   187 	int eig_block[3];
   188 	_kernel_swi_regs regs;
   189 	int os_x, os_y;
   190 
   191 	eig_block[0] = 4;  /* X eig factor */
   192 	eig_block[1] = 5;  /* Y eig factor */
   193 	eig_block[2] = -1;  /* End of list of variables to request */
   194 
   195     regs.r[0] = (int)eig_block;
   196     regs.r[1] = (int)eig_block;
   197     _kernel_swi(OS_ReadVduVariables, &regs, &regs);
   198 
   199 	os_x = x << eig_block[0];
   200 	os_y = y << eig_block[1];
   201 
   202 	move_block[0] = 3; /* Move cursor */
   203 	move_block[1] = os_x & 0xFF;
   204 	move_block[2] = (os_x >> 8) & 0xFF;
   205 	move_block[3] = os_y & 0xFF;
   206 	move_block[4] = (os_y >> 8) & 0xFF;
   207 
   208 	_kernel_osword(21, (int *)move_block);
   209 	SDL_PrivateMouseMotion(0, 0, x, y);
   210 }
   211 
   212 
   213 /* Reshow cursor when mouse re-enters the window */
   214 void WIMP_ReshowCursor(_THIS)
   215 {
   216 	WMcursor *cursor = current_cursor;
   217 	current_cursor = NULL;
   218 	RISCOS_ShowWMCursor(this, cursor);
   219 }
   220 
   221 extern int mouseInWindow;
   222 
   223 void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
   224 {
   225 	_kernel_swi_regs regs;
   226 	int window_state[9];
   227 	char block[5];
   228 	int osX, osY;
   229 
   230 	window_state[0] = this->hidden->window_handle;
   231 	regs.r[1] = (unsigned int)window_state;
   232 	_kernel_swi(Wimp_GetWindowState, &regs, &regs);
   233 
   234 	 osX = (x << this->hidden->xeig) + window_state[1];
   235 	 osY = window_state[4] - (y << this->hidden->yeig);
   236 
   237 	block[0] = 3;
   238 	block[1] = osX & 0xFF;
   239 	block[2] = (osX >> 8) & 0xFF;
   240 	block[3] = osY & 0xFF;
   241 	block[4] = (osY >> 8) & 0xFF;
   242 
   243 	regs.r[0] = 21;
   244 	regs.r[1] = (int)block;
   245 	_kernel_swi(OS_Word, &regs, &regs);
   246 	SDL_PrivateMouseMotion(0, 0, x, y);
   247 }
   248 
   249 int WIMP_ShowWMCursor(_THIS, WMcursor *cursor)
   250 {
   251 	if (mouseInWindow) return RISCOS_ShowWMCursor(this, cursor);
   252 	return 1;
   253 }
   254 
   255 SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode)
   256 {
   257    /* In fullscreen mode we don't need to do anything */
   258    if (mode < SDL_GRAB_FULLSCREEN)
   259    {
   260       _kernel_swi_regs regs;
   261       unsigned char block[9];
   262       block[0] = 1; /* Define mouse cursor bounding block */
   263 
   264       if ( mode == SDL_GRAB_OFF )
   265       {
   266          /* Clip to whole screen */
   267 
   268          int r = (this->hidden->screen_width << this->hidden->xeig) - 1;
   269          int t = (this->hidden->screen_height << this->hidden->yeig) - 1;
   270 
   271 	 block[1] = 0; block[2] = 0; /* Left*/
   272          block[3] = 0; block[4] = 0; /* Bottom */
   273          block[5] = r & 0xFF; block[6] = (r >> 8) & 0xFF; /* Right */
   274          block[7] = t & 0xFF; block[8] = (t >> 8) & 0xFF; /* Top */
   275       } else
   276       {
   277         /* Clip to window */
   278        	unsigned char window_state[36];
   279 
   280 	*((int *)window_state) = this->hidden->window_handle;
   281 	regs.r[1] = (unsigned int)window_state;
   282 	_kernel_swi(Wimp_GetWindowState, &regs, &regs);
   283 
   284         block[1] = window_state[4];
   285         block[2] = window_state[5];
   286         block[3] = window_state[8];
   287         block[4] = window_state[9];
   288         block[5] = window_state[12];
   289         block[6] = window_state[13];
   290         block[7] = window_state[16];
   291         block[8] = window_state[17];
   292 
   293       }
   294 
   295       regs.r[0] = 21; /* OS word code */
   296       regs.r[1] = (int)block;
   297       _kernel_swi(OS_Word, &regs, &regs);
   298    }
   299 
   300    return mode;
   301 }