Lock screen when drawing on the calendar/notification panel

Lock the screen if either the calendar panel or the notification bar is
updated to avoid race conditions.

Addresses BUG#6.

Note that we currently always use a screen-level lock, even if only one
window is affected. This is to be changed in the future.

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
Lukas Fleischer 2012-11-23 09:59:06 +01:00
parent e16ac0a8a8
commit a80f8dcf2c
4 changed files with 61 additions and 3 deletions

View File

@ -975,6 +975,10 @@ void vars_init(void);
/* wins.c */ /* wins.c */
extern struct window win[NBWINS]; extern struct window win[NBWINS];
unsigned wins_nbar_lock(void);
void wins_nbar_unlock(void);
unsigned wins_calendar_lock(void);
void wins_calendar_unlock(void);
int wins_refresh(void); int wins_refresh(void);
int wins_wrefresh(WINDOW *); int wins_wrefresh(WINDOW *);
int wins_doupdate(void); int wins_doupdate(void);

View File

@ -297,6 +297,7 @@ draw_monthly_view(struct window *cwin, struct date *current_day,
c_day_1 = (int)((ymd_to_scalar(yr, mo, 1 + sunday_first) - (long)1) % 7L); c_day_1 = (int)((ymd_to_scalar(yr, mo, 1 + sunday_first) - (long)1) % 7L);
/* Write the current month and year on top of the calendar */ /* Write the current month and year on top of the calendar */
wins_calendar_lock();
custom_apply_attr(cwin->p, ATTR_HIGHEST); custom_apply_attr(cwin->p, ATTR_HIGHEST);
mvwprintw(cwin->p, ofs_y, mvwprintw(cwin->p, ofs_y,
(SBAR_WIDTH - (strlen(_(monthnames[mo - 1])) + 5)) / 2, (SBAR_WIDTH - (strlen(_(monthnames[mo - 1])) + 5)) / 2,
@ -310,6 +311,7 @@ draw_monthly_view(struct window *cwin, struct date *current_day,
mvwaddstr(cwin->p, ofs_y, ofs_x + 4 * j, _(daynames[1 + j - sunday_first])); mvwaddstr(cwin->p, ofs_y, ofs_x + 4 * j, _(daynames[1 + j - sunday_first]));
} }
custom_remove_attr(cwin->p, ATTR_HIGHEST); custom_remove_attr(cwin->p, ATTR_HIGHEST);
wins_calendar_unlock();
day_1_sav = (c_day_1 + 1) * 3 + c_day_1 - 7; day_1_sav = (c_day_1 + 1) * 3 + c_day_1 - 7;
@ -327,11 +329,12 @@ draw_monthly_view(struct window *cwin, struct date *current_day,
ofs_x = OFFX - day_1_sav - 4 * c_day; ofs_x = OFFX - day_1_sav - 4 * c_day;
} }
/* This is today, so print it in yellow. */ wins_calendar_lock();
if (c_day == current_day->dd if (c_day == current_day->dd
&& current_day->mm == slctd_day.mm && current_day->mm == slctd_day.mm
&& current_day->yyyy == slctd_day.yyyy && current_day->yyyy == slctd_day.yyyy
&& current_day->dd != slctd_day.dd) { && current_day->dd != slctd_day.dd) {
/* This is today, so print it in yellow. */
custom_apply_attr(cwin->p, ATTR_LOWEST); custom_apply_attr(cwin->p, ATTR_LOWEST);
mvwprintw(cwin->p, ofs_y + 1, mvwprintw(cwin->p, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day);
@ -347,10 +350,12 @@ draw_monthly_view(struct window *cwin, struct date *current_day,
mvwprintw(cwin->p, ofs_y + 1, mvwprintw(cwin->p, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day);
custom_remove_attr(cwin->p, ATTR_LOW); custom_remove_attr(cwin->p, ATTR_LOW);
} else } else {
/* otherwise, print normal days in black */ /* otherwise, print normal days in black */
mvwprintw(cwin->p, ofs_y + 1, mvwprintw(cwin->p, ofs_y + 1,
ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day);
}
wins_calendar_unlock();
} }
} }
@ -454,9 +459,11 @@ draw_weekly_view(struct window *cwin, struct date *current_day,
/* Print the week number. */ /* Print the week number. */
weeknum = ISO8601weeknum(&t); weeknum = ISO8601weeknum(&t);
wins_calendar_lock();
custom_apply_attr(cwin->p, ATTR_HIGHEST); custom_apply_attr(cwin->p, ATTR_HIGHEST);
mvwprintw(cwin->p, 2, cwin->w - 9, "(# %02d)", weeknum); mvwprintw(cwin->p, 2, cwin->w - 9, "(# %02d)", weeknum);
custom_remove_attr(cwin->p, ATTR_HIGHEST); custom_remove_attr(cwin->p, ATTR_HIGHEST);
wins_calendar_unlock();
/* Now draw calendar view. */ /* Now draw calendar view. */
for (j = 0; j < WEEKINDAYS; j++) { for (j = 0; j < WEEKINDAYS; j++) {
@ -488,22 +495,28 @@ draw_weekly_view(struct window *cwin, struct date *current_day,
else else
attr = 0; attr = 0;
wins_calendar_lock();
if (attr) if (attr)
custom_apply_attr(cwin->p, attr); custom_apply_attr(cwin->p, attr);
mvwprintw(cwin->p, OFFY + 1, OFFX + 1 + 4 * j, "%02d", t.tm_mday); mvwprintw(cwin->p, OFFY + 1, OFFX + 1 + 4 * j, "%02d", t.tm_mday);
if (attr) if (attr)
custom_remove_attr(cwin->p, attr); custom_remove_attr(cwin->p, attr);
wins_calendar_unlock();
/* Draw slices indicating appointment times. */ /* Draw slices indicating appointment times. */
memset(slices, 0, DAYSLICESNO * sizeof *slices); memset(slices, 0, DAYSLICESNO * sizeof *slices);
if (day_chk_busy_slices(date, DAYSLICESNO, slices)) { if (day_chk_busy_slices(date, DAYSLICESNO, slices)) {
for (i = 0; i < DAYSLICESNO; i++) { for (i = 0; i < DAYSLICESNO; i++) {
if (j != WEEKINDAYS - 1 && i != DAYSLICESNO - 1) if (j != WEEKINDAYS - 1 && i != DAYSLICESNO - 1) {
wins_calendar_lock();
mvwhline(cwin->p, OFFY + 2 + i, OFFX + 3 + 4 * j, ACS_S9, 2); mvwhline(cwin->p, OFFY + 2 + i, OFFX + 3 + 4 * j, ACS_S9, 2);
wins_calendar_unlock();
}
if (slices[i]) { if (slices[i]) {
int highlight; int highlight;
highlight = (t.tm_mday == slctd_day.dd) ? 1 : 0; highlight = (t.tm_mday == slctd_day.dd) ? 1 : 0;
wins_calendar_lock();
if (highlight) if (highlight)
custom_apply_attr(cwin->p, attr); custom_apply_attr(cwin->p, attr);
wattron(cwin->p, A_REVERSE); wattron(cwin->p, A_REVERSE);
@ -512,6 +525,7 @@ draw_weekly_view(struct window *cwin, struct date *current_day,
wattroff(cwin->p, A_REVERSE); wattroff(cwin->p, A_REVERSE);
if (highlight) if (highlight)
custom_remove_attr(cwin->p, attr); custom_remove_attr(cwin->p, attr);
wins_calendar_unlock();
} }
} }
} }
@ -521,11 +535,13 @@ draw_weekly_view(struct window *cwin, struct date *current_day,
} }
/* Draw marks to indicate midday on the sides of the calendar. */ /* Draw marks to indicate midday on the sides of the calendar. */
wins_calendar_lock();
custom_apply_attr(cwin->p, ATTR_HIGHEST); custom_apply_attr(cwin->p, ATTR_HIGHEST);
mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2, OFFX, ACS_S9, 1); mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2, OFFX, ACS_S9, 1);
mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2, mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2,
OFFX + WCALWIDTH - 3, ACS_S9, 1); OFFX + WCALWIDTH - 3, ACS_S9, 1);
custom_remove_attr(cwin->p, ATTR_HIGHEST); custom_remove_attr(cwin->p, ATTR_HIGHEST);
wins_calendar_unlock();
#undef DAYSLICESNO #undef DAYSLICESNO
} }
@ -537,8 +553,12 @@ void calendar_update_panel(struct window *cwin)
unsigned sunday_first; unsigned sunday_first;
calendar_store_current_date(&current_day); calendar_store_current_date(&current_day);
wins_calendar_lock();
erase_window_part(cwin->p, 1, 3, cwin->w - 2, cwin->h - 2); erase_window_part(cwin->p, 1, 3, cwin->w - 2, cwin->h - 2);
mvwhline(cwin->p, 2, 1, ACS_HLINE, cwin->w - 2); mvwhline(cwin->p, 2, 1, ACS_HLINE, cwin->w - 2);
wins_calendar_unlock();
sunday_first = calendar_week_begins_on_monday()? 0 : 1; sunday_first = calendar_week_begins_on_monday()? 0 : 1;
draw_calendar[calendar_view] (cwin, &current_day, sunday_first); draw_calendar[calendar_view] (cwin, &current_day, sunday_first);

View File

@ -240,11 +240,13 @@ void notify_update_bar(void)
app_pos = file_pos + strlen(notify.apts_file) + 2 + space; app_pos = file_pos + strlen(notify.apts_file) + 2 + space;
txt_max_len = col - (app_pos + 12 + space); txt_max_len = col - (app_pos + 12 + space);
wins_nbar_lock();
custom_apply_attr(notify.win, ATTR_HIGHEST); custom_apply_attr(notify.win, ATTR_HIGHEST);
wattron(notify.win, A_UNDERLINE | A_REVERSE); wattron(notify.win, A_UNDERLINE | A_REVERSE);
mvwhline(notify.win, 0, 0, ACS_HLINE, col); mvwhline(notify.win, 0, 0, ACS_HLINE, col);
mvwprintw(notify.win, 0, date_pos, "[ %s | %s ]", notify.date, notify.time); mvwprintw(notify.win, 0, date_pos, "[ %s | %s ]", notify.date, notify.time);
mvwprintw(notify.win, 0, file_pos, "(%s)", notify.apts_file); mvwprintw(notify.win, 0, file_pos, "(%s)", notify.apts_file);
wins_nbar_unlock();
pthread_mutex_lock(&notify_app.mutex); pthread_mutex_lock(&notify_app.mutex);
if (notify_app.got_app) { if (notify_app.got_app) {
@ -271,6 +273,7 @@ void notify_update_bar(void)
else else
blinking = 0; blinking = 0;
wins_nbar_lock();
if (blinking) if (blinking)
wattron(notify.win, A_BLINK); wattron(notify.win, A_BLINK);
if (too_long) if (too_long)
@ -281,6 +284,7 @@ void notify_update_bar(void)
hours_left, minutes_left, notify_app.txt); hours_left, minutes_left, notify_app.txt);
if (blinking) if (blinking)
wattroff(notify.win, A_BLINK); wattroff(notify.win, A_BLINK);
wins_nbar_unlock();
if (blinking) if (blinking)
notify_launch_cmd(); notify_launch_cmd();
@ -295,8 +299,10 @@ void notify_update_bar(void)
} }
pthread_mutex_unlock(&notify_app.mutex); pthread_mutex_unlock(&notify_app.mutex);
wins_nbar_lock();
wattroff(notify.win, A_UNDERLINE | A_REVERSE); wattroff(notify.win, A_UNDERLINE | A_REVERSE);
custom_remove_attr(notify.win, ATTR_HIGHEST); custom_remove_attr(notify.win, ATTR_HIGHEST);
wins_nbar_unlock();
wins_wrefresh(notify.win); wins_wrefresh(notify.win);
pthread_mutex_unlock(&notify.mutex); pthread_mutex_unlock(&notify.mutex);

View File

@ -76,6 +76,32 @@ static void screen_release(void)
pthread_mutex_unlock(&screen_mutex); pthread_mutex_unlock(&screen_mutex);
} }
/*
* FIXME: The following functions currently lock the whole screen. Use both
* window-level and screen-level mutexes (or use use_screen() and use_window(),
* see curs_threads(3)) to avoid locking too much.
*/
unsigned wins_nbar_lock(void)
{
return screen_acquire();
}
void wins_nbar_unlock(void)
{
screen_release();
}
unsigned wins_calendar_lock(void)
{
return screen_acquire();
}
void wins_calendar_unlock(void)
{
screen_release();
}
int wins_refresh(void) int wins_refresh(void)
{ {
int rc; int rc;
@ -476,10 +502,12 @@ static void border_nocolor(WINDOW * window)
void wins_update_border(int flags) void wins_update_border(int flags)
{ {
if (flags & FLAG_CAL) { if (flags & FLAG_CAL) {
wins_calendar_lock();
if (slctd_win == CAL) if (slctd_win == CAL)
border_color(win[CAL].p); border_color(win[CAL].p);
else else
border_nocolor(win[CAL].p); border_nocolor(win[CAL].p);
wins_calendar_unlock();
} }
if (flags & FLAG_APP) { if (flags & FLAG_APP) {
if (slctd_win == APP) if (slctd_win == APP)