summaryrefslogtreecommitdiff
path: root/apps/gui
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-06-21 06:04:19 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-06-21 06:04:19 +0000
commita398c2846aa86650aa386a68cb51929477b6aa23 (patch)
tree4fa695ba8ea3a2b0e0c1f1c1ab5ac9ce27430804 /apps/gui
parent2b0ef19900295ef4e8da0fa52a13a04ccf76cb65 (diff)
downloadrockbox-a398c2846aa86650aa386a68cb51929477b6aa23.tar.gz
rockbox-a398c2846aa86650aa386a68cb51929477b6aa23.zip
Touchregion support for the Base Skin and FM Skins. display obviously needs to be in stylus mode for this to work. Just about all screens should be mostly useable if your sbs has the next/prev/select/cancel/menu regions defined.
Plenty of room to add new action abilities if they are wanted. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27004 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/gui')
-rw-r--r--apps/gui/bitmap/list.c3
-rw-r--r--apps/gui/skin_engine/skin_engine.h3
-rw-r--r--apps/gui/skin_engine/skin_touchsupport.c116
-rw-r--r--apps/gui/statusbar-skinned.c34
-rw-r--r--apps/gui/statusbar-skinned.h5
-rw-r--r--apps/gui/viewport.c5
-rw-r--r--apps/gui/wps.c196
7 files changed, 215 insertions, 147 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c
index ae7b19821e..fa015bf71a 100644
--- a/apps/gui/bitmap/list.c
+++ b/apps/gui/bitmap/list.c
@@ -359,7 +359,8 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
359 if (button == BUTTON_NONE) 359 if (button == BUTTON_NONE)
360 return ACTION_NONE; 360 return ACTION_NONE;
361 361
362 if (x > list_text_vp->x + list_width) 362 /* make sure it is inside the UI viewport */
363 if (!viewport_point_within_vp(list_text_vp, x, y))
363 /* wider than the list's viewport, ignore it */ 364 /* wider than the list's viewport, ignore it */
364 return ACTION_NONE; 365 return ACTION_NONE;
365 366
diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h
index 380b854d24..69991ab587 100644
--- a/apps/gui/skin_engine/skin_engine.h
+++ b/apps/gui/skin_engine/skin_engine.h
@@ -40,7 +40,8 @@ enum skinnable_screens {
40 40
41 41
42#ifdef HAVE_TOUCHSCREEN 42#ifdef HAVE_TOUCHSCREEN
43int wps_get_touchaction(struct wps_data *data); 43int skin_get_touchaction(struct wps_data *data, int* edge_offset);
44void skin_disarm_touchregions(struct wps_data *data);
44#endif 45#endif
45 46
46/* Do a update_type update of the skinned screen */ 47/* Do a update_type update of the skinned screen */
diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c
new file mode 100644
index 0000000000..9c0cda779a
--- /dev/null
+++ b/apps/gui/skin_engine/skin_touchsupport.c
@@ -0,0 +1,116 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 - Jonathan Gordon
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include <stdio.h>
24#include "action.h"
25#include "skin_engine.h"
26#include "wps_internals.h"
27
28/** Disarms all touchregions. */
29void skin_disarm_touchregions(struct wps_data *data)
30{
31 struct skin_token_list *regions = data->touchregions;
32 while (regions)
33 {
34 ((struct touchregion *)regions->token->value.data)->armed = false;
35 regions = regions->next;
36 }
37}
38
39/* Get the touched action.
40 * egde_offset is a percentage value for the position of the touch
41 * inside the bar for regions which arnt WPS_TOUCHREGION_ACTION type.
42 */
43int skin_get_touchaction(struct wps_data *data, int* edge_offset)
44{
45 int returncode = ACTION_NONE;
46 short x,y;
47 short vx, vy;
48 int type = action_get_touchscreen_press(&x, &y);
49 static int last_action = ACTION_NONE;
50 struct touchregion *r;
51 bool repeated = (type == BUTTON_REPEAT);
52 bool released = (type == BUTTON_REL);
53 bool pressed = (type == BUTTON_TOUCHSCREEN);
54 struct skin_token_list *regions = data->touchregions;
55
56 while (regions)
57 {
58 r = (struct touchregion *)regions->token->value.data;
59 /* make sure this region's viewport is visible */
60 if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
61 {
62 regions = regions->next;
63 continue;
64 }
65 /* check if it's inside this viewport */
66 if (viewport_point_within_vp(&(r->wvp->vp), x, y))
67 { /* reposition the touch inside the viewport since touchregions
68 * are relative to a preceding viewport */
69 vx = x - r->wvp->vp.x;
70 vy = y - r->wvp->vp.y;
71 /* now see if the point is inside this region */
72 if (vx >= r->x && vx < r->x+r->width &&
73 vy >= r->y && vy < r->y+r->height)
74 {
75 /* reposition the touch within the area */
76 vx -= r->x;
77 vy -= r->y;
78
79
80 switch(r->type)
81 {
82 case WPS_TOUCHREGION_ACTION:
83 if (r->armed && ((repeated && r->repeat) || (released && !r->repeat)))
84 {
85 last_action = r->action;
86 returncode = r->action;
87 }
88 if (pressed)
89 r->armed = true;
90 break;
91 default:
92 if (edge_offset)
93 {
94 if(r->width > r->height)
95 *edge_offset = vx*100/r->width;
96 else
97 *edge_offset = vy*100/r->height;
98 }
99 returncode = r->type;
100 break;
101 }
102 }
103 }
104 regions = regions->next;
105 }
106
107 /* On release, all regions are disarmed. */
108 if (released)
109 skin_disarm_touchregions(data);
110
111 if (returncode != ACTION_NONE)
112 return returncode;
113
114 last_action = ACTION_TOUCHSCREEN;
115 return ACTION_TOUCHSCREEN;
116}
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index fcd4cfbd9e..168b17fa38 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -21,6 +21,7 @@
21 21
22#include "config.h" 22#include "config.h"
23 23
24#include "action.h"
24#include "system.h" 25#include "system.h"
25#include "settings.h" 26#include "settings.h"
26#include "appevents.h" 27#include "appevents.h"
@@ -253,3 +254,36 @@ void sb_skin_init(void)
253 sb_skin[i].sync_data = &sb_skin_sync_data; 254 sb_skin[i].sync_data = &sb_skin_sync_data;
254 } 255 }
255} 256}
257
258#ifdef HAVE_TOUCHSCREEN
259static bool bypass_sb_touchregions = true;
260void sb_bypass_touchregions(bool enable)
261{
262 bypass_sb_touchregions = enable;
263}
264
265int sb_touch_to_button(int context)
266{
267 static int last_context = -1;
268 int button, offset;
269 if (bypass_sb_touchregions)
270 return ACTION_TOUCHSCREEN;
271
272 if (last_context != context)
273 skin_disarm_touchregions(&sb_skin_data[SCREEN_MAIN]);
274 last_context = context;
275 button = skin_get_touchaction(&sb_skin_data[SCREEN_MAIN], &offset);
276
277 switch (button)
278 {
279#ifdef HAVE_VOLUME_IN_LIST
280 case ACTION_WPS_VOLUP:
281 return ACTION_LIST_VOLUP;
282 case ACTION_WPS_VOLDOWN:
283 return ACTION_LIST_VOLDOWN;
284#endif
285 /* TODO */
286 }
287 return button;
288}
289#endif
diff --git a/apps/gui/statusbar-skinned.h b/apps/gui/statusbar-skinned.h
index eb27b06196..7925aa8093 100644
--- a/apps/gui/statusbar-skinned.h
+++ b/apps/gui/statusbar-skinned.h
@@ -43,6 +43,11 @@ void sb_skin_update(enum screen_type screen, bool force);
43void sb_skin_set_update_delay(int delay); 43void sb_skin_set_update_delay(int delay);
44bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen); 44bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen);
45 45
46#ifdef HAVE_TOUCHSCREEN
47void sb_bypass_touchregions(bool enable);
48int sb_touch_to_button(int context);
49#endif
50
46#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) 51#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
47char* sb_get_backdrop(enum screen_type screen); 52char* sb_get_backdrop(enum screen_type screen);
48bool sb_set_backdrop(enum screen_type screen, char* filename); 53bool sb_set_backdrop(enum screen_type screen, char* filename);
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index 7b4419f107..9e07c0fe08 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -169,6 +169,7 @@ static void toggle_theme(enum screen_type screen, bool force)
169 screens[screen].set_viewport(NULL); 169 screens[screen].set_viewport(NULL);
170 } 170 }
171 intptr_t force = first_boot?0:1; 171 intptr_t force = first_boot?0:1;
172
172 send_event(GUI_EVENT_ACTIONUPDATE, (void*)force); 173 send_event(GUI_EVENT_ACTIONUPDATE, (void*)force);
173 } 174 }
174 else 175 else
@@ -182,7 +183,9 @@ static void toggle_theme(enum screen_type screen, bool force)
182 send_event(GUI_EVENT_THEME_CHANGED, NULL); 183 send_event(GUI_EVENT_THEME_CHANGED, NULL);
183 FOR_NB_SCREENS(i) 184 FOR_NB_SCREENS(i)
184 was_enabled[i] = is_theme_enabled(i); 185 was_enabled[i] = is_theme_enabled(i);
185 186#ifdef HAVE_TOUCHSCREEN
187 sb_bypass_touchregions(!is_theme_enabled(SCREEN_MAIN));
188#endif
186 after_boot[screen] = true; 189 after_boot[screen] = true;
187} 190}
188 191
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 0a8ce899c5..dafc1cd278 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -85,10 +85,6 @@ static void wps_state_init(void);
85static void track_changed_callback(void *param); 85static void track_changed_callback(void *param);
86static void nextid3available_callback(void* param); 86static void nextid3available_callback(void* param);
87 87
88#ifdef HAVE_TOUCHSCREEN
89static void wps_disarm_touchregions(struct wps_data *data);
90#endif
91
92#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps" 88#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
93#ifdef HAVE_REMOTE_LCD 89#ifdef HAVE_REMOTE_LCD
94#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps" 90#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps"
@@ -227,6 +223,55 @@ static bool update_onvol_change(struct gui_wps * gwps)
227} 223}
228 224
229 225
226#ifdef HAVE_TOUCHSCREEN
227int skintouch_to_wps(struct wps_data *data)
228{
229 int offset = 0;
230 int button = skin_get_touchaction(data, &offset);
231 switch (button)
232 {
233 case ACTION_STD_PREV:
234 return ACTION_WPS_SKIPPREV;
235 case ACTION_STD_PREVREPEAT:
236 return ACTION_WPS_SEEKBACK;
237 case ACTION_STD_NEXT:
238 return ACTION_WPS_SKIPNEXT;
239 case ACTION_STD_NEXTREPEAT:
240 return ACTION_WPS_SEEKFWD;
241 case ACTION_STD_MENU:
242 return ACTION_WPS_MENU;
243 case ACTION_STD_CONTEXT:
244 return ACTION_WPS_CONTEXT;
245 case ACTION_STD_QUICKSCREEN:
246 return ACTION_WPS_QUICKSCREEN;
247 case WPS_TOUCHREGION_SCROLLBAR:
248 wps_state.id3->elapsed = wps_state.id3->length*offset/100;
249 if (!wps_state.paused)
250#if (CONFIG_CODEC == SWCODEC)
251 audio_pre_ff_rewind();
252#else
253 audio_pause();
254#endif
255 audio_ff_rewind(wps_state.id3->elapsed);
256#if (CONFIG_CODEC != SWCODEC)
257 if (!wps_state.paused)
258 audio_resume();
259#endif
260 return ACTION_TOUCHSCREEN;
261 case WPS_TOUCHREGION_VOLUME:
262 {
263 const int min_vol = sound_min(SOUND_VOLUME);
264 const int max_vol = sound_max(SOUND_VOLUME);
265 global_settings.volume = (offset * (max_vol - min_vol)) / 100;
266 global_settings.volume += min_vol;
267 setvol();
268 }
269 return ACTION_TOUCHSCREEN;
270 }
271 return button;
272}
273#endif
274
230bool ffwd_rew(int button) 275bool ffwd_rew(int button)
231{ 276{
232 unsigned int step = 0; /* current ff/rewind step */ 277 unsigned int step = 0; /* current ff/rewind step */
@@ -359,7 +404,7 @@ bool ffwd_rew(int button)
359 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK); 404 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK);
360#ifdef HAVE_TOUCHSCREEN 405#ifdef HAVE_TOUCHSCREEN
361 if (button == ACTION_TOUCHSCREEN) 406 if (button == ACTION_TOUCHSCREEN)
362 button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); 407 button = skintouch_to_wps(gui_wps[SCREEN_MAIN].data);
363 if (button != ACTION_WPS_SEEKFWD && 408 if (button != ACTION_WPS_SEEKFWD &&
364 button != ACTION_WPS_SEEKBACK) 409 button != ACTION_WPS_SEEKBACK)
365 button = ACTION_WPS_STOPSEEK; 410 button = ACTION_WPS_STOPSEEK;
@@ -616,150 +661,13 @@ static void gwps_enter_wps(void)
616 skin_update(gwps, WPS_REFRESH_ALL); 661 skin_update(gwps, WPS_REFRESH_ALL);
617 662
618#ifdef HAVE_TOUCHSCREEN 663#ifdef HAVE_TOUCHSCREEN
619 wps_disarm_touchregions(gui_wps[i].data); 664 skin_disarm_touchregions(gui_wps[i].data);
620#endif 665#endif
621 } 666 }
622 /* force statusbar/skin update since we just cleared the whole screen */ 667 /* force statusbar/skin update since we just cleared the whole screen */
623 send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); 668 send_event(GUI_EVENT_ACTIONUPDATE, (void*)1);
624} 669}
625 670
626#ifdef HAVE_TOUCHSCREEN
627/** Disarms all touchregions. */
628static void wps_disarm_touchregions(struct wps_data *data)
629{
630 struct skin_token_list *regions = data->touchregions;
631 while (regions)
632 {
633 ((struct touchregion *)regions->token->value.data)->armed = false;
634 regions = regions->next;
635 }
636}
637
638int wps_get_touchaction(struct wps_data *data)
639{
640 int returncode = ACTION_NONE;
641 short x,y;
642 short vx, vy;
643 int type = action_get_touchscreen_press(&x, &y);
644 static int last_action = ACTION_NONE;
645 struct touchregion *r;
646 bool repeated = (type == BUTTON_REPEAT);
647 bool released = (type == BUTTON_REL);
648 bool pressed = (type == BUTTON_TOUCHSCREEN);
649 struct skin_token_list *regions = data->touchregions;
650
651 while (regions)
652 {
653 r = (struct touchregion *)regions->token->value.data;
654 /* make sure this region's viewport is visible */
655 if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
656 {
657 regions = regions->next;
658 continue;
659 }
660 /* check if it's inside this viewport */
661 if (viewport_point_within_vp(&(r->wvp->vp), x, y))
662 { /* reposition the touch inside the viewport since touchregions
663 * are relative to a preceding viewport */
664 vx = x - r->wvp->vp.x;
665 vy = y - r->wvp->vp.y;
666 /* now see if the point is inside this region */
667 if (vx >= r->x && vx < r->x+r->width &&
668 vy >= r->y && vy < r->y+r->height)
669 {
670 /* reposition the touch within the area */
671 vx -= r->x;
672 vy -= r->y;
673
674 switch(r->type)
675 {
676 case WPS_TOUCHREGION_ACTION:
677 if (r->armed && ((repeated && r->repeat) || (released && !r->repeat)))
678 {
679 last_action = r->action;
680 returncode = r->action;
681 }
682 if (pressed)
683 r->armed = true;
684 break;
685 case WPS_TOUCHREGION_SCROLLBAR:
686 if(r->width > r->height)
687 /* landscape */
688 wps_state.id3->elapsed = (vx *
689 wps_state.id3->length) / r->width;
690 else
691 /* portrait */
692 wps_state.id3->elapsed = (vy *
693 wps_state.id3->length) / r->height;
694
695 if (!wps_state.paused)
696#if (CONFIG_CODEC == SWCODEC)
697 audio_pre_ff_rewind();
698#else
699 audio_pause();
700#endif
701 audio_ff_rewind(wps_state.id3->elapsed);
702#if (CONFIG_CODEC != SWCODEC)
703 if (!wps_state.paused)
704 audio_resume();
705#endif
706 break;
707 case WPS_TOUCHREGION_VOLUME:
708 {
709 const int min_vol = sound_min(SOUND_VOLUME);
710 const int max_vol = sound_max(SOUND_VOLUME);
711 if(r->width > r->height)
712 /* landscape */
713 global_settings.volume = (vx *
714 (max_vol - min_vol)) / r->width;
715 else
716 /* portrait */
717 global_settings.volume = ((r->height - vy) *
718 (max_vol-min_vol)) / r->height;
719
720 global_settings.volume += min_vol;
721 setvol();
722 returncode = ACTION_REDRAW;
723 }
724 }
725 }
726 }
727 regions = regions->next;
728 }
729
730 /* On release, all regions are disarmed. */
731 if (released)
732 wps_disarm_touchregions(data);
733
734 /* Now we need to convert buttons to the WPS context */
735 switch (returncode)
736 {
737 case ACTION_STD_PREV:
738 return ACTION_WPS_SKIPPREV;
739 case ACTION_STD_PREVREPEAT:
740 return ACTION_WPS_SEEKBACK;
741 case ACTION_STD_NEXT:
742 return ACTION_WPS_SKIPNEXT;
743 case ACTION_STD_NEXTREPEAT:
744 return ACTION_WPS_SEEKFWD;
745 case ACTION_STD_MENU:
746 return ACTION_WPS_MENU;
747 case ACTION_STD_CONTEXT:
748 return ACTION_WPS_CONTEXT;
749 case ACTION_STD_QUICKSCREEN:
750 return ACTION_WPS_QUICKSCREEN;
751 }
752
753 if (returncode != ACTION_NONE)
754 return returncode;
755
756
757 if ((last_action == ACTION_WPS_SEEKBACK || last_action == ACTION_WPS_SEEKFWD))
758 return ACTION_WPS_STOPSEEK;
759 last_action = ACTION_TOUCHSCREEN;
760 return ACTION_TOUCHSCREEN;
761}
762#endif
763/* The WPS can be left in two ways: 671/* The WPS can be left in two ways:
764 * a) call a function, which draws over the wps. In this case, the wps 672 * a) call a function, which draws over the wps. In this case, the wps
765 * will be still active (i.e. the below function didn't return) 673 * will be still active (i.e. the below function didn't return)
@@ -818,7 +726,7 @@ long gui_wps_show(void)
818 exit = true; 726 exit = true;
819#ifdef HAVE_TOUCHSCREEN 727#ifdef HAVE_TOUCHSCREEN
820 if (button == ACTION_TOUCHSCREEN) 728 if (button == ACTION_TOUCHSCREEN)
821 button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); 729 button = skintouch_to_wps(gui_wps[SCREEN_MAIN].data);
822#endif 730#endif
823/* The iPods/X5/M5 use a single button for the A-B mode markers, 731/* The iPods/X5/M5 use a single button for the A-B mode markers,
824 defined as ACTION_WPSAB_SINGLE in their config files. */ 732 defined as ACTION_WPSAB_SINGLE in their config files. */