SDL-1.2.14
[sdl_omap.git] / src / video / riscos / SDL_wimppoll.c
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, &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 }