Prepare new maemo release
[maemo-rb.git] / firmware / target / hosted / sdl / button-sdl.c
blob4bd4b8de64af46c56238bd8cc52a009899dfd33a
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 #ifdef HAVE_REMOTE_LCD
27 #include "lcd-remote.h"
28 #endif
29 #include "config.h"
30 #include "button.h"
31 #include "kernel.h"
32 #include "backlight.h"
33 #include "system.h"
34 #include "button-sdl.h"
35 #include "sim_tasks.h"
36 #include "buttonmap.h"
37 #include "debug.h"
38 #include "powermgmt.h"
40 #ifdef HAVE_TOUCHSCREEN
41 #include "touchscreen.h"
42 static int mouse_coords = 0;
43 #endif
44 /* how long until repeat kicks in */
45 #define REPEAT_START 6
47 /* the speed repeat starts at */
48 #define REPEAT_INTERVAL_START 4
50 /* speed repeat finishes at */
51 #define REPEAT_INTERVAL_FINISH 2
53 #ifdef HAVE_TOUCHSCREEN
54 #define USB_KEY SDLK_c /* SDLK_u is taken by BUTTON_MIDLEFT */
55 #else
56 #define USB_KEY SDLK_u
57 #endif
59 #if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
60 int _remote_type=REMOTETYPE_H100_LCD;
62 int remote_type(void)
64 return _remote_type;
66 #endif
68 struct event_queue button_queue;
70 static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
72 int sdl_app_has_input_focus = 1;
73 #if (CONFIG_PLATFORM & PLATFORM_MAEMO)
74 static int n900_updown_key_pressed = 0;
75 #endif
77 #ifdef HAS_BUTTON_HOLD
78 bool hold_button_state = false;
79 bool button_hold(void) {
80 return hold_button_state;
82 #endif
84 #ifdef HAS_REMOTE_BUTTON_HOLD
85 bool remote_hold_button_state = false;
86 bool remote_button_hold(void) {
87 return remote_hold_button_state;
89 #endif
90 static void button_event(int key, bool pressed);
91 extern bool debug_wps;
92 extern bool mapping;
94 #ifdef HAVE_TOUCHSCREEN
95 static void touchscreen_event(int x, int y)
97 if(background) {
98 x -= UI_LCD_POSX;
99 y -= UI_LCD_POSY;
102 if(x >= 0 && y >= 0 && x < SIM_LCD_WIDTH && y < SIM_LCD_HEIGHT) {
103 mouse_coords = (x << 16) | y;
104 button_event(BUTTON_TOUCHSCREEN, true);
105 if (debug_wps)
106 printf("Mouse at 1: (%d, %d)\n", x, y);
109 #endif
111 static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
113 #define SQUARE(x) ((x)*(x))
114 static int x,y;
115 #ifdef SIMULATOR
116 static int xybutton = 0;
117 #endif
119 if(button_up) {
120 switch ( event->button )
122 #ifdef HAVE_SCROLLWHEEL
123 case SDL_BUTTON_WHEELUP:
124 case SDL_BUTTON_WHEELDOWN:
125 #endif
126 case SDL_BUTTON_MIDDLE:
127 case SDL_BUTTON_RIGHT:
128 button_event( event->button, false );
129 break;
130 /* The scrollwheel button up events are ignored as they are queued immediately */
131 case SDL_BUTTON_LEFT:
132 if ( mapping && background ) {
133 printf(" { SDLK_, %d, %d, %d, \"\" },\n", x, y,
134 (int)sqrt( SQUARE(x-(int)event->x) + SQUARE(y-(int)event->y))
137 #ifdef SIMULATOR
138 if ( background && xybutton ) {
139 button_event( xybutton, false );
140 xybutton = 0;
142 #endif
143 #ifdef HAVE_TOUCHSCREEN
144 else
145 button_event(BUTTON_TOUCHSCREEN, false);
146 #endif
147 break;
149 } else { /* button down */
150 switch ( event->button )
152 #ifdef HAVE_SCROLLWHEEL
153 case SDL_BUTTON_WHEELUP:
154 case SDL_BUTTON_WHEELDOWN:
155 #endif
156 case SDL_BUTTON_MIDDLE:
157 case SDL_BUTTON_RIGHT:
158 button_event( event->button, true );
159 break;
160 case SDL_BUTTON_LEFT:
161 if ( mapping && background ) {
162 x = event->x;
163 y = event->y;
165 #ifdef SIMULATOR
166 if ( background ) {
167 xybutton = xy2button( event->x, event->y );
168 if( xybutton ) {
169 button_event( xybutton, true );
170 break;
173 #endif
174 #ifdef HAVE_TOUCHSCREEN
175 touchscreen_event(event->x, event->y);
176 #endif
177 break;
180 if (debug_wps && event->button == SDL_BUTTON_LEFT)
182 int m_x, m_y;
184 if ( background )
186 m_x = event->x - 1;
187 m_y = event->y - 1;
188 #ifdef HAVE_REMOTE
189 if ( event->y >= UI_REMOTE_POSY ) /* Remote Screen */
191 m_x -= UI_REMOTE_POSX;
192 m_y -= UI_REMOTE_POSY;
194 else
195 #endif
197 m_x -= UI_LCD_POSX;
198 m_y -= UI_LCD_POSY;
201 else
203 m_x = event->x;
204 m_y = event->y;
205 #ifdef HAVE_REMOTE
206 if ( m_y >= LCD_HEIGHT ) /* Remote Screen */
207 m_y -= LCD_HEIGHT;
208 #endif
211 printf("Mouse at 2: (%d, %d)\n", m_x, m_y);
214 #undef SQUARE
217 static bool event_handler(SDL_Event *event)
219 SDLKey ev_key;
221 switch(event->type)
223 case SDL_ACTIVEEVENT:
224 if (event->active.state & SDL_APPINPUTFOCUS)
226 if (event->active.gain == 1)
227 sdl_app_has_input_focus = 1;
228 else
229 sdl_app_has_input_focus = 0;
231 break;
232 case SDL_KEYDOWN:
233 case SDL_KEYUP:
234 ev_key = event->key.keysym.sym;
235 #if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
236 /* N900 with shared up/down cursor mapping. Seen on the German,
237 Finnish, Italian, French and Russian version. Probably more. */
238 if (event->key.keysym.mod & KMOD_MODE || n900_updown_key_pressed)
240 /* Prevent stuck up/down keys: If you release the ALT key before the cursor key,
241 rockbox will see a KEYUP event for left/right instead of up/down and
242 the previously pressed up/down key would stay active. */
243 if (ev_key == SDLK_LEFT || ev_key == SDLK_RIGHT)
245 if (event->type == SDL_KEYDOWN)
246 n900_updown_key_pressed = 1;
247 else
248 n900_updown_key_pressed = 0;
251 if (ev_key == SDLK_LEFT)
252 ev_key = SDLK_UP;
253 else if (ev_key == SDLK_RIGHT)
254 ev_key = SDLK_DOWN;
256 #endif
257 button_event(ev_key, event->type == SDL_KEYDOWN);
258 break;
259 #ifdef HAVE_TOUCHSCREEN
260 case SDL_MOUSEMOTION:
261 if (event->motion.state & SDL_BUTTON(1))
263 int x = event->motion.x / display_zoom;
264 int y = event->motion.y / display_zoom;
265 touchscreen_event(x, y);
267 break;
268 #endif
270 case SDL_MOUSEBUTTONUP:
271 case SDL_MOUSEBUTTONDOWN:
273 SDL_MouseButtonEvent *mev = &event->button;
274 mev->x /= display_zoom;
275 mev->y /= display_zoom;
276 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP);
277 break;
279 case SDL_QUIT:
280 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
281 sys_poweroff();
282 break;
283 case SDL_USEREVENT:
284 return true;
285 break;
288 return false;
291 void gui_message_loop(void)
293 SDL_Event event;
294 bool quit;
296 do {
297 /* wait for the next event */
298 if(SDL_WaitEvent(&event) == 0) {
299 printf("SDL_WaitEvent() error\n");
300 return; /* error, out of here */
303 sim_enter_irq_handler();
304 quit = event_handler(&event);
305 sim_exit_irq_handler();
307 } while(!quit);
310 static void button_event(int key, bool pressed)
312 int new_btn = 0;
313 switch (key)
315 #ifdef SIMULATOR
316 case USB_KEY:
317 if (!pressed)
319 static bool usb_connected = false;
320 usb_connected = !usb_connected;
321 sim_trigger_usb(usb_connected);
323 return;
324 #endif
325 #if (CONFIG_PLATFORM & PLATFORM_PANDORA)
326 case SDLK_LCTRL:
327 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
328 sys_poweroff();
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 #ifndef APPLICATION
377 case SDLK_KP0:
378 case SDLK_F5:
379 if(pressed)
381 sim_trigger_screendump();
382 return;
384 break;
385 #endif
386 #ifdef HAVE_TOUCHSCREEN
387 case SDLK_F4:
388 if(pressed)
390 touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
391 printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
393 #endif
394 default:
395 #ifdef HAVE_TOUCHSCREEN
396 new_btn = key_to_touch(key, mouse_coords);
397 if (!new_btn)
398 #endif
399 new_btn = key_to_button(key);
400 break;
402 /* Call to make up for scrollwheel target implementation. This is
403 * not handled in the main button.c driver, but on the target
404 * implementation (look at button-e200.c for example if you are trying to
405 * figure out why using button_get_data needed a hack before).
407 #if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
408 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
409 pressed)
411 /* Clear these buttons from the data - adding them to the queue is
412 * handled in the scrollwheel drivers for the targets. They do not
413 * store the scroll forward/back buttons in their button data for
414 * the button_read call.
416 #ifdef HAVE_BACKLIGHT
417 backlight_on();
418 #endif
419 #ifdef HAVE_BUTTON_LIGHT
420 buttonlight_on();
421 #endif
422 reset_poweroff_timer();
423 queue_post(&button_queue, new_btn, 1<<24);
424 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
426 #endif
428 if (pressed)
429 btn |= new_btn;
430 else
431 btn &= ~new_btn;
433 #if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
434 int button_read_device(int* data)
436 *data = mouse_coords;
437 #else
438 int button_read_device(void)
440 #endif
441 #ifdef HAS_BUTTON_HOLD
442 int hold_button = button_hold();
444 #ifdef HAVE_BACKLIGHT
445 /* light handling */
446 static int hold_button_old = false;
447 if (hold_button != hold_button_old)
449 hold_button_old = hold_button;
450 backlight_hold_changed(hold_button);
452 #endif
454 if (hold_button)
455 return BUTTON_NONE;
456 else
457 #endif
459 return btn;
462 void button_init_device(void)
464 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);