Exit of SDL_WaitEvent() returns an error.
[maemo-rb.git] / firmware / target / hosted / sdl / button-sdl.c
blob3d6a3797cf6a2f516d001501bb2993ac9e3152f3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Felix Arends
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <math.h>
23 #include <stdlib.h> /* EXIT_SUCCESS */
24 #include "sim-ui-defines.h"
25 #include "lcd-charcells.h"
26 #include "lcd-remote.h"
27 #include "config.h"
28 #include "button.h"
29 #include "kernel.h"
30 #include "backlight.h"
31 #include "system.h"
32 #include "button-sdl.h"
33 #include "sim_tasks.h"
34 #include "buttonmap.h"
35 #include "debug.h"
37 #ifdef HAVE_TOUCHSCREEN
38 #include "touchscreen.h"
39 static int mouse_coords = 0;
40 #endif
41 /* how long until repeat kicks in */
42 #define REPEAT_START 6
44 /* the speed repeat starts at */
45 #define REPEAT_INTERVAL_START 4
47 /* speed repeat finishes at */
48 #define REPEAT_INTERVAL_FINISH 2
50 #ifdef HAVE_TOUCHSCREEN
51 #define USB_KEY SDLK_c /* SDLK_u is taken by BUTTON_MIDLEFT */
52 #else
53 #define USB_KEY SDLK_u
54 #endif
56 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
57 int _remote_type=REMOTETYPE_H100_LCD;
59 int remote_type(void)
61 return _remote_type;
63 #endif
65 struct event_queue button_queue;
67 static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
69 int sdl_app_has_input_focus = 1;
70 #if (CONFIG_PLATFORM & PLATFORM_MAEMO)
71 static int n900_updown_key_pressed = 0;
72 #endif
74 #ifdef HAS_BUTTON_HOLD
75 bool hold_button_state = false;
76 bool button_hold(void) {
77 return hold_button_state;
79 #endif
81 #ifdef HAS_REMOTE_BUTTON_HOLD
82 bool remote_hold_button_state = false;
83 bool remote_button_hold(void) {
84 return remote_hold_button_state;
86 #endif
87 static void button_event(int key, bool pressed);
88 extern bool debug_wps;
89 extern bool mapping;
91 #ifdef HAVE_TOUCHSCREEN
92 static void touchscreen_event(int x, int y)
94 if(background) {
95 x -= UI_LCD_POSX;
96 y -= UI_LCD_POSY;
99 if(x >= 0 && y >= 0 && x < SIM_LCD_WIDTH && y < SIM_LCD_HEIGHT) {
100 mouse_coords = (x << 16) | y;
101 button_event(BUTTON_TOUCHSCREEN, true);
102 if (debug_wps)
103 printf("Mouse at 1: (%d, %d)\n", x, y);
106 #endif
108 static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
110 #define SQUARE(x) ((x)*(x))
111 static int x,y;
112 #ifdef SIMULATOR
113 static int xybutton = 0;
114 #endif
116 if(button_up) {
117 switch ( event->button )
119 #ifdef HAVE_SCROLLWHEEL
120 case SDL_BUTTON_WHEELUP:
121 case SDL_BUTTON_WHEELDOWN:
122 #endif
123 case SDL_BUTTON_MIDDLE:
124 case SDL_BUTTON_RIGHT:
125 button_event( event->button, false );
126 break;
127 /* The scrollwheel button up events are ignored as they are queued immediately */
128 case SDL_BUTTON_LEFT:
129 if ( mapping && background ) {
130 printf(" { SDLK_, %d, %d, %d, \"\" },\n", x, y,
131 (int)sqrt( SQUARE(x-(int)event->x) + SQUARE(y-(int)event->y))
134 #ifdef SIMULATOR
135 if ( background && xybutton ) {
136 button_event( xybutton, false );
137 xybutton = 0;
139 #endif
140 #ifdef HAVE_TOUCHSCREEN
141 else
142 button_event(BUTTON_TOUCHSCREEN, false);
143 #endif
144 break;
146 } else { /* button down */
147 switch ( event->button )
149 #ifdef HAVE_SCROLLWHEEL
150 case SDL_BUTTON_WHEELUP:
151 case SDL_BUTTON_WHEELDOWN:
152 #endif
153 case SDL_BUTTON_MIDDLE:
154 case SDL_BUTTON_RIGHT:
155 button_event( event->button, true );
156 break;
157 case SDL_BUTTON_LEFT:
158 if ( mapping && background ) {
159 x = event->x;
160 y = event->y;
162 #ifdef SIMULATOR
163 if ( background ) {
164 xybutton = xy2button( event->x, event->y );
165 if( xybutton ) {
166 button_event( xybutton, true );
167 break;
170 #endif
171 #ifdef HAVE_TOUCHSCREEN
172 touchscreen_event(event->x, event->y);
173 #endif
174 break;
177 if (debug_wps && event->button == SDL_BUTTON_LEFT)
179 int m_x, m_y;
181 if ( background )
183 m_x = event->x - 1;
184 m_y = event->y - 1;
185 #ifdef HAVE_REMOTE
186 if ( event->y >= UI_REMOTE_POSY ) /* Remote Screen */
188 m_x -= UI_REMOTE_POSX;
189 m_y -= UI_REMOTE_POSY;
191 else
192 #endif
194 m_x -= UI_LCD_POSX;
195 m_y -= UI_LCD_POSY;
198 else
200 m_x = event->x;
201 m_y = event->y;
202 #ifdef HAVE_REMOTE
203 if ( m_y >= LCD_HEIGHT ) /* Remote Screen */
204 m_y -= LCD_HEIGHT;
205 #endif
208 printf("Mouse at 2: (%d, %d)\n", m_x, m_y);
211 #undef SQUARE
214 static bool event_handler(SDL_Event *event)
216 SDLKey ev_key;
218 switch(event->type)
220 case SDL_ACTIVEEVENT:
221 if (event->active.state & SDL_APPINPUTFOCUS)
223 if (event->active.gain == 1)
224 sdl_app_has_input_focus = 1;
225 else
226 sdl_app_has_input_focus = 0;
228 break;
229 case SDL_KEYDOWN:
230 case SDL_KEYUP:
231 ev_key = event->key.keysym.sym;
232 #if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
233 /* N900 with shared up/down cursor mapping. Seen on the German,
234 Finnish, Italian, French and Russian version. Probably more. */
235 if (event->key.keysym.mod & KMOD_MODE || n900_updown_key_pressed)
237 /* Prevent stuck up/down keys: If you release the ALT key before the cursor key,
238 rockbox will see a KEYUP event for left/right instead of up/down and
239 the previously pressed up/down key would stay active. */
240 if (ev_key == SDLK_LEFT || ev_key == SDLK_RIGHT)
242 if (event->type == SDL_KEYDOWN)
243 n900_updown_key_pressed = 1;
244 else
245 n900_updown_key_pressed = 0;
248 if (ev_key == SDLK_LEFT)
249 ev_key = SDLK_UP;
250 else if (ev_key == SDLK_RIGHT)
251 ev_key = SDLK_DOWN;
253 #endif
254 button_event(ev_key, event->type == SDL_KEYDOWN);
255 break;
256 #ifdef HAVE_TOUCHSCREEN
257 case SDL_MOUSEMOTION:
258 if (event->motion.state & SDL_BUTTON(1))
260 int x = event->motion.x / display_zoom;
261 int y = event->motion.y / display_zoom;
262 touchscreen_event(x, y);
264 break;
265 #endif
267 case SDL_MOUSEBUTTONUP:
268 case SDL_MOUSEBUTTONDOWN:
270 SDL_MouseButtonEvent *mev = &event->button;
271 mev->x /= display_zoom;
272 mev->y /= display_zoom;
273 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP);
274 break;
276 case SDL_QUIT:
277 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
278 sys_poweroff();
279 break;
280 case SDL_USEREVENT:
281 return true;
282 break;
285 return false;
288 void gui_message_loop(void)
290 SDL_Event event;
291 bool quit;
293 do {
294 /* wait for the next event */
295 if(SDL_WaitEvent(&event) == 0) {
296 printf("SDL_WaitEvent() error\n");
297 return; /* error, out of here */
300 sim_enter_irq_handler();
301 quit = event_handler(&event);
302 sim_exit_irq_handler();
304 } while(!quit);
307 static void button_event(int key, bool pressed)
309 int new_btn = 0;
310 static bool usb_connected = false;
311 if (usb_connected && key != USB_KEY)
312 return;
313 switch (key)
315 case USB_KEY:
316 if (!pressed)
318 usb_connected = !usb_connected;
319 if (usb_connected)
320 queue_post(&button_queue, SYS_USB_CONNECTED, 0);
321 else
322 queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
324 return;
326 #if (CONFIG_PLATFORM & PLATFORM_PANDORA)
327 case SDLK_LCTRL:
328 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
329 sys_poweroff();
330 break;
331 #endif
332 #ifdef HAS_BUTTON_HOLD
333 case SDLK_h:
334 if(pressed)
336 hold_button_state = !hold_button_state;
337 DEBUGF("Hold button is %s\n", hold_button_state?"ON":"OFF");
339 return;
340 #endif
342 #ifdef HAS_REMOTE_BUTTON_HOLD
343 case SDLK_j:
344 if(pressed)
346 remote_hold_button_state = !remote_hold_button_state;
347 DEBUGF("Remote hold button is %s\n",
348 remote_hold_button_state?"ON":"OFF");
350 return;
351 #endif
353 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
354 case SDLK_t:
355 if(pressed)
356 switch(_remote_type)
358 case REMOTETYPE_UNPLUGGED:
359 _remote_type=REMOTETYPE_H100_LCD;
360 DEBUGF("Changed remote type to H100\n");
361 break;
362 case REMOTETYPE_H100_LCD:
363 _remote_type=REMOTETYPE_H300_LCD;
364 DEBUGF("Changed remote type to H300\n");
365 break;
366 case REMOTETYPE_H300_LCD:
367 _remote_type=REMOTETYPE_H300_NONLCD;
368 DEBUGF("Changed remote type to H300 NON-LCD\n");
369 break;
370 case REMOTETYPE_H300_NONLCD:
371 _remote_type=REMOTETYPE_UNPLUGGED;
372 DEBUGF("Changed remote type to none\n");
373 break;
375 break;
376 #endif
377 case SDLK_KP0:
378 case SDLK_F5:
379 if(pressed)
381 sim_trigger_screendump();
382 return;
384 break;
385 #ifdef HAVE_TOUCHSCREEN
386 case SDLK_F4:
387 if(pressed)
389 touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
390 printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
392 #endif
393 default:
394 #ifdef HAVE_TOUCHSCREEN
395 new_btn = key_to_touch(key, mouse_coords);
396 if (!new_btn)
397 #endif
398 new_btn = key_to_button(key);
399 break;
401 /* Call to make up for scrollwheel target implementation. This is
402 * not handled in the main button.c driver, but on the target
403 * implementation (look at button-e200.c for example if you are trying to
404 * figure out why using button_get_data needed a hack before).
406 #if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
407 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
408 pressed)
410 /* Clear these buttons from the data - adding them to the queue is
411 * handled in the scrollwheel drivers for the targets. They do not
412 * store the scroll forward/back buttons in their button data for
413 * the button_read call.
415 #ifdef HAVE_BACKLIGHT
416 backlight_on();
417 #endif
418 #ifdef HAVE_BUTTON_LIGHT
419 buttonlight_on();
420 #endif
421 queue_post(&button_queue, new_btn, 1<<24);
422 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
424 #endif
426 if (pressed)
427 btn |= new_btn;
428 else
429 btn &= ~new_btn;
431 #if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
432 int button_read_device(int* data)
434 *data = mouse_coords;
435 #else
436 int button_read_device(void)
438 #endif
439 #ifdef HAS_BUTTON_HOLD
440 int hold_button = button_hold();
442 #ifdef HAVE_BACKLIGHT
443 /* light handling */
444 static int hold_button_old = false;
445 if (hold_button != hold_button_old)
447 hold_button_old = hold_button;
448 backlight_hold_changed(hold_button);
450 #endif
452 if (hold_button)
453 return BUTTON_NONE;
454 else
455 #endif
457 return btn;
460 void button_init_device(void)
462 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);