Fix the shutdown sequence for maemo, SDL and simulator builds
[maemo-rb.git] / firmware / target / hosted / sdl / button-sdl.c
blob9c8188a12f051cefaf13bbcc43267f5372891f22
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 "misc.h"
32 #include "button-sdl.h"
33 #include "backlight.h"
34 #include "sim_tasks.h"
35 #include "buttonmap.h"
36 #include "debug.h"
38 #ifdef HAVE_TOUCHSCREEN
39 #include "touchscreen.h"
40 static int mouse_coords = 0;
41 #endif
42 /* how long until repeat kicks in */
43 #define REPEAT_START 6
45 /* the speed repeat starts at */
46 #define REPEAT_INTERVAL_START 4
48 /* speed repeat finishes at */
49 #define REPEAT_INTERVAL_FINISH 2
51 #ifdef HAVE_TOUCHSCREEN
52 #define USB_KEY SDLK_c /* SDLK_u is taken by BUTTON_MIDLEFT */
53 #else
54 #define USB_KEY SDLK_u
55 #endif
57 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
58 int _remote_type=REMOTETYPE_H100_LCD;
60 int remote_type(void)
62 return _remote_type;
64 #endif
66 struct event_queue button_queue;
68 static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
70 int sdl_app_has_input_focus = 1;
72 #ifdef HAS_BUTTON_HOLD
73 bool hold_button_state = false;
74 bool button_hold(void) {
75 return hold_button_state;
77 #endif
79 #ifdef HAS_REMOTE_BUTTON_HOLD
80 bool remote_hold_button_state = false;
81 bool remote_button_hold(void) {
82 return remote_hold_button_state;
84 #endif
85 static void button_event(int key, bool pressed);
86 extern bool debug_wps;
87 extern bool mapping;
89 #ifdef HAVE_TOUCHSCREEN
90 static void touchscreen_event(int x, int y)
92 if(background) {
93 x -= UI_LCD_POSX;
94 y -= UI_LCD_POSY;
97 if(x >= 0 && y >= 0 && x < SIM_LCD_WIDTH && y < SIM_LCD_HEIGHT) {
98 mouse_coords = (x << 16) | y;
99 button_event(BUTTON_TOUCHSCREEN, true);
100 if (debug_wps)
101 printf("Mouse at 1: (%d, %d)\n", x, y);
104 #endif
106 static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
108 #define SQUARE(x) ((x)*(x))
109 static int x,y;
110 #ifdef SIMULATOR
111 static int xybutton = 0;
112 #endif
114 if(button_up) {
115 switch ( event->button )
117 #ifdef HAVE_SCROLLWHEEL
118 case SDL_BUTTON_WHEELUP:
119 case SDL_BUTTON_WHEELDOWN:
120 #endif
121 case SDL_BUTTON_MIDDLE:
122 case SDL_BUTTON_RIGHT:
123 button_event( event->button, false );
124 break;
125 /* The scrollwheel button up events are ignored as they are queued immediately */
126 case SDL_BUTTON_LEFT:
127 if ( mapping && background ) {
128 printf(" { SDLK_, %d, %d, %d, \"\" },\n", x, y,
129 (int)sqrt( SQUARE(x-(int)event->x) + SQUARE(y-(int)event->y))
132 #ifdef SIMULATOR
133 if ( background && xybutton ) {
134 button_event( xybutton, false );
135 xybutton = 0;
137 #endif
138 #ifdef HAVE_TOUCHSCREEN
139 else
140 button_event(BUTTON_TOUCHSCREEN, false);
141 #endif
142 break;
144 } else { /* button down */
145 switch ( event->button )
147 #ifdef HAVE_SCROLLWHEEL
148 case SDL_BUTTON_WHEELUP:
149 case SDL_BUTTON_WHEELDOWN:
150 #endif
151 case SDL_BUTTON_MIDDLE:
152 case SDL_BUTTON_RIGHT:
153 button_event( event->button, true );
154 break;
155 case SDL_BUTTON_LEFT:
156 if ( mapping && background ) {
157 x = event->x;
158 y = event->y;
160 #ifdef SIMULATOR
161 if ( background ) {
162 xybutton = xy2button( event->x, event->y );
163 if( xybutton ) {
164 button_event( xybutton, true );
165 break;
168 #endif
169 #ifdef HAVE_TOUCHSCREEN
170 touchscreen_event(event->x, event->y);
171 #endif
172 break;
175 if (debug_wps && event->button == SDL_BUTTON_LEFT)
177 int m_x, m_y;
179 if ( background )
181 m_x = event->x - 1;
182 m_y = event->y - 1;
183 #ifdef HAVE_REMOTE
184 if ( event->y >= UI_REMOTE_POSY ) /* Remote Screen */
186 m_x -= UI_REMOTE_POSX;
187 m_y -= UI_REMOTE_POSY;
189 else
190 #endif
192 m_x -= UI_LCD_POSX;
193 m_y -= UI_LCD_POSY;
196 else
198 m_x = event->x;
199 m_y = event->y;
200 #ifdef HAVE_REMOTE
201 if ( m_y >= LCD_HEIGHT ) /* Remote Screen */
202 m_y -= LCD_HEIGHT;
203 #endif
206 printf("Mouse at 2: (%d, %d)\n", m_x, m_y);
209 #undef SQUARE
212 static bool event_handler(SDL_Event *event)
214 SDLKey ev_key;
216 switch(event->type)
218 case SDL_ACTIVEEVENT:
219 if (event->active.state & SDL_APPINPUTFOCUS)
221 if (event->active.gain == 1)
222 sdl_app_has_input_focus = 1;
223 else
224 sdl_app_has_input_focus = 0;
226 break;
227 case SDL_KEYDOWN:
228 case SDL_KEYUP:
229 ev_key = event->key.keysym.sym;
230 #if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
231 /* N900 with shared up/down cursor mapping. Seen on the German,
232 Finnish, Italian, French and Russian version. Probably more. */
233 if (event->key.keysym.mod & KMOD_MODE)
235 if (ev_key == SDLK_LEFT)
236 ev_key = SDLK_UP;
237 else if (ev_key == SDLK_RIGHT)
238 ev_key = SDLK_DOWN;
240 #endif
241 button_event(ev_key, event->type == SDL_KEYDOWN);
242 break;
243 #ifdef HAVE_TOUCHSCREEN
244 case SDL_MOUSEMOTION:
245 if (event->motion.state & SDL_BUTTON(1))
247 int x = event->motion.x / display_zoom;
248 int y = event->motion.y / display_zoom;
249 touchscreen_event(x, y);
251 break;
252 #endif
254 case SDL_MOUSEBUTTONUP:
255 case SDL_MOUSEBUTTONDOWN:
257 SDL_MouseButtonEvent *mev = &event->button;
258 mev->x /= display_zoom;
259 mev->y /= display_zoom;
260 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP);
261 break;
263 case SDL_QUIT:
264 /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */
265 queue_broadcast(SYS_POWEROFF, 0);
266 break;
267 case SDL_USEREVENT:
268 return true;
269 break;
272 return false;
275 void gui_message_loop(void)
277 SDL_Event event;
278 bool quit;
280 do {
281 /* wait for the next event */
282 while(SDL_WaitEvent(&event) == 0)
283 printf("SDL_WaitEvent() error\n");
285 sim_enter_irq_handler();
286 quit = event_handler(&event);
287 sim_exit_irq_handler();
289 } while(!quit);
292 static void button_event(int key, bool pressed)
294 int new_btn = 0;
295 static bool usb_connected = false;
296 if (usb_connected && key != USB_KEY)
297 return;
298 switch (key)
300 case USB_KEY:
301 if (!pressed)
303 usb_connected = !usb_connected;
304 if (usb_connected)
305 queue_post(&button_queue, SYS_USB_CONNECTED, 0);
306 else
307 queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
309 return;
311 #ifdef HAS_BUTTON_HOLD
312 case SDLK_h:
313 if(pressed)
315 hold_button_state = !hold_button_state;
316 DEBUGF("Hold button is %s\n", hold_button_state?"ON":"OFF");
318 return;
319 #endif
321 #ifdef HAS_REMOTE_BUTTON_HOLD
322 case SDLK_j:
323 if(pressed)
325 remote_hold_button_state = !remote_hold_button_state;
326 DEBUGF("Remote hold button is %s\n",
327 remote_hold_button_state?"ON":"OFF");
329 return;
330 #endif
332 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
333 case SDLK_t:
334 if(pressed)
335 switch(_remote_type)
337 case REMOTETYPE_UNPLUGGED:
338 _remote_type=REMOTETYPE_H100_LCD;
339 DEBUGF("Changed remote type to H100\n");
340 break;
341 case REMOTETYPE_H100_LCD:
342 _remote_type=REMOTETYPE_H300_LCD;
343 DEBUGF("Changed remote type to H300\n");
344 break;
345 case REMOTETYPE_H300_LCD:
346 _remote_type=REMOTETYPE_H300_NONLCD;
347 DEBUGF("Changed remote type to H300 NON-LCD\n");
348 break;
349 case REMOTETYPE_H300_NONLCD:
350 _remote_type=REMOTETYPE_UNPLUGGED;
351 DEBUGF("Changed remote type to none\n");
352 break;
354 break;
355 #endif
356 case SDLK_KP0:
357 case SDLK_F5:
358 if(pressed)
360 sim_trigger_screendump();
361 return;
363 break;
364 #ifdef HAVE_TOUCHSCREEN
365 case SDLK_F4:
366 if(pressed)
368 touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
369 printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
371 #endif
372 default:
373 #ifdef HAVE_TOUCHSCREEN
374 new_btn = key_to_touch(key, mouse_coords);
375 if (!new_btn)
376 #endif
377 new_btn = key_to_button(key);
378 break;
380 /* Call to make up for scrollwheel target implementation. This is
381 * not handled in the main button.c driver, but on the target
382 * implementation (look at button-e200.c for example if you are trying to
383 * figure out why using button_get_data needed a hack before).
385 #if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
386 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
387 pressed)
389 /* Clear these buttons from the data - adding them to the queue is
390 * handled in the scrollwheel drivers for the targets. They do not
391 * store the scroll forward/back buttons in their button data for
392 * the button_read call.
394 #ifdef HAVE_BACKLIGHT
395 backlight_on();
396 #endif
397 #ifdef HAVE_BUTTON_LIGHT
398 buttonlight_on();
399 #endif
400 queue_post(&button_queue, new_btn, 1<<24);
401 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
403 #endif
405 if (pressed)
406 btn |= new_btn;
407 else
408 btn &= ~new_btn;
410 #if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
411 int button_read_device(int* data)
413 *data = mouse_coords;
414 #else
415 int button_read_device(void)
417 #endif
418 #ifdef HAS_BUTTON_HOLD
419 int hold_button = button_hold();
421 #ifdef HAVE_BACKLIGHT
422 /* light handling */
423 static int hold_button_old = false;
424 if (hold_button != hold_button_old)
426 hold_button_old = hold_button;
427 backlight_hold_changed(hold_button);
429 #endif
431 if (hold_button)
432 return BUTTON_NONE;
433 else
434 #endif
436 return btn;
439 void button_init_device(void)
441 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);