Add hidden key handler window
After BUG#6 had apparently been closed with the screen locks introduced in commit a80f8dcf2c6eb3b54658218bc081ee9694204dd5, some people still had problems with random characters appearing in the notification bar. This was obviously caused by wgetch() refreshing the screen if the status panel was changed. From wgetch(3): If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read. Since the wgetch(3) isn't thread-safe, there were race conditions between the notification bar thread drawing to the notification bar and wgetch() updating the screen. Introduce a (hidden) window that handles all key presses and never gets changed in order to avoid this. Also, call wins_wrefresh() explicitly in status_mesg(), since we can no longer rely on wgetch() updating windows automatically. Fixes reopened BUG#6. Note that this is a hotfix -- FR#26 has been opened to ensure we fix this properly in the next major release. Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
parent
aa7844942e
commit
e492ac6f95
@ -565,6 +565,11 @@ int main(int argc, char **argv)
|
||||
io_load_todo();
|
||||
io_load_app();
|
||||
wins_reinit();
|
||||
/*
|
||||
* Refresh the hidden key handler window here to prevent wgetch() from
|
||||
* implicitly calling wrefresh() later (causing ncurses race conditions).
|
||||
*/
|
||||
wins_wrefresh(win[KEY].p);
|
||||
if (conf.system_dialogs) {
|
||||
wins_update(FLAG_ALL);
|
||||
io_startup_screen(no_data_file);
|
||||
@ -589,7 +594,7 @@ int main(int argc, char **argv)
|
||||
wins_reset();
|
||||
}
|
||||
|
||||
key = keys_getch(win[STA].p, &count, ®);
|
||||
key = keys_getch(win[KEY].p, &count, ®);
|
||||
switch (key) {
|
||||
case KEY_GENERIC_REDRAW:
|
||||
resize = 1;
|
||||
|
@ -239,6 +239,7 @@ enum win {
|
||||
TOD,
|
||||
NOT,
|
||||
STA,
|
||||
KEY,
|
||||
NBWINS
|
||||
};
|
||||
|
||||
|
@ -641,7 +641,7 @@ void calendar_change_day(int datefmt)
|
||||
}
|
||||
if (wrong_day) {
|
||||
status_mesg(mesg_line1, mesg_line2);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
src/custom.c
14
src/custom.c
@ -226,7 +226,7 @@ void custom_layout_config(void)
|
||||
display_layout_config(&conf_win, mark, cursor);
|
||||
clear();
|
||||
|
||||
while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
while ((ch = keys_getch(win[KEY].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
need_reset = 0;
|
||||
switch (ch) {
|
||||
case KEY_GENERIC_HELP:
|
||||
@ -310,7 +310,7 @@ void custom_sidebar_config(void)
|
||||
bindings_size, NULL);
|
||||
wins_doupdate();
|
||||
|
||||
while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
while ((ch = keys_getch(win[KEY].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
switch (ch) {
|
||||
case KEY_MOVE_UP:
|
||||
wins_sbar_winc();
|
||||
@ -528,7 +528,7 @@ void custom_color_config(void)
|
||||
theme_changed);
|
||||
clear();
|
||||
|
||||
while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
while ((ch = keys_getch(win[KEY].p, NULL, NULL)) != KEY_GENERIC_QUIT) {
|
||||
need_reset = 0;
|
||||
theme_changed = 0;
|
||||
|
||||
@ -732,7 +732,7 @@ void custom_general_config(void)
|
||||
wins_scrollwin_display(&cwin);
|
||||
|
||||
buf = mem_malloc(BUFSIZ);
|
||||
while ((ch = wgetch(win[STA].p)) != 'q') {
|
||||
while ((ch = wgetch(win[KEY].p)) != 'q') {
|
||||
buf[0] = '\0';
|
||||
|
||||
switch (ch) {
|
||||
@ -921,7 +921,7 @@ void custom_keys_config(void)
|
||||
for (;;) {
|
||||
int ch;
|
||||
|
||||
ch = keys_getch(win[STA].p, NULL, NULL);
|
||||
ch = keys_getch(win[KEY].p, NULL, NULL);
|
||||
switch (ch) {
|
||||
case KEY_MOVE_UP:
|
||||
if (selrow > 0) {
|
||||
@ -1032,7 +1032,7 @@ void custom_config_main(void)
|
||||
int old_layout;
|
||||
|
||||
custom_config_bar();
|
||||
while ((ch = wgetch(win[STA].p)) != 'q') {
|
||||
while ((ch = wgetch(win[KEY].p)) != 'q') {
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
@ -1042,7 +1042,7 @@ void custom_config_main(void)
|
||||
colorize = 0;
|
||||
wins_erase_status_bar();
|
||||
mvwaddstr(win[STA].p, 0, 0, no_color_support);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
|
@ -793,7 +793,7 @@ void help_screen(void)
|
||||
}
|
||||
|
||||
wins_scrollwin_display(&hwin);
|
||||
ch = keys_getch(win[STA].p, NULL, NULL);
|
||||
ch = keys_getch(win[KEY].p, NULL, NULL);
|
||||
}
|
||||
wins_scrollwin_delete(&hwin);
|
||||
if (need_resize)
|
||||
|
@ -54,7 +54,7 @@ static int day_edit_time(int time, unsigned *new_hour, unsigned *new_minute)
|
||||
return 1;
|
||||
} else {
|
||||
status_mesg(fmt_msg, enter_str);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
@ -86,7 +86,7 @@ static int day_edit_duration(int start, int dur, unsigned *new_duration)
|
||||
break;
|
||||
} else {
|
||||
status_mesg(fmt_msg, enter_str);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
@ -115,7 +115,7 @@ static void update_start_time(long *start, long *dur)
|
||||
valid_date = 1;
|
||||
} else {
|
||||
status_mesg(msg_wrong_time, msg_enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
valid_date = 0;
|
||||
}
|
||||
}
|
||||
@ -212,7 +212,7 @@ static void update_rept(struct rpt **rpt, const long start)
|
||||
mem_free(freqstr);
|
||||
if (newfreq == 0) {
|
||||
status_mesg(msg_wrong_freq, msg_enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
} else {
|
||||
mem_free(freqstr);
|
||||
@ -249,14 +249,14 @@ static void update_rept(struct rpt **rpt, const long start)
|
||||
newuntil = date2sec(new_date, lt.tm_hour, lt.tm_min);
|
||||
if (newuntil < start) {
|
||||
status_mesg(msg_wrong_time, msg_enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
date_entered = 0;
|
||||
} else
|
||||
date_entered = 1;
|
||||
} else {
|
||||
snprintf(outstr, BUFSIZ, msg_fmts, DATEFMT_DESC(conf.input_datefmt));
|
||||
status_mesg(msg_wrong_date, outstr);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
date_entered = 0;
|
||||
}
|
||||
}
|
||||
@ -447,7 +447,7 @@ void interact_day_item_add(void)
|
||||
break;
|
||||
else {
|
||||
status_mesg(format_message_1, enter_str);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
} else
|
||||
return;
|
||||
@ -477,7 +477,7 @@ void interact_day_item_add(void)
|
||||
break;
|
||||
} else {
|
||||
status_mesg(format_message_2, enter_str);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
} else
|
||||
return;
|
||||
@ -606,7 +606,7 @@ void interact_todo_add(void)
|
||||
if (getstring(win[STA].p, todo_input, BUFSIZ, 0, 1) == GETSTRING_VALID) {
|
||||
while ((ch < '1') || (ch > '9')) {
|
||||
status_mesg(mesg_id, "");
|
||||
ch = wgetch(win[STA].p);
|
||||
ch = wgetch(win[KEY].p);
|
||||
}
|
||||
todo_add(todo_input, ch - '0', NULL);
|
||||
todo_set_nb(todo_nb() + 1);
|
||||
@ -744,7 +744,7 @@ void interact_day_item_repeat(void)
|
||||
p = day_get_item(item_nb);
|
||||
if (p->type != APPT && p->type != EVNT) {
|
||||
status_mesg(wrong_type_1, wrong_type_2);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -771,7 +771,7 @@ void interact_day_item_repeat(void)
|
||||
freq = atoi(user_input);
|
||||
if (freq == 0) {
|
||||
status_mesg(mesg_wrong_freq, wrong_type_2);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
user_input[0] = '\0';
|
||||
} else
|
||||
@ -796,7 +796,7 @@ void interact_day_item_repeat(void)
|
||||
until = date2sec(until_date, lt.tm_hour, lt.tm_min);
|
||||
if (until < p->start) {
|
||||
status_mesg(mesg_older, wrong_type_2);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
date_entered = 0;
|
||||
} else {
|
||||
date_entered = 1;
|
||||
@ -805,7 +805,7 @@ void interact_day_item_repeat(void)
|
||||
snprintf(outstr, BUFSIZ, mesg_wrong_2,
|
||||
DATEFMT_DESC(conf.input_datefmt));
|
||||
status_mesg(mesg_wrong_1, outstr);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
date_entered = 0;
|
||||
}
|
||||
}
|
||||
|
12
src/io.c
12
src/io.c
@ -175,7 +175,7 @@ static FILE *get_export_stream(enum export_type type)
|
||||
stream = fopen(stream_name, "w");
|
||||
if (stream == NULL) {
|
||||
status_mesg(wrong_name, press_enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
}
|
||||
mem_free(stream_name);
|
||||
@ -421,7 +421,7 @@ void io_save_cal(enum save_display display)
|
||||
/* Print a message telling data were saved */
|
||||
if (ui_mode == UI_CURSES && conf.system_dialogs) {
|
||||
status_mesg(save_success, enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&io_save_mutex);
|
||||
@ -893,7 +893,7 @@ void io_startup_screen(int no_data_file)
|
||||
status_mesg(_("Welcome to Calcurse. Missing data files were created."),
|
||||
enter);
|
||||
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
|
||||
/* Export calcurse data. */
|
||||
@ -928,7 +928,7 @@ void io_export_data(enum export_type type)
|
||||
|
||||
if (conf.system_dialogs && ui_mode == UI_CURSES) {
|
||||
status_mesg(success, enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -952,7 +952,7 @@ static FILE *get_import_stream(enum import_type type)
|
||||
stream = fopen(stream_name, "r");
|
||||
if (stream == NULL) {
|
||||
status_mesg(wrong_file, press_enter);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
}
|
||||
}
|
||||
mem_free(stream_name);
|
||||
@ -1030,7 +1030,7 @@ void io_import_data(enum import_type type, const char *stream_name)
|
||||
stats_str[1], stats_str[2], stats_str[3],
|
||||
_("Press [ENTER] to continue"));
|
||||
status_mesg(read, stat);
|
||||
wgetch(win[STA].p);
|
||||
wgetch(win[KEY].p);
|
||||
} else if (ui_mode == UI_CMDLINE) {
|
||||
printf(proc_report, stats.lines);
|
||||
printf("\n%s / %s / %s / %s\n", stats_str[0], stats_str[1],
|
||||
|
@ -676,7 +676,7 @@ void notify_config_bar(void)
|
||||
wins_scrollwin_display(&cwin);
|
||||
|
||||
buf = mem_malloc(BUFSIZ);
|
||||
while ((ch = wgetch(win[STA].p)) != 'q') {
|
||||
while ((ch = wgetch(win[KEY].p)) != 'q') {
|
||||
buf[0] = '\0';
|
||||
|
||||
switch (ch) {
|
||||
|
@ -174,6 +174,7 @@ void status_mesg(const char *msg1, const char *msg2)
|
||||
mvwaddstr(win[STA].p, 0, 0, msg1);
|
||||
mvwaddstr(win[STA].p, 1, 0, msg2);
|
||||
custom_remove_attr(win[STA].p, ATTR_HIGHEST);
|
||||
wins_wrefresh(win[STA].p);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -205,7 +206,7 @@ int status_ask_choice(const char *message, const char choice[], int nb_choice)
|
||||
status_mesg(message, avail_choice);
|
||||
|
||||
for (;;) {
|
||||
ch = wgetch(win[STA].p);
|
||||
ch = wgetch(win[KEY].p);
|
||||
for (i = 1; i <= nb_choice; i++)
|
||||
if (ch == choice[i])
|
||||
return i;
|
||||
|
@ -262,8 +262,10 @@ void wins_init(void)
|
||||
{
|
||||
wins_init_panels();
|
||||
win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x);
|
||||
win[KEY].p = newwin(1, 1, 1, 1);
|
||||
|
||||
keypad(win[STA].p, TRUE);
|
||||
keypad(win[KEY].p, TRUE);
|
||||
|
||||
/* Notify that the curses mode is now launched. */
|
||||
ui_mode = UI_CURSES;
|
||||
@ -345,6 +347,7 @@ void wins_reinit(void)
|
||||
delwin(apad.ptrwin);
|
||||
delwin(win[TOD].p);
|
||||
delwin(win[STA].p);
|
||||
delwin(win[KEY].p);
|
||||
wins_get_config();
|
||||
wins_init();
|
||||
if (notify_bar())
|
||||
|
Loading…
x
Reference in New Issue
Block a user