From a80f8dcf2c6eb3b54658218bc081ee9694204dd5 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Fri, 23 Nov 2012 09:59:06 +0100 Subject: 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 --- src/calcurse.h | 4 ++++ src/calendar.c | 26 +++++++++++++++++++++++--- src/notify.c | 6 ++++++ src/wins.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/calcurse.h b/src/calcurse.h index e35fe9a..7a7f4f2 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -975,6 +975,10 @@ void vars_init(void); /* wins.c */ 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_wrefresh(WINDOW *); int wins_doupdate(void); diff --git a/src/calendar.c b/src/calendar.c index 48ac84d..42ee449 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -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); /* Write the current month and year on top of the calendar */ + wins_calendar_lock(); custom_apply_attr(cwin->p, ATTR_HIGHEST); mvwprintw(cwin->p, ofs_y, (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])); } custom_remove_attr(cwin->p, ATTR_HIGHEST); + wins_calendar_unlock(); 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; } - /* This is today, so print it in yellow. */ + wins_calendar_lock(); if (c_day == current_day->dd && current_day->mm == slctd_day.mm && current_day->yyyy == slctd_day.yyyy && current_day->dd != slctd_day.dd) { + /* This is today, so print it in yellow. */ custom_apply_attr(cwin->p, ATTR_LOWEST); mvwprintw(cwin->p, ofs_y + 1, 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, ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); custom_remove_attr(cwin->p, ATTR_LOW); - } else + } else { /* otherwise, print normal days in black */ mvwprintw(cwin->p, ofs_y + 1, 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. */ weeknum = ISO8601weeknum(&t); + wins_calendar_lock(); custom_apply_attr(cwin->p, ATTR_HIGHEST); mvwprintw(cwin->p, 2, cwin->w - 9, "(# %02d)", weeknum); custom_remove_attr(cwin->p, ATTR_HIGHEST); + wins_calendar_unlock(); /* Now draw calendar view. */ for (j = 0; j < WEEKINDAYS; j++) { @@ -488,22 +495,28 @@ draw_weekly_view(struct window *cwin, struct date *current_day, else attr = 0; + wins_calendar_lock(); if (attr) custom_apply_attr(cwin->p, attr); mvwprintw(cwin->p, OFFY + 1, OFFX + 1 + 4 * j, "%02d", t.tm_mday); if (attr) custom_remove_attr(cwin->p, attr); + wins_calendar_unlock(); /* Draw slices indicating appointment times. */ memset(slices, 0, DAYSLICESNO * sizeof *slices); if (day_chk_busy_slices(date, DAYSLICESNO, slices)) { 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); + wins_calendar_unlock(); + } if (slices[i]) { int highlight; highlight = (t.tm_mday == slctd_day.dd) ? 1 : 0; + wins_calendar_lock(); if (highlight) custom_apply_attr(cwin->p, attr); wattron(cwin->p, A_REVERSE); @@ -512,6 +525,7 @@ draw_weekly_view(struct window *cwin, struct date *current_day, wattroff(cwin->p, A_REVERSE); if (highlight) 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. */ + wins_calendar_lock(); 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 + WCALWIDTH - 3, ACS_S9, 1); custom_remove_attr(cwin->p, ATTR_HIGHEST); + wins_calendar_unlock(); #undef DAYSLICESNO } @@ -537,8 +553,12 @@ void calendar_update_panel(struct window *cwin) unsigned sunday_first; calendar_store_current_date(¤t_day); + + wins_calendar_lock(); erase_window_part(cwin->p, 1, 3, cwin->w - 2, cwin->h - 2); mvwhline(cwin->p, 2, 1, ACS_HLINE, cwin->w - 2); + wins_calendar_unlock(); + sunday_first = calendar_week_begins_on_monday()? 0 : 1; draw_calendar[calendar_view] (cwin, ¤t_day, sunday_first); diff --git a/src/notify.c b/src/notify.c index 10bc0f7..6ac94b9 100644 --- a/src/notify.c +++ b/src/notify.c @@ -240,11 +240,13 @@ void notify_update_bar(void) app_pos = file_pos + strlen(notify.apts_file) + 2 + space; txt_max_len = col - (app_pos + 12 + space); + wins_nbar_lock(); custom_apply_attr(notify.win, ATTR_HIGHEST); wattron(notify.win, A_UNDERLINE | A_REVERSE); mvwhline(notify.win, 0, 0, ACS_HLINE, col); mvwprintw(notify.win, 0, date_pos, "[ %s | %s ]", notify.date, notify.time); mvwprintw(notify.win, 0, file_pos, "(%s)", notify.apts_file); + wins_nbar_unlock(); pthread_mutex_lock(¬ify_app.mutex); if (notify_app.got_app) { @@ -271,6 +273,7 @@ void notify_update_bar(void) else blinking = 0; + wins_nbar_lock(); if (blinking) wattron(notify.win, A_BLINK); if (too_long) @@ -281,6 +284,7 @@ void notify_update_bar(void) hours_left, minutes_left, notify_app.txt); if (blinking) wattroff(notify.win, A_BLINK); + wins_nbar_unlock(); if (blinking) notify_launch_cmd(); @@ -295,8 +299,10 @@ void notify_update_bar(void) } pthread_mutex_unlock(¬ify_app.mutex); + wins_nbar_lock(); wattroff(notify.win, A_UNDERLINE | A_REVERSE); custom_remove_attr(notify.win, ATTR_HIGHEST); + wins_nbar_unlock(); wins_wrefresh(notify.win); pthread_mutex_unlock(¬ify.mutex); diff --git a/src/wins.c b/src/wins.c index d518377..64dd962 100644 --- a/src/wins.c +++ b/src/wins.c @@ -76,6 +76,32 @@ static void screen_release(void) 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 rc; @@ -476,10 +502,12 @@ static void border_nocolor(WINDOW * window) void wins_update_border(int flags) { if (flags & FLAG_CAL) { + wins_calendar_lock(); if (slctd_win == CAL) border_color(win[CAL].p); else border_nocolor(win[CAL].p); + wins_calendar_unlock(); } if (flags & FLAG_APP) { if (slctd_win == APP) -- cgit v1.2.3-54-g00ecf