e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 | |
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 | } |