summaryrefslogtreecommitdiff
path: root/apps
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
parent2b0ef19900295ef4e8da0fa52a13a04ccf76cb65 (diff)
downloadrockbox-a398c2846aa86650aa386a68cb51929477b6aa23.zip
rockbox-a398c2846aa86650aa386a68cb51929477b6aa23.tar.gz
rockbox-a398c2846aa86650aa386a68cb51929477b6aa23.tar.bz2
rockbox-a398c2846aa86650aa386a68cb51929477b6aa23.tar.xz
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')
-rw-r--r--apps/SOURCES3
-rw-r--r--apps/action.c10
-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
-rw-r--r--apps/radio/radio_skin.c26
10 files changed, 252 insertions, 149 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 93ec93f..58186d2 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -102,6 +102,9 @@ gui/skin_engine/skin_fonts.c
#endif
gui/skin_engine/skin_parser.c
gui/skin_engine/skin_tokens.c
+#ifdef HAVE_TOUCHSCREEN
+gui/skin_engine/skin_touchsupport.c
+#endif
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
gui/backdrop.c
diff --git a/apps/action.c b/apps/action.c
index cd76faa..8f427c8 100644
--- a/apps/action.c
+++ b/apps/action.c
@@ -38,6 +38,9 @@
#include "language.h"
#endif
#include "viewport.h"
+#ifdef HAVE_TOUCHSCREEN
+#include "statusbar-skinned.h"
+#endif
static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
work on startup */
@@ -320,7 +323,12 @@ static int get_action_worker(int context, int timeout,
int get_action(int context, int timeout)
{
- return get_action_worker(context,timeout,NULL);
+ int button = get_action_worker(context,timeout,NULL);
+#ifdef HAVE_TOUCHSCREEN
+ if (button == ACTION_TOUCHSCREEN)
+ button = sb_touch_to_button(context);
+#endif
+ return button;
}
int get_custom_action(int context,int timeout,
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c
index ae7b198..fa015bf 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)
if (button == BUTTON_NONE)
return ACTION_NONE;
- if (x > list_text_vp->x + list_width)
+ /* make sure it is inside the UI viewport */
+ if (!viewport_point_within_vp(list_text_vp, x, y))
/* wider than the list's viewport, ignore it */
return ACTION_NONE;
diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h
index 380b854..69991ab 100644
--- a/apps/gui/skin_engine/skin_engine.h
+++ b/apps/gui/skin_engine/skin_engine.h
@@ -40,7 +40,8 @@ enum skinnable_screens {
#ifdef HAVE_TOUCHSCREEN
-int wps_get_touchaction(struct wps_data *data);
+int skin_get_touchaction(struct wps_data *data, int* edge_offset);
+void skin_disarm_touchregions(struct wps_data *data);
#endif
/* 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 0000000..9c0cda7
--- /dev/null
+++ b/apps/gui/skin_engine/skin_touchsupport.c
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 - Jonathan Gordon
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include <stdio.h>
+#include "action.h"
+#include "skin_engine.h"
+#include "wps_internals.h"
+
+/** Disarms all touchregions. */
+void skin_disarm_touchregions(struct wps_data *data)
+{
+ struct skin_token_list *regions = data->touchregions;
+ while (regions)
+ {
+ ((struct touchregion *)regions->token->value.data)->armed = false;
+ regions = regions->next;
+ }
+}
+
+/* Get the touched action.
+ * egde_offset is a percentage value for the position of the touch
+ * inside the bar for regions which arnt WPS_TOUCHREGION_ACTION type.
+ */
+int skin_get_touchaction(struct wps_data *data, int* edge_offset)
+{
+ int returncode = ACTION_NONE;
+ short x,y;
+ short vx, vy;
+ int type = action_get_touchscreen_press(&x, &y);
+ static int last_action = ACTION_NONE;
+ struct touchregion *r;
+ bool repeated = (type == BUTTON_REPEAT);
+ bool released = (type == BUTTON_REL);
+ bool pressed = (type == BUTTON_TOUCHSCREEN);
+ struct skin_token_list *regions = data->touchregions;
+
+ while (regions)
+ {
+ r = (struct touchregion *)regions->token->value.data;
+ /* make sure this region's viewport is visible */
+ if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
+ {
+ regions = regions->next;
+ continue;
+ }
+ /* check if it's inside this viewport */
+ if (viewport_point_within_vp(&(r->wvp->vp), x, y))
+ { /* reposition the touch inside the viewport since touchregions
+ * are relative to a preceding viewport */
+ vx = x - r->wvp->vp.x;
+ vy = y - r->wvp->vp.y;
+ /* now see if the point is inside this region */
+ if (vx >= r->x && vx < r->x+r->width &&
+ vy >= r->y && vy < r->y+r->height)
+ {
+ /* reposition the touch within the area */
+ vx -= r->x;
+ vy -= r->y;
+
+
+ switch(r->type)
+ {
+ case WPS_TOUCHREGION_ACTION:
+ if (r->armed && ((repeated && r->repeat) || (released && !r->repeat)))
+ {
+ last_action = r->action;
+ returncode = r->action;
+ }
+ if (pressed)
+ r->armed = true;
+ break;
+ default:
+ if (edge_offset)
+ {
+ if(r->width > r->height)
+ *edge_offset = vx*100/r->width;
+ else
+ *edge_offset = vy*100/r->height;
+ }
+ returncode = r->type;
+ break;
+ }
+ }
+ }
+ regions = regions->next;
+ }
+
+ /* On release, all regions are disarmed. */
+ if (released)
+ skin_disarm_touchregions(data);
+
+ if (returncode != ACTION_NONE)
+ return returncode;
+
+ last_action = ACTION_TOUCHSCREEN;
+ return ACTION_TOUCHSCREEN;
+}
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index fcd4cfb..168b17f 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -21,6 +21,7 @@
#include "config.h"
+#include "action.h"
#include "system.h"
#include "settings.h"
#include "appevents.h"
@@ -253,3 +254,36 @@ void sb_skin_init(void)
sb_skin[i].sync_data = &sb_skin_sync_data;
}
}
+
+#ifdef HAVE_TOUCHSCREEN
+static bool bypass_sb_touchregions = true;
+void sb_bypass_touchregions(bool enable)
+{
+ bypass_sb_touchregions = enable;
+}
+
+int sb_touch_to_button(int context)
+{
+ static int last_context = -1;
+ int button, offset;
+ if (bypass_sb_touchregions)
+ return ACTION_TOUCHSCREEN;
+
+ if (last_context != context)
+ skin_disarm_touchregions(&sb_skin_data[SCREEN_MAIN]);
+ last_context = context;
+ button = skin_get_touchaction(&sb_skin_data[SCREEN_MAIN], &offset);
+
+ switch (button)
+ {
+#ifdef HAVE_VOLUME_IN_LIST
+ case ACTION_WPS_VOLUP:
+ return ACTION_LIST_VOLUP;
+ case ACTION_WPS_VOLDOWN:
+ return ACTION_LIST_VOLDOWN;
+#endif
+ /* TODO */
+ }
+ return button;
+}
+#endif
diff --git a/apps/gui/statusbar-skinned.h b/apps/gui/statusbar-skinned.h
index eb27b06..7925aa8 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);
void sb_skin_set_update_delay(int delay);
bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen);
+#ifdef HAVE_TOUCHSCREEN
+void sb_bypass_touchregions(bool enable);
+int sb_touch_to_button(int context);
+#endif
+
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
char* sb_get_backdrop(enum screen_type screen);
bool sb_set_backdrop(enum screen_type screen, char* filename);
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index 7b4419f..9e07c0f 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)
screens[screen].set_viewport(NULL);
}
intptr_t force = first_boot?0:1;
+
send_event(GUI_EVENT_ACTIONUPDATE, (void*)force);
}
else
@@ -182,7 +183,9 @@ static void toggle_theme(enum screen_type screen, bool force)
send_event(GUI_EVENT_THEME_CHANGED, NULL);
FOR_NB_SCREENS(i)
was_enabled[i] = is_theme_enabled(i);
-
+#ifdef HAVE_TOUCHSCREEN
+ sb_bypass_touchregions(!is_theme_enabled(SCREEN_MAIN));
+#endif
after_boot[screen] = true;
}
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 0a8ce89..dafc1cd 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -85,10 +85,6 @@ static void wps_state_init(void);
static void track_changed_callback(void *param);
static void nextid3available_callback(void* param);
-#ifdef HAVE_TOUCHSCREEN
-static void wps_disarm_touchregions(struct wps_data *data);
-#endif
-
#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
#ifdef HAVE_REMOTE_LCD
#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps"
@@ -227,6 +223,55 @@ static bool update_onvol_change(struct gui_wps * gwps)
}
+#ifdef HAVE_TOUCHSCREEN
+int skintouch_to_wps(struct wps_data *data)
+{
+ int offset = 0;
+ int button = skin_get_touchaction(data, &offset);
+ switch (button)
+ {
+ case ACTION_STD_PREV:
+ return ACTION_WPS_SKIPPREV;
+ case ACTION_STD_PREVREPEAT:
+ return ACTION_WPS_SEEKBACK;
+ case ACTION_STD_NEXT:
+ return ACTION_WPS_SKIPNEXT;
+ case ACTION_STD_NEXTREPEAT:
+ return ACTION_WPS_SEEKFWD;
+ case ACTION_STD_MENU:
+ return ACTION_WPS_MENU;
+ case ACTION_STD_CONTEXT:
+ return ACTION_WPS_CONTEXT;
+ case ACTION_STD_QUICKSCREEN:
+ return ACTION_WPS_QUICKSCREEN;
+ case WPS_TOUCHREGION_SCROLLBAR:
+ wps_state.id3->elapsed = wps_state.id3->length*offset/100;
+ if (!wps_state.paused)
+#if (CONFIG_CODEC == SWCODEC)
+ audio_pre_ff_rewind();
+#else
+ audio_pause();
+#endif
+ audio_ff_rewind(wps_state.id3->elapsed);
+#if (CONFIG_CODEC != SWCODEC)
+ if (!wps_state.paused)
+ audio_resume();
+#endif
+ return ACTION_TOUCHSCREEN;
+ case WPS_TOUCHREGION_VOLUME:
+ {
+ const int min_vol = sound_min(SOUND_VOLUME);
+ const int max_vol = sound_max(SOUND_VOLUME);
+ global_settings.volume = (offset * (max_vol - min_vol)) / 100;
+ global_settings.volume += min_vol;
+ setvol();
+ }
+ return ACTION_TOUCHSCREEN;
+ }
+ return button;
+}
+#endif
+
bool ffwd_rew(int button)
{
unsigned int step = 0; /* current ff/rewind step */
@@ -359,7 +404,7 @@ bool ffwd_rew(int button)
button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK);
#ifdef HAVE_TOUCHSCREEN
if (button == ACTION_TOUCHSCREEN)
- button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data);
+ button = skintouch_to_wps(gui_wps[SCREEN_MAIN].data);
if (button != ACTION_WPS_SEEKFWD &&
button != ACTION_WPS_SEEKBACK)
button = ACTION_WPS_STOPSEEK;
@@ -616,150 +661,13 @@ static void gwps_enter_wps(void)
skin_update(gwps, WPS_REFRESH_ALL);
#ifdef HAVE_TOUCHSCREEN
- wps_disarm_touchregions(gui_wps[i].data);
+ skin_disarm_touchregions(gui_wps[i].data);
#endif
}
/* force statusbar/skin update since we just cleared the whole screen */
send_event(GUI_EVENT_ACTIONUPDATE, (void*)1);
}
-#ifdef HAVE_TOUCHSCREEN
-/** Disarms all touchregions. */
-static void wps_disarm_touchregions(struct wps_data *data)
-{
- struct skin_token_list *regions = data->touchregions;
- while (regions)
- {
- ((struct touchregion *)regions->token->value.data)->armed = false;
- regions = regions->next;
- }
-}
-
-int wps_get_touchaction(struct wps_data *data)
-{
- int returncode = ACTION_NONE;
- short x,y;
- short vx, vy;
- int type = action_get_touchscreen_press(&x, &y);
- static int last_action = ACTION_NONE;
- struct touchregion *r;
- bool repeated = (type == BUTTON_REPEAT);
- bool released = (type == BUTTON_REL);
- bool pressed = (type == BUTTON_TOUCHSCREEN);
- struct skin_token_list *regions = data->touchregions;
-
- while (regions)
- {
- r = (struct touchregion *)regions->token->value.data;
- /* make sure this region's viewport is visible */
- if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
- {
- regions = regions->next;
- continue;
- }
- /* check if it's inside this viewport */
- if (viewport_point_within_vp(&(r->wvp->vp), x, y))
- { /* reposition the touch inside the viewport since touchregions
- * are relative to a preceding viewport */
- vx = x - r->wvp->vp.x;
- vy = y - r->wvp->vp.y;
- /* now see if the point is inside this region */
- if (vx >= r->x && vx < r->x+r->width &&
- vy >= r->y && vy < r->y+r->height)
- {
- /* reposition the touch within the area */
- vx -= r->x;
- vy -= r->y;
-
- switch(r->type)
- {
- case WPS_TOUCHREGION_ACTION:
- if (r->armed && ((repeated && r->repeat) || (released && !r->repeat)))
- {
- last_action = r->action;
- returncode = r->action;
- }
- if (pressed)
- r->armed = true;
- break;
- case WPS_TOUCHREGION_SCROLLBAR:
- if(r->width > r->height)
- /* landscape */
- wps_state.id3->elapsed = (vx *
- wps_state.id3->length) / r->width;
- else
- /* portrait */
- wps_state.id3->elapsed = (vy *
- wps_state.id3->length) / r->height;
-
- if (!wps_state.paused)
-#if (CONFIG_CODEC == SWCODEC)
- audio_pre_ff_rewind();
-#else
- audio_pause();
-#endif
- audio_ff_rewind(wps_state.id3->elapsed);
-#if (CONFIG_CODEC != SWCODEC)
- if (!wps_state.paused)
- audio_resume();
-#endif
- break;
- case WPS_TOUCHREGION_VOLUME:
- {
- const int min_vol = sound_min(SOUND_VOLUME);
- const int max_vol = sound_max(SOUND_VOLUME);
- if(r->width > r->height)
- /* landscape */
- global_settings.volume = (vx *
- (max_vol - min_vol)) / r->width;
- else
- /* portrait */
- global_settings.volume = ((r->height - vy) *
- (max_vol-min_vol)) / r->height;
-
- global_settings.volume += min_vol;
- setvol();
- returncode = ACTION_REDRAW;
- }
- }
- }
- }
- regions = regions->next;
- }
-
- /* On release, all regions are disarmed. */
- if (released)
- wps_disarm_touchregions(data);
-
- /* Now we need to convert buttons to the WPS context */
- switch (returncode)
- {
- case ACTION_STD_PREV:
- return ACTION_WPS_SKIPPREV;
- case ACTION_STD_PREVREPEAT:
- return ACTION_WPS_SEEKBACK;
- case ACTION_STD_NEXT:
- return ACTION_WPS_SKIPNEXT;
- case ACTION_STD_NEXTREPEAT:
- return ACTION_WPS_SEEKFWD;
- case ACTION_STD_MENU:
- return ACTION_WPS_MENU;
- case ACTION_STD_CONTEXT:
- return ACTION_WPS_CONTEXT;
- case ACTION_STD_QUICKSCREEN:
- return ACTION_WPS_QUICKSCREEN;
- }
-
- if (returncode != ACTION_NONE)
- return returncode;
-
-
- if ((last_action == ACTION_WPS_SEEKBACK || last_action == ACTION_WPS_SEEKFWD))
- return ACTION_WPS_STOPSEEK;
- last_action = ACTION_TOUCHSCREEN;
- return ACTION_TOUCHSCREEN;
-}
-#endif
/* The WPS can be left in two ways:
* a) call a function, which draws over the wps. In this case, the wps
* will be still active (i.e. the below function didn't return)
@@ -818,7 +726,7 @@ long gui_wps_show(void)
exit = true;
#ifdef HAVE_TOUCHSCREEN
if (button == ACTION_TOUCHSCREEN)
- button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data);
+ button = skintouch_to_wps(gui_wps[SCREEN_MAIN].data);
#endif
/* The iPods/X5/M5 use a single button for the A-B mode markers,
defined as ACTION_WPSAB_SINGLE in their config files. */
diff --git a/apps/radio/radio_skin.c b/apps/radio/radio_skin.c
index 838d1f9..c7994b3 100644
--- a/apps/radio/radio_skin.c
+++ b/apps/radio/radio_skin.c
@@ -108,8 +108,32 @@ void fms_skin_init(void)
int fms_do_button_loop(bool update_screen)
{
- return skin_wait_for_action(fms_skin, CONTEXT_FM,
+ int button = skin_wait_for_action(fms_skin, CONTEXT_FM,
update_screen ? TIMEOUT_NOBLOCK : HZ);
+#ifdef HAVE_TOUCHSCREEN
+ int offset;
+ if (button == ACTION_TOUCHSCREEN)
+ button = skin_get_touchaction(&fms_skin_data[SCREEN_MAIN], &offset);
+ switch (button)
+ {
+ case ACTION_WPS_STOP:
+ return ACTION_FM_STOP;
+ case ACTION_STD_CANCEL:
+ return ACTION_FM_EXIT;
+ case ACTION_WPS_VOLUP:
+ return ACTION_SETTINGS_INC;
+ case ACTION_WPS_VOLDOWN:
+ return ACTION_SETTINGS_DEC;
+ case ACTION_WPS_PLAY:
+ return ACTION_FM_PLAY;
+ case ACTION_STD_MENU:
+ return ACTION_FM_MENU;
+ case WPS_TOUCHREGION_SCROLLBAR:
+ /* TODO */
+ break;
+ }
+#endif
+ return button;
}
struct gui_wps *fms_get(enum screen_type screen)