Revert to normal shutdown sequence on the Pandora
[maemo-rb.git] / firmware / target / hosted / sdl / button-sdl.c
blobd77ac6cbd1baec342557aacde9c1c76bad7dc729
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 "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;
71 #if (CONFIG_PLATFORM & PLATFORM_MAEMO)
72 static int n900_updown_key_pressed = 0;
73 #endif
75 #ifdef HAS_BUTTON_HOLD
76 bool hold_button_state = false;
77 bool button_hold(void) {
78 return hold_button_state;
80 #endif
82 #ifdef HAS_REMOTE_BUTTON_HOLD
83 bool remote_hold_button_state = false;
84 bool remote_button_hold(void) {
85 return remote_hold_button_state;
87 #endif
88 static void button_event(int key, bool pressed);
89 extern bool debug_wps;
90 extern bool mapping;
92 #ifdef HAVE_TOUCHSCREEN
93 static void touchscreen_event(int x, int y)
95 if(background) {
96 x -= UI_LCD_POSX;
97 y -= UI_LCD_POSY;
100 if(x >= 0 && y >= 0 && x < SIM_LCD_WIDTH && y < SIM_LCD_HEIGHT) {
101 mouse_coords = (x << 16) | y;
102 button_event(BUTTON_TOUCHSCREEN, true);
103 if (debug_wps)
104 printf("Mouse at 1: (%d, %d)\n", x, y);
107 #endif
109 static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
111 #define SQUARE(x) ((x)*(x))
112 static int x,y;
113 #ifdef SIMULATOR
114 static int xybutton = 0;
115 #endif
117 if(button_up) {
118 switch ( event->button )
120 #ifdef HAVE_SCROLLWHEEL
121 case SDL_BUTTON_WHEELUP:
122 case SDL_BUTTON_WHEELDOWN:
123 #endif
124 case SDL_BUTTON_MIDDLE:
125 case SDL_BUTTON_RIGHT:
126 button_event( event->button, false );
127 break;
128 /* The scrollwheel button up events are ignored as they are queued immediately */
129 case SDL_BUTTON_LEFT:
130 if ( mapping && background ) {
131 printf(" { SDLK_, %d, %d, %d, \"\" },\n", x, y,
132 (int)sqrt( SQUARE(x-(int)event->x) + SQUARE(y-(int)event->y))
135 #ifdef SIMULATOR
136 if ( background && xybutton ) {
137 button_event( xybutton, false );
138 xybutton = 0;
140 #endif
141 #ifdef HAVE_TOUCHSCREEN
142 else
143 button_event(BUTTON_TOUCHSCREEN, false);
144 #endif
145 break;
147 } else { /* button down */
148 switch ( event->button )
150 #ifdef HAVE_SCROLLWHEEL
151 case SDL_BUTTON_WHEELUP:
152 case SDL_BUTTON_WHEELDOWN:
153 #endif
154 case SDL_BUTTON_MIDDLE:
155 case SDL_BUTTON_RIGHT:
156 button_event( event->button, true );
157 break;
158 case SDL_BUTTON_LEFT:
159 if ( mapping && background ) {
160 x = event->x;
161 y = event->y;
163 #ifdef SIMULATOR
164 if ( background ) {
165 xybutton = xy2button( event->x, event->y );
166 if( xybutton ) {
167 button_event( xybutton, true );
168 break;
171 #endif
172 #ifdef HAVE_TOUCHSCREEN
173 touchscreen_event(event->x, event->y);
174 #endif
175 break;
178 if (debug_wps && event->button == SDL_BUTTON_LEFT)
180 int m_x, m_y;
182 if ( background )
184 m_x = event->x - 1;
185 m_y = event->y - 1;
186 #ifdef HAVE_REMOTE
187 if ( event->y >= UI_REMOTE_POSY ) /* Remote Screen */
189 m_x -= UI_REMOTE_POSX;
190 m_y -= UI_REMOTE_POSY;
192 else
193 #endif
195 m_x -= UI_LCD_POSX;
196 m_y -= UI_LCD_POSY;
199 else
201 m_x = event->x;
202 m_y = event->y;
203 #ifdef HAVE_REMOTE
204 if ( m_y >= LCD_HEIGHT ) /* Remote Screen */
205 m_y -= LCD_HEIGHT;
206 #endif
209 printf("Mouse at 2: (%d, %d)\n", m_x, m_y);
212 #undef SQUARE
215 static bool event_handler(SDL_Event *event)
217 SDLKey ev_key;
219 switch(event->type)
221 case SDL_ACTIVEEVENT:
222 if (event->active.state & SDL_APPINPUTFOCUS)
224 if (event->active.gain == 1)
225 sdl_app_has_input_focus = 1;
226 else
227 sdl_app_has_input_focus = 0;
229 break;
230 case SDL_KEYDOWN:
231 case SDL_KEYUP:
232 ev_key = event->key.keysym.sym;
233 #if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
234 /* N900 with shared up/down cursor mapping. Seen on the German,
235 Finnish, Italian, French and Russian version. Probably more. */
236 if (event->key.keysym.mod & KMOD_MODE || n900_updown_key_pressed)
238 /* Prevent stuck up/down keys: If you release the ALT key before the cursor key,
239 rockbox will see a KEYUP event for left/right instead of up/down and
240 the previously pressed up/down key would stay active. */
241 if (ev_key == SDLK_LEFT || ev_key == SDLK_RIGHT)
243 if (event->type == SDL_KEYDOWN)
244 n900_updown_key_pressed = 1;
245 else
246 n900_updown_key_pressed = 0;
249 if (ev_key == SDLK_LEFT)
250 ev_key = SDLK_UP;
251 else if (ev_key == SDLK_RIGHT)
252 ev_key = SDLK_DOWN;
254 #endif
255 button_event(ev_key, event->type == SDL_KEYDOWN);
256 break;
257 #ifdef HAVE_TOUCHSCREEN
258 case SDL_MOUSEMOTION:
259 if (event->motion.state & SDL_BUTTON(1))
261 int x = event->motion.x / display_zoom;
262 int y = event->motion.y / display_zoom;
263 touchscreen_event(x, y);
265 break;
266 #endif
268 case SDL_MOUSEBUTTONUP:
269 case SDL_MOUSEBUTTONDOWN:
271 SDL_MouseButtonEvent *mev = &event->button;
272 mev->x /= display_zoom;
273 mev->y /= display_zoom;
274 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP);
275 break;
277 case SDL_QUIT:
278 /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */
279 queue_broadcast(SYS_POWEROFF, 0);
280 break;
281 case SDL_USEREVENT:
282 return true;
283 break;
286 return false;
289 void gui_message_loop(void)
291 SDL_Event event;
292 bool quit;
294 do {
295 /* wait for the next event */
296 while(SDL_WaitEvent(&event) == 0)
297 printf("SDL_WaitEvent() error\n");
299 sim_enter_irq_handler();
300 quit = event_handler(&event);
301 sim_exit_irq_handler();
303 } while(!quit);
306 static void button_event(int key, bool pressed)
308 int new_btn = 0;
309 static bool usb_connected = false;
310 if (usb_connected && key != USB_KEY)
311 return;
312 switch (key)
314 case USB_KEY:
315 if (!pressed)
317 usb_connected = !usb_connected;
318 if (usb_connected)
319 queue_post(&button_queue, SYS_USB_CONNECTED, 0);
320 else
321 queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
323 return;
325 #if (CONFIG_PLATFORM & PLATFORM_PANDORA)
326 case SDLK_FIRST:
327 /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */
328 queue_broadcast(SYS_POWEROFF, 0);
329 break;
330 #endif
331 #ifdef HAS_BUTTON_HOLD
332 case SDLK_h:
333 if(pressed)
335 hold_button_state = !hold_button_state;
336 DEBUGF("Hold button is %s\n", hold_button_state?"ON":"OFF");
338 return;
339 #endif
341 #ifdef HAS_REMOTE_BUTTON_HOLD
342 case SDLK_j:
343 if(pressed)
345 remote_hold_button_state = !remote_hold_button_state;
346 DEBUGF("Remote hold button is %s\n",
347 remote_hold_button_state?"ON":"OFF");
349 return;
350 #endif
352 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
353 case SDLK_t:
354 if(pressed)
355 switch(_remote_type)
357 case REMOTETYPE_UNPLUGGED:
358 _remote_type=REMOTETYPE_H100_LCD;
359 DEBUGF("Changed remote type to H100\n");
360 break;
361 case REMOTETYPE_H100_LCD:
362 _remote_type=REMOTETYPE_H300_LCD;
363 DEBUGF("Changed remote type to H300\n");
364 break;
365 case REMOTETYPE_H300_LCD:
366 _remote_type=REMOTETYPE_H300_NONLCD;
367 DEBUGF("Changed remote type to H300 NON-LCD\n");
368 break;
369 case REMOTETYPE_H300_NONLCD:
370 _remote_type=REMOTETYPE_UNPLUGGED;
371 DEBUGF("Changed remote type to none\n");
372 break;
374 break;
375 #endif
376 case SDLK_KP0:
377 case SDLK_F5:
378 if(pressed)
380 sim_trigger_screendump();
381 return;
383 break;
384 #ifdef HAVE_TOUCHSCREEN
385 case SDLK_F4:
386 if(pressed)
388 touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
389 printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
391 #endif
392 default:
393 #ifdef HAVE_TOUCHSCREEN
394 new_btn = key_to_touch(key, mouse_coords);
395 if (!new_btn)
396 #endif
397 new_btn = key_to_button(key);
398 break;
400 /* Call to make up for scrollwheel target implementation. This is
401 * not handled in the main button.c driver, but on the target
402 * implementation (look at button-e200.c for example if you are trying to
403 * figure out why using button_get_data needed a hack before).
405 #if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
406 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
407 pressed)
409 /* Clear these buttons from the data - adding them to the queue is
410 * handled in the scrollwheel drivers for the targets. They do not
411 * store the scroll forward/back buttons in their button data for
412 * the button_read call.
414 #ifdef HAVE_BACKLIGHT
415 backlight_on();
416 #endif
417 #ifdef HAVE_BUTTON_LIGHT
418 buttonlight_on();
419 #endif
420 queue_post(&button_queue, new_btn, 1<<24);
421 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
423 #endif
425 if (pressed)
426 btn |= new_btn;
427 else
428 btn &= ~new_btn;
430 #if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
431 int button_read_device(int* data)
433 *data = mouse_coords;
434 #else
435 int button_read_device(void)
437 #endif
438 #ifdef HAS_BUTTON_HOLD
439 int hold_button = button_hold();
441 #ifdef HAVE_BACKLIGHT
442 /* light handling */
443 static int hold_button_old = false;
444 if (hold_button != hold_button_old)
446 hold_button_old = hold_button;
447 backlight_hold_changed(hold_button);
449 #endif
451 if (hold_button)
452 return BUTTON_NONE;
453 else
454 #endif
456 return btn;
459 void button_init_device(void)
461 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);