summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2023-12-01 15:09:11 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2023-12-03 10:13:19 -0500
commit9dd1b0f46da32ea019e51972715d67bf8ba77687 (patch)
tree885c48ceab9102b9acf3e24dd68a1d17b265229b
parent58ec8c62bb8c8293ae6424fe2b46c09c7e3cf70e (diff)
downloadrockbox-9dd1b0f46da32ea019e51972715d67bf8ba77687.tar.gz
rockbox-9dd1b0f46da32ea019e51972715d67bf8ba77687.zip
[BugFix] YesNo screen scrolling
clearing the viewport stops the scroller so instead clear the viewport ourselves [this might cause some glitching but should be acceptable] in testing this causes no discernible ill effect -- time will tell.. Change-Id: Ia73a459205e37c8aebdf1cd82cd742df3d803af8
-rw-r--r--apps/gui/yesno.c200
1 files changed, 103 insertions, 97 deletions
diff --git a/apps/gui/yesno.c b/apps/gui/yesno.c
index a0fd908727..f5de0f67a3 100644
--- a/apps/gui/yesno.c
+++ b/apps/gui/yesno.c
@@ -30,16 +30,16 @@
30#include "viewport.h" 30#include "viewport.h"
31#include "appevents.h" 31#include "appevents.h"
32 32
33#include <stdio.h> 33//#include <stdio.h>
34#include "splash.h" 34#include "splash.h"
35#include "backlight.h"
35 36
36struct gui_yesno 37struct gui_yesno
37{ 38{
39 struct viewport vp;
38 const struct text_message * main_message; 40 const struct text_message * main_message;
39 const struct text_message * result_message[2];
40
41 struct viewport *vp;
42 struct screen * display; 41 struct screen * display;
42 int vp_lines;
43 /* timeout data */ 43 /* timeout data */
44 long end_tick; 44 long end_tick;
45 enum yesno_res tmo_default_res; 45 enum yesno_res tmo_default_res;
@@ -48,16 +48,13 @@ struct gui_yesno
48static void talk_text_message(const struct text_message * message, bool enqueue) 48static void talk_text_message(const struct text_message * message, bool enqueue)
49{ 49{
50 int line; 50 int line;
51 if(message) 51 for(line=0; line < message->nb_lines; line++)
52 { 52 {
53 for(line=0; line<message->nb_lines; line++) 53 long id = P2ID((unsigned char *)message->message_lines[line]);
54 if(id>=0)
54 { 55 {
55 long id = P2ID((unsigned char *)message->message_lines[line]); 56 talk_id(id, enqueue);
56 if(id>=0) 57 enqueue = true;
57 {
58 talk_id(id, enqueue);
59 enqueue = true;
60 }
61 } 58 }
62 } 59 }
63} 60}
@@ -67,7 +64,8 @@ static int put_message(struct screen *display,
67 int start, int max_y) 64 int start, int max_y)
68{ 65{
69 int i; 66 int i;
70 for(i=0; i<message->nb_lines && i+start<max_y; i++) 67 int ct = MIN(message->nb_lines, max_y - start);
68 for(i=0; i < ct; i++)
71 { 69 {
72 display->puts_scroll(0, i+start, 70 display->puts_scroll(0, i+start,
73 P2STR((unsigned char *)message->message_lines[i])); 71 P2STR((unsigned char *)message->message_lines[i]));
@@ -82,22 +80,24 @@ static int put_message(struct screen *display,
82static void gui_yesno_draw(struct gui_yesno * yn) 80static void gui_yesno_draw(struct gui_yesno * yn)
83{ 81{
84 struct screen * display=yn->display; 82 struct screen * display=yn->display;
85 struct viewport *vp = yn->vp; 83 struct viewport *vp = &yn->vp;
86 int nb_lines, vp_lines, line_shift=0; 84 int vp_lines = yn->vp_lines;
87 struct viewport *last_vp;
88 enum yesno_res def_res = yn->tmo_default_res; 85 enum yesno_res def_res = yn->tmo_default_res;
89 long end_tick = yn->end_tick; 86 const struct text_message *main_message = yn->main_message;
87 int line_shift = 0;
88 struct viewport *last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN);
90 89
91 last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN); 90 /* do our own clear to avoid stopping scrolling */
92 display->clear_viewport(); 91 int oldmode = vp->drawmode;
93 nb_lines = yn->main_message->nb_lines; 92 vp->drawmode ^= DRMODE_INVERSEVID;
94 vp_lines = viewport_get_nb_lines(vp); 93 vp->drawmode |= DRMODE_SOLID;
94 display->fillrect(0, 0, vp->width, vp->height);
95 vp->drawmode = oldmode;
95 96
96 if(nb_lines+3< vp_lines) 97 if(main_message->nb_lines + 3 < vp_lines)
97 line_shift=1; 98 line_shift = 1;
98 99
99 line_shift += put_message(display, yn->main_message, 100 line_shift += put_message(display, main_message, line_shift, vp_lines);
100 line_shift, vp_lines);
101 101
102#ifdef HAVE_TOUCHSCREEN 102#ifdef HAVE_TOUCHSCREEN
103 if (display->screen_type == SCREEN_MAIN) 103 if (display->screen_type == SCREEN_MAIN)
@@ -113,9 +113,9 @@ static void gui_yesno_draw(struct gui_yesno * yn)
113 113
114 if (def_res == YESNO_YES) 114 if (def_res == YESNO_YES)
115 { 115 {
116 display->getstringsize(" (0)", &tmo_w, NULL); 116 display->getstringsize(" (00)", &tmo_w, NULL);
117 tm_rem = ((end_tick - current_tick) / 100); 117 tm_rem = ((yn->end_tick - current_tick) / 100);
118 btn_fmt = "%s (%d)"; 118 btn_fmt = "%s (%02d)";
119 } 119 }
120 else 120 else
121 { 121 {
@@ -132,9 +132,9 @@ static void gui_yesno_draw(struct gui_yesno * yn)
132 132
133 if (def_res == YESNO_NO) 133 if (def_res == YESNO_NO)
134 { 134 {
135 display->getstringsize(" (0)", &tmo_w, NULL); 135 display->getstringsize(" (00)", &tmo_w, NULL);
136 tm_rem = ((end_tick - current_tick) / 100); 136 tm_rem = ((yn->end_tick - current_tick) / 100);
137 btn_fmt = "%s (%d)"; 137 btn_fmt = "%s (%02d)";
138 } 138 }
139 else 139 else
140 { 140 {
@@ -149,20 +149,22 @@ static void gui_yesno_draw(struct gui_yesno * yn)
149 } 149 }
150#else 150#else
151 /* Space remaining for yes / no text ? */ 151 /* Space remaining for yes / no text ? */
152 if(line_shift+2 <= vp_lines) 152 if(line_shift + 2 <= vp_lines)
153 { 153 {
154 if(line_shift+3 <= vp_lines) 154 if(line_shift + 3 <= vp_lines)
155 line_shift++; 155 line_shift++;
156 display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON)); 156 display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON));
157 display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY)); 157 display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY));
158 158
159 if (def_res == YESNO_YES || def_res == YESNO_NO) 159 if (def_res == YESNO_YES || def_res == YESNO_NO)
160 { 160 {
161 int tm_rem = ((end_tick - current_tick) / 100); 161 int tm_rem = ((yn->end_tick - current_tick) / 100);
162 if (def_res == YESNO_YES) 162 if (def_res == YESNO_YES)
163 display->putsf(0, line_shift, "%s (%d)", str(LANG_CONFIRM_WITH_BUTTON), tm_rem); 163 display->putsf(0, line_shift, "%s (%02d)",
164 str(LANG_CONFIRM_WITH_BUTTON), tm_rem);
164 else 165 else
165 display->putsf(0, line_shift+1, "%s (%d)", str(LANG_CANCEL_WITH_ANY), tm_rem); 166 display->putsf(0, line_shift+1, "%s (%02d)",
167 str(LANG_CANCEL_WITH_ANY), tm_rem);
166 } 168 }
167 } 169 }
168#endif 170#endif
@@ -177,22 +179,18 @@ static void gui_yesno_draw(struct gui_yesno * yn)
177 * YESNO_NO if no 179 * YESNO_NO if no
178 * YESNO_YES if yes 180 * YESNO_YES if yes
179 */ 181 */
180static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result) 182static void gui_yesno_draw_result(struct gui_yesno * yn, const struct text_message * message)
181{ 183{
182 const struct text_message * message=yn->result_message[result]; 184 struct viewport *vp = &yn->vp;
183 struct viewport *vp = yn->vp;
184 struct screen * display=yn->display; 185 struct screen * display=yn->display;
185 struct viewport *last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN); 186 struct viewport *last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN);
186 187
187 if(message==NULL)
188 return false;
189 display->clear_viewport(); 188 display->clear_viewport();
190 put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); 189 put_message(display, message, 0, yn->vp_lines);
191 display->update_viewport(); 190 display->update_viewport();
192 display->set_viewport(last_vp); 191 display->set_viewport(last_vp);
193 return(true);
194} 192}
195 193#if 0
196static void gui_yesno_ui_update(unsigned short id, void *event_data, void *user_data) 194static void gui_yesno_ui_update(unsigned short id, void *event_data, void *user_data)
197{ 195{
198 (void)id; 196 (void)id;
@@ -200,11 +198,13 @@ static void gui_yesno_ui_update(unsigned short id, void *event_data, void *user_
200 198
201 struct gui_yesno* yn = (struct gui_yesno*)user_data; 199 struct gui_yesno* yn = (struct gui_yesno*)user_data;
202 FOR_NB_SCREENS(i) 200 FOR_NB_SCREENS(i)
201 {
203 gui_yesno_draw(&yn[i]); 202 gui_yesno_draw(&yn[i]);
203 }
204} 204}
205 205#endif
206/* Display a YES_NO prompt to the user 206/* Display a YES_NO prompt to the user
207 * 207 *
208 * ticks < HZ will be ignored and the prompt will be blocking 208 * ticks < HZ will be ignored and the prompt will be blocking
209 * tmo_default_res is the answer that is returned when the timeout expires 209 * tmo_default_res is the answer that is returned when the timeout expires
210 * a default result of YESNO_TMO will also make the prompt blocking 210 * a default result of YESNO_TMO will also make the prompt blocking
@@ -222,14 +222,14 @@ enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res
222 const struct text_message * yes_message, 222 const struct text_message * yes_message,
223 const struct text_message * no_message) 223 const struct text_message * no_message)
224{ 224{
225 int button; 225 #define YESNO_NONE (-1)
226 int result=-1; 226 int action;
227 bool result_displayed = false; 227 bool backlight_on;
228 bool talk_menu = global_settings.talk_menu;
229 int result = YESNO_NONE;
228 struct gui_yesno yn[NB_SCREENS]; 230 struct gui_yesno yn[NB_SCREENS];
229 struct viewport vp[NB_SCREENS]; 231 long talked_tick = current_tick - 1;
230 long talked_tick = 0;
231 long end_tick = current_tick + ticks; 232 long end_tick = current_tick + ticks;
232 long button_scan_tmo = HZ/2;
233 233
234 if (ticks < HZ) /* Display a prompt with NO timeout to the user */ 234 if (ticks < HZ) /* Display a prompt with NO timeout to the user */
235 { 235 {
@@ -240,15 +240,11 @@ enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res
240 { 240 {
241 yn[i].end_tick = end_tick; 241 yn[i].end_tick = end_tick;
242 yn[i].tmo_default_res = tmo_default_res; 242 yn[i].tmo_default_res = tmo_default_res;
243
244 yn[i].main_message=main_message; 243 yn[i].main_message=main_message;
245 yn[i].result_message[YESNO_YES]=yes_message;
246 yn[i].result_message[YESNO_NO]=no_message;
247 yn[i].display=&screens[i]; 244 yn[i].display=&screens[i];
248 yn[i].vp = &vp[i];
249 viewportmanager_theme_enable(i, true, yn[i].vp);
250 screens[i].scroll_stop(); 245 screens[i].scroll_stop();
251 gui_yesno_draw(&(yn[i])); 246 viewportmanager_theme_enable(i, true, &(yn[i].vp));
247 yn[i].vp_lines = viewport_get_nb_lines(&(yn[i].vp));
252 } 248 }
253 249
254#ifdef HAVE_TOUCHSCREEN 250#ifdef HAVE_TOUCHSCREEN
@@ -263,33 +259,36 @@ enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res
263 259
264 /* hook into UI update events to avoid the dialog disappearing 260 /* hook into UI update events to avoid the dialog disappearing
265 * in case the skin decides to do a full refresh */ 261 * in case the skin decides to do a full refresh */
266 add_event_ex(GUI_EVENT_NEED_UI_UPDATE, false, gui_yesno_ui_update, &yn[0]); 262 /*add_event_ex(GUI_EVENT_NEED_UI_UPDATE, false, gui_yesno_ui_update, &yn[0]);*/
263 /* probably no longer needed --Bilgus 2023*/
267 264
268 while (result==-1) 265 while (result==YESNO_NONE)
269 { 266 {
267
268 FOR_NB_SCREENS(i)
269 gui_yesno_draw(&yn[i]);
270
270 /* Repeat the question every 5secs (more or less) */ 271 /* Repeat the question every 5secs (more or less) */
271 if (global_settings.talk_menu 272 if (talk_menu && TIME_AFTER(current_tick, talked_tick))
272 && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5)))
273 { 273 {
274 talked_tick = current_tick; 274 talked_tick = current_tick + (HZ*5);
275 talk_text_message(main_message, false); 275 talk_text_message(main_message, false);
276 } 276 }
277 FOR_NB_SCREENS(i) 277 backlight_on = is_backlight_on(false);
278 gui_yesno_draw(&yn[i]); 278 action = get_action(CONTEXT_YESNOSCREEN, HZ / 2); /* for statubar and tmo */
279 279 switch (action)
280 button = get_action(CONTEXT_YESNOSCREEN, button_scan_tmo);
281
282 switch (button)
283 { 280 {
284#ifdef HAVE_TOUCHSCREEN 281#ifdef HAVE_TOUCHSCREEN
285 case ACTION_TOUCHSCREEN: 282 case ACTION_TOUCHSCREEN:
286 { 283 {
284 int btn;
287 short int x, y; 285 short int x, y;
288 if (action_get_touchscreen_press_in_vp(&x, &y, yn[0].vp) == BUTTON_REL) 286 btn = action_get_touchscreen_press_in_vp(&x, &y, &(yn[0].vp))
287 if (btn == BUTTON_REL)
289 { 288 {
290 if (y > yn[0].vp->height/2) 289 if (y > yn[0].vp.height/2)
291 { 290 {
292 if (x <= yn[0].vp->width/2) 291 if (x <= yn[0].vp.width/2)
293 result = YESNO_YES; 292 result = YESNO_YES;
294 else 293 else
295 result = YESNO_NO; 294 result = YESNO_NO;
@@ -299,55 +298,62 @@ enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res
299 break; 298 break;
300#endif 299#endif
301 case ACTION_YESNO_ACCEPT: 300 case ACTION_YESNO_ACCEPT:
302 result=YESNO_YES; 301 result = YESNO_YES;
303 break; 302 break;
304 case ACTION_NONE: 303 case ACTION_NONE:
305 if(tmo_default_res != YESNO_TMO && TIME_AFTER(current_tick, end_tick)) 304 if(tmo_default_res != YESNO_TMO && TIME_AFTER(current_tick, end_tick))
306 { 305 {
307 splash(HZ/2, ID2P(LANG_TIMEOUT)); 306 splash(HZ/2, ID2P(LANG_TIMEOUT));
308 result = tmo_default_res; 307 result = tmo_default_res;
309 break; 308 goto exit;
310 } 309 }
311 /*fall-through*/ 310 /*fall-through*/
312 case ACTION_UNKNOWN: 311 case ACTION_UNKNOWN:
313 case SYS_CHARGER_DISCONNECTED: 312 case ACTION_REDRAW:
314 case SYS_BATTERY_UPDATE:
315 case SYS_TIMEOUT:
316#if CONFIG_CHARGING
317 case SYS_CHARGER_CONNECTED:
318#endif
319 /* ignore some SYS events that can happen */
320 continue; 313 continue;
321 default: 314 default:
322 if(default_event_handler(button) == SYS_USB_CONNECTED) { 315 if(default_event_handler(action) == SYS_USB_CONNECTED) {
323 result = YESNO_USB; 316 result = YESNO_USB;
324 goto exit; 317 goto exit;
325 } 318 }
326 319 if (!IS_SYSEVENT(action)) /* ignore SYS events that can happen */
327 result = YESNO_NO; 320 result = YESNO_NO;
328 } 321 }
322
323 if (!backlight_on)
324 result = YESNO_NONE; /* don't allow results if the screen is off */
329 } 325 }
330 326
331 FOR_NB_SCREENS(i) 327exit:
332 result_displayed=gui_yesno_draw_result(&(yn[i]), result);
333 328
334 if (global_settings.talk_menu) 329 /*remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]);*/
330
331 if (result == YESNO_YES || result == YESNO_NO)
335 { 332 {
336 talk_text_message((result == YESNO_YES) ? yes_message 333 const struct text_message * resmsg;
337 : no_message, false); 334 if (result == YESNO_YES)
338 talk_force_enqueue_next(); 335 resmsg = yes_message;
339 } 336 else
337 resmsg = no_message;
340 338
339 if (resmsg != NULL)
340 {
341 FOR_NB_SCREENS(i)
342 gui_yesno_draw_result(&(yn[i]), resmsg);
341 343
342 exit: 344 if (talk_menu)
343 remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]); 345 {
346 talk_text_message(resmsg, false);
347 talk_force_enqueue_next();
348 }
344 349
345 if(result_displayed) 350 sleep(HZ);
346 sleep(HZ); 351 }
352 }
347 353
348 FOR_NB_SCREENS(i) 354 FOR_NB_SCREENS(i)
349 { 355 {
350 screens[i].scroll_stop_viewport(yn[i].vp); 356 screens[i].scroll_stop_viewport(&(yn[i].vp));
351 viewportmanager_theme_undo(i, true); 357 viewportmanager_theme_undo(i, true);
352 } 358 }
353 359
@@ -366,7 +372,7 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message,
366} 372}
367 373
368/* Function to manipulate all yesno dialogues. 374/* Function to manipulate all yesno dialogues.
369 This function needs the output text as an argument. */ 375 This function needs the prompt text as an argument. */
370bool yesno_pop(const char* text) 376bool yesno_pop(const char* text)
371{ 377{
372 const char *lines[]={text}; 378 const char *lines[]={text};