Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

touchscreen: Port skin engine to gesture API

Use the gesture API for improved reliability.

Change-Id: I44c4e124132605ecf4f1499f97defd7b4b2d78e8

authored by

Aidan MacDonald and committed by
Solomon Peachy
010d22ed 0f99defe

+256 -244
+1
apps/gui/skin_engine/skin_engine.c
··· 119 119 skin->data.tree = -1; 120 120 #ifdef HAVE_TOUCHSCREEN 121 121 skin->data.touchregions = -1; 122 + gesture_reset(&skin->data.gesture); 122 123 #endif 123 124 #ifdef HAVE_SKIN_VARIABLES 124 125 skin->data.skinvars = -1;
+1 -2
apps/gui/skin_engine/skin_parser.c
··· 1284 1284 region->allow_while_locked = false; 1285 1285 region->press_length = PRESS; 1286 1286 region->last_press = -1; 1287 - region->armed = false; 1288 1287 region->bar = PTRTOSKINOFFSET(skin_buffer, pb); 1289 1288 region->label = PTRTOSKINOFFSET(skin_buffer, NULL); 1290 1289 ··· 1781 1780 p++; 1782 1781 1783 1782 region->wvp = PTRTOSKINOFFSET(skin_buffer, curr_vp); 1784 - region->armed = false; 1785 1783 region->reverse_bar = false; 1786 1784 region->value = 0; 1787 1785 region->last_press = -1; 1788 1786 region->press_length = PRESS; 1789 1787 region->allow_while_locked = false; 1790 1788 region->bar = PTRTOSKINOFFSET(skin_buffer, NULL); 1789 + 1791 1790 action = get_param_text(element, p++); 1792 1791 1793 1792 /* figure out the action */
+252 -240
apps/gui/skin_engine/skin_touchsupport.c
··· 37 37 /** Disarms all touchregions. */ 38 38 void skin_disarm_touchregions(struct gui_wps *gwps) 39 39 { 40 - struct wps_data *data = gwps->data; 41 - char* skin_buffer = get_skin_buffer(data); 42 - struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions); 43 - while (regions) 44 - { 45 - struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token); 46 - struct touchregion *region = SKINOFFSETTOPTR(skin_buffer, token->value.data); 47 - region->armed = false; 48 - regions = SKINOFFSETTOPTR(skin_buffer, regions->next); 49 - } 40 + gesture_reset(&gwps->data->gesture); 50 41 } 51 42 52 43 /* Get the touched action. ··· 56 47 int skin_get_touchaction(struct gui_wps *gwps, int* edge_offset) 57 48 { 58 49 struct wps_data *data = gwps->data; 59 - int returncode = ACTION_NONE; 60 - short x,y; 61 - short vx, vy; 62 - int type = action_get_touchscreen_press(&x, &y); 63 - struct skin_viewport *wvp; 64 - struct touchregion *r, *temp = NULL; 65 50 char* skin_buffer = get_skin_buffer(data); 66 - bool repeated = (type == BUTTON_REPEAT); 67 - bool released = (type == BUTTON_REL); 68 - bool pressed = (type == BUTTON_TOUCHSCREEN); 51 + struct touchregion *region = NULL; 52 + struct touchevent tevent; 53 + struct gesture_event gevent; 54 + 55 + action_get_touch_event(&tevent); 56 + gesture_process(&data->gesture, &tevent); 57 + 69 58 struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions); 70 - bool needs_repeat; 71 - 72 - while (regions) 59 + for (; regions && !region; 60 + regions = SKINOFFSETTOPTR(skin_buffer, regions->next)) 73 61 { 74 62 struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token); 75 - r = SKINOFFSETTOPTR(skin_buffer, token->value.data); 76 - wvp = SKINOFFSETTOPTR(skin_buffer, r->wvp); 63 + struct touchregion *r = SKINOFFSETTOPTR(skin_buffer, token->value.data); 64 + struct skin_viewport *wvp = SKINOFFSETTOPTR(skin_buffer, r->wvp); 65 + 77 66 /* make sure this region's viewport is visible */ 78 - if (wvp->hidden_flags&VP_DRAW_HIDDEN) 79 - { 80 - regions = SKINOFFSETTOPTR(skin_buffer, regions->next); 67 + if (wvp->hidden_flags & VP_DRAW_HIDDEN) 81 68 continue; 82 - } 69 + 70 + /* unless it's allow_while_locked, ignore the region if locked 71 + * (this is a special skin engine lock, different from softlock) */ 83 72 if (data->touchscreen_locked && 84 73 (r->action != ACTION_TOUCH_SOFTLOCK && !r->allow_while_locked)) 85 - { 86 - regions = SKINOFFSETTOPTR(skin_buffer, regions->next); 87 74 continue; 88 - } 89 - needs_repeat = r->press_length != PRESS; 90 - /* check if it's inside this viewport */ 91 - if (viewport_point_within_vp(&(wvp->vp), x, y)) 92 - { /* reposition the touch inside the viewport since touchregions 93 - * are relative to a preceding viewport */ 94 - vx = x - wvp->vp.x; 95 - vy = y - wvp->vp.y; 96 75 97 - /* project touches in the padding region so they clamp to the 98 - * edge of the region instead */ 99 - if(r->x - r->wpad <= vx && vx < r->x) 100 - vx = r->x; 101 - else if(r->x + r->width <= vx && vx < r->x + r->width + r->wpad) 102 - vx = r->x + r->width - 1; 103 - if(r->y - r->hpad <= vy && vy < r->y) 104 - vy = r->y; 105 - else if(r->y + r->height <= vy && vy < r->y + r->height + r->hpad) 106 - vy = r->y + r->height - 1; 76 + /* check for a gesture inside the region's parent viewport */ 77 + if (!gesture_get_event_in_vp(&data->gesture, &gevent, &wvp->vp)) 78 + continue; 107 79 108 - /* now see if the point is inside this region */ 109 - if (vx >= r->x && vx < r->x+r->width && 110 - vy >= r->y && vy < r->y+r->height) 111 - { 112 - /* reposition the touch within the area */ 113 - vx -= r->x; 114 - vy -= r->y; 80 + /* project touches inside the padding box to the region edge */ 81 + if (r->x - r->wpad <= gevent.ox && gevent.ox < r->x) 82 + gevent.ox = r->x; 83 + else if (r->x + r->width <= gevent.ox && gevent.ox < r->x + r->width + r->wpad) 84 + gevent.ox = r->x + r->width - 1; 115 85 116 - switch(r->action) 117 - { 118 - case ACTION_TOUCH_SCROLLBAR: 119 - case ACTION_TOUCH_VOLUME: 120 - case ACTION_TOUCH_SETTING: 121 - if (edge_offset) 122 - { 123 - struct progressbar *bar = 124 - SKINOFFSETTOPTR(skin_buffer, r->bar); 125 - if(r->width > r->height) { 126 - if(r->width > 1) 127 - *edge_offset = vx*1000/(r->width - 1); 128 - else 129 - *edge_offset = 0; 130 - } else { 131 - /* vertical bars are bottom-up by default */ 132 - if(r->height > 1) 133 - *edge_offset = 1000 - vy*1000/(r->height - 1); 134 - else 135 - *edge_offset = 0; 136 - } 86 + if (r->y - r->hpad <= gevent.y && gevent.y < r->y) 87 + gevent.oy = r->y; 88 + else if (r->y + r->height <= gevent.oy && gevent.oy < r->y + r->height + r->hpad) 89 + gevent.oy = r->y + r->height - 1; 137 90 138 - if (r->reverse_bar || (bar && bar->invert_fill_direction)) 139 - *edge_offset = 1000 - *edge_offset; 140 - } 141 - temp = r; 142 - returncode = r->action; 143 - r->last_press = current_tick; 144 - break; 145 - default: 146 - if (r->armed && ((repeated && needs_repeat) || 147 - (released && !needs_repeat))) 148 - { 149 - returncode = r->action; 150 - temp = r; 151 - } 152 - if (pressed) 153 - { 154 - r->armed = true; 155 - r->last_press = current_tick; 156 - } 157 - break; 91 + /* ignore anything outside of the region */ 92 + if (gevent.ox < r->x || gevent.ox >= r->x + r->width) 93 + continue; 94 + if (gevent.oy < r->y || gevent.oy >= r->y + r->height) 95 + continue; 96 + 97 + /* convert coordinates to region-relative and clamp */ 98 + gevent.x -= r->x; 99 + gevent.y -= r->y; 100 + 101 + switch (r->action) 102 + { 103 + case ACTION_TOUCH_SCROLLBAR: 104 + case ACTION_TOUCH_VOLUME: 105 + case ACTION_TOUCH_SETTING: 106 + /* we need something press-like */ 107 + if (!(gevent.id == GESTURE_TAP || 108 + gevent.id == GESTURE_LONG_PRESS || 109 + gevent.id == GESTURE_HOLD || 110 + gevent.id == GESTURE_DRAGSTART || 111 + gevent.id == GESTURE_DRAG)) 112 + break; 113 + 114 + if (edge_offset) 115 + { 116 + struct progressbar *bar = SKINOFFSETTOPTR(skin_buffer, r->bar); 117 + bool reverse = r->reverse_bar || (bar && bar->invert_fill_direction); 118 + int pos, lim; 119 + 120 + if (r->width > r->height) { 121 + /* left to right by default */ 122 + pos = MIN(MAX(0, gevent.x), r->width - 1); 123 + lim = r->width; 124 + } else { 125 + /* bottom up by default, so we need to add a reversal */ 126 + pos = MIN(MAX(0, gevent.y), r->height - 1); 127 + lim = r->height; 128 + reverse = !reverse; 158 129 } 130 + 131 + if (lim > 1) 132 + *edge_offset = pos * 1000 / (lim - 1); 133 + else 134 + *edge_offset = 0; 135 + 136 + if (reverse) 137 + *edge_offset = 1000 - *edge_offset; 159 138 } 160 - } 161 - regions = SKINOFFSETTOPTR(skin_buffer, regions->next); 162 - } 163 139 164 - /* On release, all regions are disarmed. */ 165 - if (released) 166 - skin_disarm_touchregions(gwps); 167 - if (temp && temp->press_length == LONG_PRESS) 168 - temp->armed = false; 140 + region = r; 141 + break; 169 142 170 - if (returncode != ACTION_NONE) 171 - { 172 - if (global_settings.party_mode) 173 - { 174 - switch (returncode) 143 + default: 144 + if (r->press_length == PRESS) 175 145 { 176 - case ACTION_WPS_PLAY: 177 - case ACTION_WPS_SKIPPREV: 178 - case ACTION_WPS_SKIPNEXT: 179 - case ACTION_WPS_STOP: 180 - returncode = ACTION_NONE; 181 - break; 182 - default: 146 + if (gevent.id != GESTURE_TAP) 183 147 break; 184 148 } 185 - } 186 - switch (returncode) 187 - { 188 - case ACTION_TOUCH_SOFTLOCK: 189 - data->touchscreen_locked = !data->touchscreen_locked; 190 - returncode = ACTION_NONE; 191 - break; 192 - case ACTION_WPS_PLAY: 193 - if (!audio_status()) 194 - { 195 - if ( global_status.resume_index != -1 ) 196 - { 197 - if (playlist_resume() != -1) 198 - { 199 - playlist_start(global_status.resume_index, 200 - global_status.resume_elapsed, 201 - global_status.resume_offset); 202 - } 203 - } 204 - else 205 - { 206 - splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); 207 - } 208 - } 209 - else 210 - { 211 - wps_do_playpause(false); 212 - } 213 - returncode = ACTION_REDRAW; 214 - break; 215 - case ACTION_WPS_SKIPPREV: 216 - audio_prev(); 217 - returncode = ACTION_REDRAW; 218 - break; 219 - case ACTION_WPS_SKIPNEXT: 220 - audio_next(); 221 - returncode = ACTION_REDRAW; 222 - break; 223 - case ACTION_WPS_STOP: 224 - audio_stop(); 225 - returncode = ACTION_REDRAW; 226 - break; 227 - case ACTION_SETTINGS_INC: 228 - case ACTION_SETTINGS_DEC: 149 + else if (r->press_length == LONG_PRESS) 229 150 { 230 - const struct settings_list *setting = 231 - temp->setting_data.setting; 232 - option_select_next_val(setting, 233 - returncode == ACTION_SETTINGS_DEC, 234 - true); 235 - returncode = ACTION_REDRAW; 151 + if (gevent.id != GESTURE_LONG_PRESS) 152 + break; 236 153 } 237 - break; 238 - case ACTION_SETTINGS_SET: 154 + else /* REPEAT */ 239 155 { 240 - struct touchsetting *data = &temp->setting_data; 241 - const struct settings_list *s = data->setting; 242 - void (*f)(int) = NULL; 243 - switch (s->flags&F_T_MASK) 244 - { 245 - case F_T_CUSTOM: 246 - s->custom_setting 247 - ->load_from_cfg(s->setting, SKINOFFSETTOPTR(skin_buffer, data->value.text)); 248 - break; 249 - case F_T_INT: 250 - case F_T_UINT: 251 - *(int*)s->setting = data->value.number; 252 - if ((s->flags & F_T_SOUND) == F_T_SOUND) 253 - sound_set(s->sound_setting->setting, data->value.number); 254 - else if (s->flags&F_CHOICE_SETTING) 255 - f = s->choice_setting->option_callback; 256 - else if (s->flags&F_TABLE_SETTING) 257 - f = s->table_setting->option_callback; 258 - else 259 - f = s->int_setting->option_callback; 156 + /* for repeat regions we allow dragging inside the region */ 157 + if (gevent.id != GESTURE_HOLD && 158 + gevent.id != GESTURE_DRAGSTART && 159 + gevent.id != GESTURE_DRAG) 160 + break; 260 161 261 - if (f) 262 - f(data->value.number); 263 - break; 264 - case F_T_BOOL: 265 - *(bool*)s->setting = data->value.number ? true : false; 266 - if (s->bool_setting->option_callback) 267 - s->bool_setting 268 - ->option_callback(data->value.number ? true : false); 269 - break; 270 - } 271 - returncode = ACTION_REDRAW; 162 + if (gevent.x < 0 || gevent.x >= r->width || 163 + gevent.y < 0 || gevent.y >= r->height) 164 + break; 272 165 } 166 + 167 + /* gesture is OK */ 168 + region = r; 273 169 break; 274 - case ACTION_TOUCH_MUTE: 170 + } 171 + } 172 + 173 + /* no region - pass the event upward */ 174 + if (!region) 175 + return ACTION_TOUCHSCREEN; 176 + 177 + int action = region->action; 178 + region->last_press = tevent.tick; 179 + 180 + if (global_settings.party_mode) 181 + { 182 + switch (action) 183 + { 184 + case ACTION_WPS_PLAY: 185 + case ACTION_WPS_SKIPPREV: 186 + case ACTION_WPS_SKIPNEXT: 187 + case ACTION_WPS_STOP: 188 + action = ACTION_NONE; 189 + break; 190 + default: 191 + break; 192 + } 193 + } 194 + 195 + switch (action) 196 + { 197 + case ACTION_TOUCH_SOFTLOCK: 198 + data->touchscreen_locked = !data->touchscreen_locked; 199 + action = ACTION_NONE; 200 + break; 201 + 202 + case ACTION_WPS_PLAY: 203 + if (!audio_status()) 204 + { 205 + if ( global_status.resume_index != -1 ) 275 206 { 276 - const int min_vol = sound_min(SOUND_VOLUME); 277 - if (global_status.volume == min_vol) 278 - global_status.volume = temp->value; 279 - else 207 + if (playlist_resume() != -1) 280 208 { 281 - temp->value = global_status.volume; 282 - global_status.volume = min_vol; 209 + playlist_start(global_status.resume_index, 210 + global_status.resume_elapsed, 211 + global_status.resume_offset); 283 212 } 284 - setvol(); 285 - returncode = ACTION_REDRAW; 286 213 } 287 - break; 288 - case ACTION_TOUCH_SHUFFLE: /* toggle shuffle mode */ 214 + else 289 215 { 290 - global_settings.playlist_shuffle = 291 - !global_settings.playlist_shuffle; 292 - replaygain_update(); 293 - if (global_settings.playlist_shuffle) 294 - playlist_randomise(NULL, current_tick, true); 295 - else 296 - playlist_sort(NULL, true); 297 - returncode = ACTION_REDRAW; 216 + splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); 298 217 } 218 + } 219 + else 220 + { 221 + wps_do_playpause(false); 222 + } 223 + 224 + action = ACTION_REDRAW; 225 + break; 226 + 227 + case ACTION_WPS_SKIPPREV: 228 + audio_prev(); 229 + action = ACTION_REDRAW; 230 + break; 231 + 232 + case ACTION_WPS_SKIPNEXT: 233 + audio_next(); 234 + action = ACTION_REDRAW; 235 + break; 236 + 237 + case ACTION_WPS_STOP: 238 + audio_stop(); 239 + action = ACTION_REDRAW; 240 + break; 241 + 242 + case ACTION_SETTINGS_INC: 243 + case ACTION_SETTINGS_DEC: 244 + { 245 + const struct settings_list *setting = region->setting_data.setting; 246 + bool decrement = (action == ACTION_SETTINGS_DEC); 247 + option_select_next_val(setting, decrement, true); 248 + action = ACTION_REDRAW; 249 + } break; 250 + 251 + case ACTION_SETTINGS_SET: 252 + { 253 + struct touchsetting *data = &region->setting_data; 254 + const struct settings_list *s = data->setting; 255 + void (*f)(int) = NULL; 256 + switch (s->flags & F_T_MASK) 257 + { 258 + case F_T_CUSTOM: 259 + s->custom_setting 260 + ->load_from_cfg(s->setting, SKINOFFSETTOPTR(skin_buffer, data->value.text)); 299 261 break; 300 - case ACTION_TOUCH_REPMODE: /* cycle the repeat mode setting */ 301 - { 302 - const struct settings_list *rep_setting = 303 - find_setting(&global_settings.repeat_mode); 304 - option_select_next_val(rep_setting, false, true); 305 - audio_flush_and_reload_tracks(); 306 - returncode = ACTION_REDRAW; 307 - } 262 + case F_T_INT: 263 + case F_T_UINT: 264 + *(int*)s->setting = data->value.number; 265 + if ((s->flags & F_T_SOUND) == F_T_SOUND) 266 + sound_set(s->sound_setting->setting, data->value.number); 267 + else if (s->flags&F_CHOICE_SETTING) 268 + f = s->choice_setting->option_callback; 269 + else if (s->flags&F_TABLE_SETTING) 270 + f = s->table_setting->option_callback; 271 + else 272 + f = s->int_setting->option_callback; 273 + 274 + if (f) 275 + f(data->value.number); 308 276 break; 309 - case ACTION_TOUCH_SETTING: 310 - { 311 - struct progressbar *bar = 312 - SKINOFFSETTOPTR(skin_buffer, temp->bar); 313 - if (bar && edge_offset) 314 - { 315 - int val, count; 316 - get_setting_info_for_bar(bar->setting, bar->setting_offset, &count, &val); 317 - val = *edge_offset * count / 1000; 318 - update_setting_value_from_touch(bar->setting, bar->setting_offset, val); 319 - } 320 - } 277 + case F_T_BOOL: 278 + *(bool*)s->setting = data->value.number ? true : false; 279 + if (s->bool_setting->option_callback) 280 + s->bool_setting 281 + ->option_callback(data->value.number ? true : false); 321 282 break; 322 283 } 323 - return returncode; 284 + 285 + action = ACTION_REDRAW; 286 + } break; 287 + 288 + case ACTION_TOUCH_MUTE: 289 + { 290 + const int min_vol = sound_min(SOUND_VOLUME); 291 + if (global_status.volume == min_vol) 292 + global_status.volume = region->value; 293 + else 294 + { 295 + region->value = global_status.volume; 296 + global_status.volume = min_vol; 297 + } 298 + 299 + setvol(); 300 + action = ACTION_REDRAW; 301 + } break; 302 + 303 + case ACTION_TOUCH_SHUFFLE: 304 + global_settings.playlist_shuffle = !global_settings.playlist_shuffle; 305 + replaygain_update(); 306 + if (global_settings.playlist_shuffle) 307 + playlist_randomise(NULL, current_tick, true); 308 + else 309 + playlist_sort(NULL, true); 310 + 311 + action = ACTION_REDRAW; 312 + break; 313 + 314 + case ACTION_TOUCH_REPMODE: 315 + { 316 + const struct settings_list *rep_setting = 317 + find_setting(&global_settings.repeat_mode); 318 + option_select_next_val(rep_setting, false, true); 319 + audio_flush_and_reload_tracks(); 320 + action = ACTION_REDRAW; 321 + } break; 322 + 323 + case ACTION_TOUCH_SETTING: 324 + { 325 + struct progressbar *bar = SKINOFFSETTOPTR(skin_buffer, region->bar); 326 + if (bar && edge_offset) 327 + { 328 + int val, count; 329 + get_setting_info_for_bar(bar->setting, 0, &count, &val); 330 + val = *edge_offset * count / 1000; 331 + update_setting_value_from_touch(bar->setting, 0, val); 332 + } 333 + 334 + action = ACTION_NONE; 335 + } break; 324 336 } 325 337 326 - return ACTION_TOUCHSCREEN; 338 + return action; 327 339 }
+2 -2
apps/gui/skin_engine/wps_internals.h
··· 27 27 28 28 #include "tag_table.h" 29 29 #include "skin_parser.h" 30 + #include "gesture.h" 30 31 #ifndef __PCTOOL__ 31 32 #include "core_alloc.h" 32 33 #endif ··· 218 219 int16_t hpad; /* padding to height */ 219 220 bool reverse_bar; /* if true 0% is the left or top */ 220 221 bool allow_while_locked; 221 - bool armed; /* A region is armed on press. Only armed regions are triggered 222 - on repeat or release. */ 223 222 enum { 224 223 PRESS, /* quick press only */ 225 224 LONG_PRESS, /* Long press without repeat */ ··· 371 370 #ifdef HAVE_TOUCHSCREEN 372 371 bool touchscreen_locked; 373 372 OFFSETTYPE(struct skin_token_list *) touchregions; 373 + struct gesture gesture; 374 374 #endif 375 375 #ifdef HAVE_ALBUMART 376 376 OFFSETTYPE(struct skin_albumart *) albumart;