skin_engine: Automatically create touch regions for skin bars

skin bars now automatically create the touch region the same size
as the bar on touchscreen targets. This means touches will
magically "just work" for reveresed bars (rtl or otherwise).

~5% padding is added on all 4 sides of the region rectangle but
this may need to be tweaked.

Please consider the 'progressbar' and 'volume' touchregion actions
to be deprecated.

Kudos to my new wife for figuring out the bleedingly obvious way to
do this!

Change-Id: I997a7bcaa70fce9885808aae27953c7676e9c2ff
This commit is contained in:
Jonathan Gordon 2012-06-24 21:52:18 +10:00
parent 3d0459dfad
commit d336eb30f8
9 changed files with 101 additions and 7 deletions

View file

@ -871,6 +871,9 @@ static int parse_progressbar_tag(struct skin_element* element,
struct skin_tag_parameter *param = get_param(element, 0);
int curr_param = 0;
char *image_filename = NULL;
#ifdef HAVE_TOUCHSCREEN
bool suppress_touchregion = false;
#endif
if (element->params_count == 0 &&
element->tag->type != SKIN_TOKEN_PROGRESSBAR)
@ -1008,6 +1011,10 @@ static int parse_progressbar_tag(struct skin_element* element,
}
else if (!strcmp(text, "horizontal"))
pb->horizontal = true;
#ifdef HAVE_TOUCHSCREEN
else if (!strcmp(text, "notouch"))
suppress_touchregion = true;
#endif
else if (curr_param == 4)
image_filename = text;
@ -1055,6 +1062,61 @@ static int parse_progressbar_tag(struct skin_element* element,
token->type = SKIN_TOKEN_LIST_SCROLLBAR;
pb->type = token->type;
#ifdef HAVE_TOUCHSCREEN
if (!suppress_touchregion &&
(token->type == SKIN_TOKEN_VOLUMEBAR || token->type == SKIN_TOKEN_PROGRESSBAR))
{
struct touchregion *region = skin_buffer_alloc(sizeof(*region));
struct skin_token_list *item;
int wpad, hpad;
if (!region)
return 0;
if (token->type == SKIN_TOKEN_VOLUMEBAR)
region->action = ACTION_TOUCH_VOLUME;
else
region->action = ACTION_TOUCH_SCROLLBAR;
/* try to add some extra space on either end to make pressing the
* full bar easier. ~5% on either side
*/
wpad = pb->width * 5 / 100;
if (wpad > 10)
wpad = 10;
hpad = pb->height * 5 / 100;
if (hpad > 10)
hpad = 10;
region->x = pb->x - wpad;
if (region->x < 0)
region->x = 0;
region->width = pb->width + 2 * wpad;
if (region->x + region->width > curr_vp->vp.x + curr_vp->vp.width)
region->width = curr_vp->vp.x + curr_vp->vp.width - region->x;
region->y = pb->y - hpad;
if (region->y < 0)
region->y = 0;
region->height = pb->height + 2 * hpad;
if (region->y + region->height > curr_vp->vp.y + curr_vp->vp.height)
region->height = curr_vp->vp.y + curr_vp->vp.height - region->y;
region->wvp = PTRTOSKINOFFSET(skin_buffer, curr_vp);
region->reverse_bar = false;
region->allow_while_locked = false;
region->press_length = PRESS;
region->last_press = 0xffff;
region->armed = false;
region->bar = PTRTOSKINOFFSET(skin_buffer, pb);
item = new_skin_token_list_item(NULL, region);
if (!item)
return WPS_ERROR_INVALID_PARAM;
add_to_ll_chain(&wps_data->touchregions, item);
}
#endif
return 0;
#else
@ -1429,6 +1491,7 @@ static int parse_touchregion(struct skin_element *element,
region->last_press = 0xffff;
region->press_length = PRESS;
region->allow_while_locked = false;
region->bar = -1;
action = get_param_text(element, p++);
/* figure out the action */
@ -2324,6 +2387,31 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
#else
wps_data->wps_loaded = wps_data->tree >= 0;
#endif
#ifdef HAVE_TOUCHSCREEN
/* Check if there are any touch regions from the skin and not just
* auto-created ones for bars */
struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer,
wps_data->touchregions);
bool user_touch_region_found = false;
while (regions)
{
struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token);
struct touchregion *r = SKINOFFSETTOPTR(skin_buffer, token->value.data);
if (r->action != ACTION_TOUCH_SCROLLBAR &&
r->action != ACTION_TOUCH_VOLUME)
{
user_touch_region_found = true;
break;
}
regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
}
regions = SKINOFFSETTOPTR(skin_buffer, wps_data->touchregions);
if (regions && !user_touch_region_found)
wps_data->touchregions = -1;
#endif
skin_buffer = NULL;
return true;
}

View file

@ -99,7 +99,6 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
/* reposition the touch within the area */
vx -= r->x;
vy -= r->y;
switch(r->action)
{
@ -107,11 +106,13 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
case ACTION_TOUCH_VOLUME:
if (edge_offset)
{
struct progressbar *bar =
SKINOFFSETTOPTR(skin_buffer, r->bar);
if(r->width > r->height)
*edge_offset = vx*100/r->width;
else
*edge_offset = vy*100/r->height;
if (r->reverse_bar)
if (r->reverse_bar || (bar && bar->invert_fill_direction))
*edge_offset = 100 - *edge_offset;
}
temp = r;

View file

@ -215,6 +215,7 @@ struct touchregion {
int value;
};
long last_press; /* last tick this was pressed */
OFFSETTYPE(struct progressbar*) bar;
};

View file

@ -676,6 +676,12 @@ display cycling round the defined sublines. See
Some tags can be used to display a bar which draws according to the value of
the tag. To use these tags like a bar you need to use the following parameters
(\%XX should be replaced with the actual tag).
\opt{touchscreen}{
Volume and progress bars automatically create touch regions the same size
as the bar (slightly larger actually). This can be disabled with the
\config{notouch} option.
}
\begin{tagmap}
\config{\%XX(x, y, width, height, [options])}
@ -706,6 +712,9 @@ display cycling round the defined sublines. See
``slider'' option).
\item[nobar] -- don't draw the bar or its frame (for use with the
``slider'' option).
\opt{touchscreen}{
\item[notouch] -- don't create the touchregion for progress/volume bars.
}
\end{description}
Example: \config{\%pb(0,0,-,-,-,nofill, slider, slider\_image, invert)} -- draw

View file

@ -8,7 +8,6 @@
%T(46,292,84,24,menu)
%T(139,292,24,24,shuffle)
%T(182,292,24,24,repmode)
%T(22,254,199,13,progressbar)
%X(wpsbackdrop-240x320x16.bmp)
%xl(A,lock-240x320x16.bmp,11,292,2)
%xl(B,battery-240x320x16.bmp,46,292,10)

View file

@ -7,7 +7,6 @@
%X(wpsbackdrop-240x400x16.bmp)
%Cl(55,50,130,130,c,c)
%pb(22,284,199,13,pb-240x320x16.bmp)
%T(22,284,199,13,progressbar)
%T(90,238,60,20,playlist)
%?Tl(2.5)<%Vd(t)|%Vd(u)>
%V(0,0,240,330,1)

View file

@ -6,7 +6,6 @@
%T(0,207,84,24,menu)
%T(218,211,24,24,shuffle)
%T(261,207,24,24,repmode)
%T(10,162,300,15,progressbar)
%X(wpsbackdrop-320x240x16.bmp)
%xl(A,lock-320x240x16.bmp,91,207,2)
%xl(B,battery-320x240x16.bmp,126,207,10)

View file

@ -63,7 +63,6 @@
# progressbar and bottom icons
%V(0,360,-,-,-)
%pb(20,11,280,-,pb-320x480x16.bmp)
%T(20,0,280,40,progressbar)
#%?mh<%xd(Aa)|%xd(Ab)>
#%?bp<%?bc<%xd(Ba)|%xd(Bb)>|%?bl<|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)>>

View file

@ -49,7 +49,6 @@
# progressbar and bottom icons
%V(0,323,-,33,-)
%pb(25,0,750,-,pb-800x480x16.bmp)
%T(25,0,750,50,progressbar)
# volume
%V(344,400,108,60,-)