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, ®s, ®s); 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, ®s, ®s); 125 } else 126 { 127 regs.r[0] = pollMask; 128 regs.r[1] = (int)message; 129 regs.r[2] = waitTime; 130 _kernel_swi(Wimp_PollIdle, ®s, ®s); 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, ®s,®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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