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 Pumping of events and WIMP polling
     29 */
     30 
     31 #include "SDL.h"
     32 #include "SDL_syswm.h"
     33 #include "../../events/SDL_sysevents.h"
     34 #include "../../events/SDL_events_c.h"
     35 #include "SDL_riscosvideo.h"
     36 #include "SDL_riscosevents_c.h"
     37 #include "SDL_riscosmouse_c.h"
     38 #include "../../timer/SDL_timer_c.h"
     39 
     40 #include "memory.h"
     41 #include "stdlib.h"
     42 #include "ctype.h"
     43 
     44 #include "kernel.h"
     45 #include "swis.h"
     46 #include "unixlib/os.h"
     47 
     48 #if !SDL_THREADS_DISABLED
     49 #include <pthread.h>
     50 #endif
     51 
     52 /* Local functions */
     53 void WIMP_Poll(_THIS, int waitTime);
     54 void WIMP_SetFocus(int win);
     55 
     56 /* SDL_riscossprite functions */
     57 void WIMP_PlotSprite(_THIS, int x, int y);
     58 void WIMP_ModeChanged(_THIS);
     59 void WIMP_PaletteChanged(_THIS);
     60 
     61 
     62 extern void WIMP_PollMouse(_THIS);
     63 extern void RISCOS_PollKeyboard();
     64 
     65 #if SDL_THREADS_DISABLED
     66 /* Timer running function */
     67 extern void RISCOS_CheckTimer();
     68 #else
     69 extern int riscos_using_threads;
     70 #endif
     71 
     72 /* Mouse cursor handling */
     73 extern void WIMP_ReshowCursor(_THIS);
     74 extern void WIMP_RestoreWimpCursor();
     75 
     76 int hasFocus = 0;
     77 int mouseInWindow = 0;
     78 
     79 /* Flag to ensure window is correct size after a mode change */
     80 static int resizeOnOpen = 0;
     81 
     82 void WIMP_PumpEvents(_THIS)
     83 {
     84 	WIMP_Poll(this, 0);
     85 	if (hasFocus) RISCOS_PollKeyboard();
     86 	if (mouseInWindow) WIMP_PollMouse(this);
     87 #if SDL_THREADS_DISABLED
     88 	if (SDL_timer_running) RISCOS_CheckTimer();
     89 #endif
     90 }
     91 
     92 
     93 void WIMP_Poll(_THIS, int waitTime)
     94 {
     95 	_kernel_swi_regs regs;
     96 	int message[64];
     97 	unsigned int code;
     98 	int pollMask = 0;
     99 	int doPoll = 1;
    100 	int sysEvent;
    101 	int sdlWindow = this->hidden->window_handle;
    102 
    103     if (this->PumpEvents != WIMP_PumpEvents) return;
    104 
    105     if (waitTime > 0)
    106     {
    107 		_kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
    108 		waitTime += regs.r[0];
    109     }
    110 
    111     while (doPoll)
    112     {
    113 #if !SDL_THREADS_DISABLED
    114        /* Stop thread callbacks while program is paged out */
    115        if (riscos_using_threads) __pthread_stop_ticker();
    116 #endif
    117 
    118         if (waitTime <= 0)
    119         {
    120         	regs.r[0] = pollMask; /* Poll Mask */
    121         	/* For no wait time mask out null event so we wait until something happens */
    122         	if (waitTime < 0) regs.r[0] |= 1;
    123         	regs.r[1] = (int)message;
    124         	_kernel_swi(Wimp_Poll, &regs, &regs);
    125         } else
    126         {
    127         	regs.r[0] = pollMask;
    128         	regs.r[1] = (int)message;
    129         	regs.r[2] = waitTime;
    130         	_kernel_swi(Wimp_PollIdle, &regs, &regs);
    131         }
    132 
    133 		/* Flag to specify if we post a SDL_SysWMEvent */
    134 	sysEvent = 0;
    135 
    136         code = (unsigned int)regs.r[0];
    137 
    138 	switch(code)
    139 	{
    140         case 0:  /* Null Event - drop out for standard processing*/
    141 	   doPoll = 0;
    142 	   break;
    143 
    144 	case 1:     /* Redraw window */
    145            _kernel_swi(Wimp_RedrawWindow, &regs,&regs);
    146 	   if (message[0] == sdlWindow)
    147 	   {
    148                  while (regs.r[0])
    149                  {
    150            	    WIMP_PlotSprite(this, message[1], message[2]);
    151            	    _kernel_swi(Wimp_GetRectangle, &regs, &regs);
    152                  }
    153 	   } else
    154 	  {
    155 	/* TODO: Currently we just eat them - we may need to pass them on */
    156         	while (regs.r[0])
    157         	{
    158                         _kernel_swi(Wimp_GetRectangle, &regs, &regs);
    159         	}
    160 	  }
    161           break;
    162 
    163 		case 2:		/* Open window */
    164 		   if ( resizeOnOpen && message[0] == sdlWindow)
    165 		   {
    166 		      /* Ensure window is correct size */
    167 		      resizeOnOpen = 0;
    168 		      message[3] = message[1] + (this->screen->w << this->hidden->xeig);
    169 		      message[4] = message[2] + (this->screen->h << this->hidden->yeig);
    170 		   }
    171         	_kernel_swi(Wimp_OpenWindow, &regs, &regs);
    172        	    break;
    173 
    174 		case 3:		/* Close window */
    175 			if (message[0] == sdlWindow)
    176 			{
    177 				/* Documentation makes it looks as if the following line is correct:
    178 				**    if (SDL_PrivateQuit() == 1) _kernel_swi(Wimp_CloseWindow, &regs, &regs);
    179 				** However some programs don't process this message and so sit there invisibly
    180 				** in the background so I just post the quit message and hope the application
    181 				** does the correct thing.
    182 				*/
    183 				SDL_PrivateQuit();
    184 			} else
    185 				sysEvent = 1;
    186         	doPoll = 0;
    187         	break;
    188 
    189 		case 4: /* Pointer_Leaving_Window */
    190 			if (message[0] == sdlWindow)
    191 			{
    192 				mouseInWindow = 0;
    193 				//TODO: Lose buttons / dragging
    194 				 /* Reset to default pointer */
    195 				 WIMP_RestoreWimpCursor();
    196 				 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
    197 			} else
    198 				sysEvent = 1;
    199 			break;
    200 
    201 		case 5: /* Pointer_Entering_Window */
    202 			if (message[0] == sdlWindow)
    203 			{
    204 				mouseInWindow = 1;
    205 				WIMP_ReshowCursor(this);
    206 				SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
    207 			} else sysEvent = 1;
    208 			break;
    209 
    210 		case 6:		/* Mouse_Click */
    211 			if (hasFocus == 0)
    212 			{
    213 			   /* First click gives focus if it's not a menu */
    214 			   /* we only count non-menu clicks on a window that has the focus */
    215 			   WIMP_SetFocus(message[3]);
    216 			} else
    217 				doPoll = 0; // So PollMouse gets a chance to pick it up
    218 		   break;
    219 
    220 		case 7: /* User_Drag_Box - Used for mouse release */
    221 			//TODO: May need to implement this in the future
    222 			sysEvent = 1;
    223 			break;
    224 
    225 		case 8: /* Keypressed */
    226 			doPoll = 0; /* PollKeyboard should pick it up */
    227 			if (message[0] != sdlWindow) sysEvent = 1;
    228 			/*TODO: May want to always pass F12 etc to the wimp
    229 			{
    230 				regs.r[0] = message[6];
    231 				_kernel_swi(Wimp_ProcessKey, &regs, &regs);
    232 			}
    233 			*/
    234 			break;
    235 
    236 		case 11: /* Lose Caret */
    237 			 hasFocus = 0;
    238 			 if (message[0] == sdlWindow) SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
    239 			 else sysEvent = 1;
    240 			 break;
    241 
    242 		case 12: /* Gain Caret */
    243 			 hasFocus = 1;
    244 			 if (message[0] == sdlWindow) SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
    245 			 else sysEvent = 1;
    246 			 break;
    247 
    248 		case 17:
    249 		case 18:
    250 			sysEvent = 1; /* All messages are passed on */
    251 
    252 			switch(message[4])
    253 			{
    254 			case 0: /* Quit Event */
    255 				/* No choice - have to quit */
    256 			   SDL_Quit();
    257         	   exit(0);
    258 			   break;
    259 
    260 			case 8: /* Pre Quit */
    261 				SDL_PrivateQuit();
    262 				break;
    263 
    264 			case 0x400c1: /* Mode change */
    265 				WIMP_ModeChanged(this);
    266 				resizeOnOpen = 1;
    267 				break;
    268 
    269 			case 9:      /* Palette changed */
    270 				WIMP_PaletteChanged(this);
    271 				break;
    272 			}
    273 			break;
    274 
    275 		default:
    276 			/* Pass unknown events on */
    277 			sysEvent = 1;
    278 			break;
    279 		}
    280 
    281 		if (sysEvent)
    282 		{
    283 	        SDL_SysWMmsg wmmsg;
    284 
    285 			SDL_VERSION(&wmmsg.version);
    286 			wmmsg.eventCode = code;
    287 			SDL_memcpy(wmmsg.pollBlock, message, 64 * sizeof(int));
    288 
    289 			/* Fall out of polling loop if message is successfully posted */
    290 			if (SDL_PrivateSysWMEvent(&wmmsg)) doPoll = 0;
    291 		}
    292 #if !SDL_THREADS_DISABLED
    293 		if (riscos_using_threads)
    294 		{
    295                    /* Restart ticker here so other thread can not interfere
    296                       with the Redraw processing */
    297 		   if (riscos_using_threads) __pthread_start_ticker();
    298                    /* Give other threads a better chance of running */
    299 		   pthread_yield();
    300 		}
    301 #endif
    302     }
    303 }
    304 
    305 /* Set focus to specified window */
    306 void WIMP_SetFocus(int win)
    307 {
    308 	_kernel_swi_regs regs;
    309 
    310 	regs.r[0] = win;
    311 	regs.r[1] = -1; /* Icon handle */
    312 	regs.r[2] = 0;  /* X-offset we just put it at position 0 */
    313 	regs.r[3] = 0;  /* Y-offset as above */
    314 	regs.r[4] = 1 << 25; /* Caret is invisible */
    315 	regs.r[5] = 0;  /* index into string */
    316 
    317 	_kernel_swi(Wimp_SetCaretPosition, &regs, &regs);
    318 }
    319 
    320 /** Run background task while in a sleep command */
    321 void RISCOS_BackgroundTasks(void)
    322 {
    323 	if (current_video && current_video->hidden->window_handle)
    324 	{
    325 		WIMP_Poll(current_video, 0);
    326 	}
    327 #if SDL_THREADS_DISABLED
    328 	if (SDL_timer_running) RISCOS_CheckTimer();
    329 #endif
    330 }
    331