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@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 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
WIMP_PumpEvents(_THIS)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
WIMP_Poll(_THIS,int waitTime)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 */
WIMP_SetFocus(int win)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 */
RISCOS_BackgroundTasks(void)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