From 9e824a79eeae03dc4cdd43d2e2ecf2f252d37093 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Fri, 4 Aug 2017 11:05:38 +0200 Subject: [PATCH 01/11] Add functions to check fullscreen windows --- src/x11/screen.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/x11/screen.h | 20 ++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/x11/screen.c b/src/x11/screen.c index 070c1f1..6ce1580 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -186,6 +186,61 @@ void screen_update_fallback(void) screens[0].dim.h = DisplayHeight(xctx.dpy, screen); } +/* see screen.h */ +bool have_fullscreen_window(void) +{ + return window_is_fullscreen(get_focused_window()); +} + +/* see screen.h */ +bool window_is_fullscreen(Window window) +{ + bool fs = false; + + Atom has_wm_state = XInternAtom(xctx.dpy, "_NET_WM_STATE", True); + if (has_wm_state == None){ + return false; + } + + Atom actual_type_return; + int actual_format_return; + unsigned long bytes_after_return; + unsigned char *prop_to_return; + unsigned long n_items; + int result = XGetWindowProperty( + xctx.dpy, + window, + has_wm_state, + 0, /* long_offset */ + sizeof(window), /* long_length */ + false, /* delete */ + AnyPropertyType, /* req_type */ + &actual_type_return, + &actual_format_return, + &n_items, + &bytes_after_return, + &prop_to_return); + + if (result == Success) { + for(int i = 0; i < n_items; i++) { + char *atom = XGetAtomName(xctx.dpy, ((Atom*)prop_to_return)[i]); + + if (atom) { + if(0 == strcmp("_NET_WM_STATE_FULLSCREEN", atom)) + fs = true; + XFree(atom); + if(fs) + break; + } + } + } + + if (prop_to_return) + XFree(prop_to_return); + + return fs; +} + /* * Select the screen on which the Window * should be displayed. diff --git a/src/x11/screen.h b/src/x11/screen.h index ed71081..fcd020d 100644 --- a/src/x11/screen.h +++ b/src/x11/screen.h @@ -3,6 +3,7 @@ #define DUNST_SCREEN_H #include +#include #define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) @@ -27,5 +28,24 @@ void screen_check_event(XEvent event); screen_info *get_active_screen(void); double get_dpi_for_screen(screen_info *scr); +/** + * Find the currently focused window and check if it's in + * fullscreen mode + * + * @see window_is_fullscreen() + * @see get_focused_window() + * + * @return `true` if the focused window is in fullscreen mode + */ +bool have_fullscreen_window(void); + +/** + * Check if window is in fullscreen mode + * + * @param window the x11 window object + * @return `true` if `window` is in fullscreen mode + */ +bool window_is_fullscreen(Window window); + #endif /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ From bda8c1dbb2589e462303df12cc31db7238118c9a Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Mon, 14 Aug 2017 01:59:35 +0200 Subject: [PATCH 02/11] Add rule to show notification on fullscreen --- src/notification.c | 2 ++ src/notification.h | 7 +++++++ src/option_parser.c | 16 ++++++++++++++++ src/option_parser.h | 14 ++++++++++++++ src/rules.c | 3 +++ src/rules.h | 1 + src/settings.c | 9 +++++++++ 7 files changed, 52 insertions(+) diff --git a/src/notification.c b/src/notification.c index f689193..6418b09 100644 --- a/src/notification.c +++ b/src/notification.c @@ -284,6 +284,8 @@ notification *notification_create(void) n->transient = false; n->progress = -1; + n->fullscreen = FS_SHOW; + return n; } diff --git a/src/notification.h b/src/notification.h index 11632a9..0d619c1 100644 --- a/src/notification.h +++ b/src/notification.h @@ -9,6 +9,12 @@ #define DUNST_NOTIF_MAX_CHARS 5000 +enum behavior_fullscreen { + FS_NULL, //!< Invalid value + FS_DELAY, //!< Delay the notification until leaving fullscreen mode + FS_SHOW, //!< Show the message when in fullscreen mode +}; + /// Representing the urgencies according to the notification spec enum urgency { URG_NONE = -1, /**< Urgency not set (invalid) */ @@ -69,6 +75,7 @@ typedef struct _notification { bool first_render; /**< markup has been rendered before? */ int dup_count; /**< amount of duplicate notifications stacked onto this */ int displayed_height; + enum behavior_fullscreen fullscreen; //!< The instruction what to do with it, when desktop enters fullscreen /* derived fields */ char *msg; /**< formatted message */ diff --git a/src/option_parser.c b/src/option_parser.c index 6573d73..ca82813 100644 --- a/src/option_parser.c +++ b/src/option_parser.c @@ -551,4 +551,20 @@ const char *cmdline_create_usage(void) return usage_str; } +/* see option_parser.h */ +enum behavior_fullscreen parse_enum_fullscreen(const char *string, enum behavior_fullscreen def) +{ + if (!string) + return def; + + if (strcmp(string, "show") == 0) + return FS_SHOW; + else if (strcmp(string, "delay") == 0) + return FS_DELAY; + else { + LOG_W("Unknown fullscreen value: '%s'\n", string); + return def; + } +} + /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/option_parser.h b/src/option_parser.h index e816b7e..d712fa8 100644 --- a/src/option_parser.h +++ b/src/option_parser.h @@ -6,6 +6,8 @@ #include #include +#include "dunst.h" + int load_ini_file(FILE *); char *ini_get_path(const char *section, const char *key, const char *def); char *ini_get_string(const char *section, const char *key, const char *def); @@ -63,5 +65,17 @@ int option_get_bool(const char *ini_section, */ const char *next_section(const char *section); +/** + * Parse the fullscreen behavior value of the given string + * + * @param string the string representation of #behavior_fullscreen. + * The string must not contain any waste characters. + * @param def value to return in case of errors + * + * @return the #behavior_fullscreen representation of `string` + * @return `def` if `string` is invalid or `NULL` + */ +enum behavior_fullscreen parse_enum_fullscreen(const char *string, enum behavior_fullscreen def); + #endif /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/rules.c b/src/rules.c index 7be1abb..22e5bf3 100644 --- a/src/rules.c +++ b/src/rules.c @@ -16,6 +16,8 @@ void rule_apply(rule_t *r, notification *n) n->timeout = r->timeout; if (r->urgency != URG_NONE) n->urgency = r->urgency; + if (r->fullscreen != FS_NULL) + n->fullscreen = r->fullscreen; if (r->history_ignore != -1) n->history_ignore = r->history_ignore; if (r->set_transient != -1) @@ -69,6 +71,7 @@ void rule_init(rule_t *r) r->msg_urgency = URG_NONE; r->timeout = -1; r->urgency = URG_NONE; + r->fullscreen = FS_NULL; r->markup = MARKUP_NULL; r->new_icon = NULL; r->history_ignore = false; diff --git a/src/rules.h b/src/rules.h index b8d1d87..9bee0a9 100644 --- a/src/rules.h +++ b/src/rules.h @@ -30,6 +30,7 @@ typedef struct _rule_t { char *bg; const char *format; const char *script; + enum behavior_fullscreen fullscreen; } rule_t; extern GSList *rules; diff --git a/src/settings.c b/src/settings.c index c9264f5..75aead6 100644 --- a/src/settings.c +++ b/src/settings.c @@ -684,6 +684,15 @@ void load_settings(char *cmdline_config_path) r->history_ignore = ini_get_bool(cur_section, "history_ignore", r->history_ignore); r->match_transient = ini_get_bool(cur_section, "match_transient", r->match_transient); r->set_transient = ini_get_bool(cur_section, "set_transient", r->set_transient); + { + char *c = ini_get_string( + cur_section, + "fullscreen", NULL + ); + + r->fullscreen = parse_enum_fullscreen(c, r->fullscreen); + g_free(c); + } r->script = ini_get_path(cur_section, "script", NULL); } From f89ce8e16f8185a1a1695647c08977da7f5fd69c Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Mon, 14 Aug 2017 02:16:14 +0200 Subject: [PATCH 03/11] Delay incoming notifications when fullscreens set --- src/dunst.c | 6 ++++-- src/queues.c | 23 +++++++++++++++++------ src/queues.h | 9 +++++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/dunst.c b/src/dunst.c index 53fb2fc..6765af4 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -48,8 +48,10 @@ void wake_up(void) static gboolean run(void *data) { - queues_check_timeouts(x_is_idle()); - queues_update(); + bool fullscreen = have_fullscreen_window(); + + queues_check_timeouts(x_is_idle(), fullscreen); + queues_update(fullscreen); static gint64 next_timeout = 0; diff --git a/src/queues.c b/src/queues.c index 78f6c6a..09fed9c 100644 --- a/src/queues.c +++ b/src/queues.c @@ -284,12 +284,14 @@ void queues_history_push_all(void) } /* see queues.h */ -void queues_check_timeouts(bool idle) +void queues_check_timeouts(bool idle, bool fullscreen) { /* nothing to do */ if (displayed->length == 0) return; + bool is_idle = fullscreen ? false : idle; + GList *iter = g_queue_peek_head_link(displayed); while (iter) { notification *n = iter->data; @@ -302,7 +304,7 @@ void queues_check_timeouts(bool idle) iter = iter->next; /* don't timeout when user is idle */ - if (idle && !n->transient) { + if (is_idle && !n->transient) { n->start = g_get_monotonic_time(); continue; } @@ -320,7 +322,7 @@ void queues_check_timeouts(bool idle) } /* see queues.h */ -void queues_update(void) +void queues_update(bool fullscreen) { if (pause_displayed) { while (displayed->length > 0) { @@ -331,25 +333,34 @@ void queues_update(void) } /* move notifications from queue to displayed */ - while (waiting->length > 0) { + GList *iter = g_queue_peek_head_link(waiting); + while (iter) { + notification *n = iter->data; + GList *nextiter = iter->next; if (displayed_limit > 0 && displayed->length >= displayed_limit) { /* the list is full */ break; } - notification *n = g_queue_pop_head(waiting); - if (!n) return; + if (fullscreen && n->fullscreen == FS_DELAY) { + iter = nextiter; + continue; + } + n->start = g_get_monotonic_time(); if (!n->redisplayed && n->script) { notification_run_script(n); } + g_queue_delete_link(waiting, iter); g_queue_insert_sorted(displayed, n, notification_cmp_data, NULL); + + iter = nextiter; } } diff --git a/src/queues.h b/src/queues.h index 2fa9900..6bb10d7 100644 --- a/src/queues.h +++ b/src/queues.h @@ -125,8 +125,10 @@ void queues_history_push_all(void); * * @param idle the program's idle status. Important to calculate the * timeout for transient notifications + * @param fullscreen the desktop's fullscreen status. Important to + * calculate the timeout for transient notifications */ -void queues_check_timeouts(bool idle); +void queues_check_timeouts(bool idle, bool fullscreen); /** * Move inserted notifications from waiting queue to displayed queue @@ -135,8 +137,11 @@ void queues_check_timeouts(bool idle); * * @post Call wake_up() to synchronize the queues with the UI * (which closes old and shows new notifications on screen) + * + * @param fullscreen the desktop's fullscreen status. Important to + * move notifications to the right queue */ -void queues_update(void); +void queues_update(bool fullscreen); /** * Calculate the distance to the next event, when an element in the From bbe262853a90795a24431a371cd4a3ecb6b07271 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Mon, 20 Nov 2017 17:10:31 +0100 Subject: [PATCH 04/11] Add documentation for fullscreen rules --- CHANGELOG.md | 4 ++++ docs/dunst.pod | 5 +++-- dunstrc | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3602a69..3d74192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- `fullscreen` rule to hide notifications when a fullscreen window is active + ## 1.3.0 - 2018-01-05 ### Added diff --git a/docs/dunst.pod b/docs/dunst.pod index d2c7a0b..24636ab 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -594,8 +594,9 @@ Shell-like globing is supported. =item B The following attributes can be overridden: timeout, urgency, foreground, -background, new_icon, set_transient, format where, as with the filtering attributes, -each one corresponds to the respective notification attribute to be modified. +background, new_icon, set_transient, format, fullscreen where, +as with the filtering attributes, each one corresponds to the respective +notification attribute to be modified. As with filtering, to make a rule modify an attribute simply assign it in the rule definition. diff --git a/dunstrc b/dunstrc index 0f4c4aa..ed8e4c6 100644 --- a/dunstrc +++ b/dunstrc @@ -279,7 +279,7 @@ # override settings for certain messages. # Messages can be matched by "appname", "summary", "body", "icon", "category", # "msg_urgency" and you can override the "timeout", "urgency", "foreground", -# "background", "new_icon" and "format". +# "background", "new_icon" and "format", "fullscreen". # Shell-like globbing will get expanded. # # SCRIPTING @@ -294,6 +294,12 @@ # NOTE: It might be helpful to run dunst -print in a terminal in order # to find fitting options for rules. +#[fullscreen_delay_everything] +# fullscreen = delay +#[fullscreen_show_critical] +# msg_urgency = critical +# fullscreen = show + #[espeak] # summary = "*" # script = dunst_espeak.sh From aa7a851fdd21d7a4fb9d1a4728a629b9603052e3 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Mon, 20 Nov 2017 18:18:04 +0100 Subject: [PATCH 05/11] Catch screen without window --- src/x11/screen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/x11/screen.c b/src/x11/screen.c index 6ce1580..b232e04 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -197,6 +197,9 @@ bool window_is_fullscreen(Window window) { bool fs = false; + if (!window) + return false; + Atom has_wm_state = XInternAtom(xctx.dpy, "_NET_WM_STATE", True); if (has_wm_state == None){ return false; From dd28e62c117ab091527bfd367a4e04e8128f65f1 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Tue, 21 Nov 2017 10:51:30 +0100 Subject: [PATCH 06/11] Add Error Handler to fullscreen check --- src/x11/screen.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/x11/screen.c b/src/x11/screen.c index b232e04..c350236 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -192,6 +192,24 @@ bool have_fullscreen_window(void) return window_is_fullscreen(get_focused_window()); } +/** + * X11 ErrorHandler to mainly discard BadWindow parameter error + */ +static int XErrorHandlerFullscreen(Display *display, XErrorEvent *e) +{ + /* Ignore BadWindow errors. Window may have been gone */ + if (e->error_code == BadWindow) { + return 0; + } + + char err_buf[BUFSIZ]; + XGetErrorText(display, e->error_code, err_buf, BUFSIZ); + fputs(err_buf, stderr); + fputs("\n", stderr); + + return 0; +} + /* see screen.h */ bool window_is_fullscreen(Window window) { @@ -205,6 +223,9 @@ bool window_is_fullscreen(Window window) return false; } + XFlush(xctx.dpy); + XSetErrorHandler(XErrorHandlerFullscreen); + Atom actual_type_return; int actual_format_return; unsigned long bytes_after_return; @@ -224,6 +245,10 @@ bool window_is_fullscreen(Window window) &bytes_after_return, &prop_to_return); + XFlush(xctx.dpy); + XSync(xctx.dpy, false); + XSetErrorHandler(NULL); + if (result == Success) { for(int i = 0; i < n_items; i++) { char *atom = XGetAtomName(xctx.dpy, ((Atom*)prop_to_return)[i]); From 0f46564e975e7166cb8bd87a4d58b67412f335c8 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Fri, 12 Jan 2018 21:49:15 +0100 Subject: [PATCH 07/11] Print fullscreen value of notification --- src/notification.c | 13 +++++++++++++ src/notification.h | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/notification.c b/src/notification.c index 6418b09..d18f001 100644 --- a/src/notification.c +++ b/src/notification.c @@ -28,6 +28,18 @@ static void notification_extract_urls(notification *n); static void notification_format_message(notification *n); static void notification_dmenu_string(notification *n); +/* see notification.h */ +const char *enum_to_string_fullscreen(enum behavior_fullscreen in) +{ + switch (in) { + case FS_SHOW: return "show"; + case FS_DELAY: return "delay"; + case FS_NULL: return "(null)"; + default: + LOG_E("Enum behavior_fullscreen has wrong value."); + } +} + /* * print a human readable representation * of the given notification to stdout. @@ -49,6 +61,7 @@ void notification_print(notification *n) printf("\tfg: %s\n", n->colors[ColFG]); printf("\tbg: %s\n", n->colors[ColBG]); printf("\tframe: %s\n", n->colors[ColFrame]); + printf("\tfullscreen: %s\n", enum_to_string_fullscreen(n->fullscreen)); printf("\tid: %d\n", n->id); if (n->urls) { char *urls = string_replace_all("\n", "\t\t\n", g_strdup(n->urls)); diff --git a/src/notification.h b/src/notification.h index 0d619c1..09d2899 100644 --- a/src/notification.h +++ b/src/notification.h @@ -101,5 +101,14 @@ void notification_update_text_to_render(notification *n); void notification_do_action(notification *n); const char *notification_urgency_to_string(enum urgency urgency); + +/** + * Return the string representation for fullscreen behavior + * + * @param in the #behavior_fullscreen enum value to represent + * @return the string representation for `in` + */ +const char *enum_to_string_fullscreen(enum behavior_fullscreen in); + #endif /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ From aa5cc977cc230f26c0d9bc3a8025b28dbcb32c42 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sat, 13 Jan 2018 00:58:18 +0100 Subject: [PATCH 08/11] Add pushback mode --- dunstrc | 7 +++++++ src/notification.c | 1 + src/notification.h | 7 ++++--- src/option_parser.c | 2 ++ src/queues.c | 19 ++++++++++++++++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/dunstrc b/dunstrc index ed8e4c6..6707411 100644 --- a/dunstrc +++ b/dunstrc @@ -294,6 +294,13 @@ # NOTE: It might be helpful to run dunst -print in a terminal in order # to find fitting options for rules. +# fullscreen values +# show: show the notifications, regardless if there is a fullscreen window opened +# delay: displays the new notification, if there is there is no fullscreen window active +# If the notification is already drawn, it won't get undrawn. +# pushback: same as delay, but when switching into fullscreen, the notification will get +# withdrawn from screen again and will get delayed like a new notification + #[fullscreen_delay_everything] # fullscreen = delay #[fullscreen_show_critical] diff --git a/src/notification.c b/src/notification.c index d18f001..b54b79f 100644 --- a/src/notification.c +++ b/src/notification.c @@ -34,6 +34,7 @@ const char *enum_to_string_fullscreen(enum behavior_fullscreen in) switch (in) { case FS_SHOW: return "show"; case FS_DELAY: return "delay"; + case FS_PUSHBACK: return "pushback"; case FS_NULL: return "(null)"; default: LOG_E("Enum behavior_fullscreen has wrong value."); diff --git a/src/notification.h b/src/notification.h index 09d2899..a866214 100644 --- a/src/notification.h +++ b/src/notification.h @@ -10,9 +10,10 @@ #define DUNST_NOTIF_MAX_CHARS 5000 enum behavior_fullscreen { - FS_NULL, //!< Invalid value - FS_DELAY, //!< Delay the notification until leaving fullscreen mode - FS_SHOW, //!< Show the message when in fullscreen mode + FS_NULL, //!< Invalid value + FS_DELAY, //!< Delay the notification until leaving fullscreen mode + FS_PUSHBACK, //!< When entering fullscreen mode, push the notification back to waiting + FS_SHOW, //!< Show the message when in fullscreen mode }; /// Representing the urgencies according to the notification spec diff --git a/src/option_parser.c b/src/option_parser.c index ca82813..b95f911 100644 --- a/src/option_parser.c +++ b/src/option_parser.c @@ -561,6 +561,8 @@ enum behavior_fullscreen parse_enum_fullscreen(const char *string, enum behavior return FS_SHOW; else if (strcmp(string, "delay") == 0) return FS_DELAY; + else if (strcmp(string, "pushback") == 0) + return FS_PUSHBACK; else { LOG_W("Unknown fullscreen value: '%s'\n", string); return def; diff --git a/src/queues.c b/src/queues.c index 09fed9c..cf229a2 100644 --- a/src/queues.c +++ b/src/queues.c @@ -332,6 +332,22 @@ void queues_update(bool fullscreen) return; } + /* move notifications back to queue, which are set to pushback */ + if (fullscreen) { + GList *iter = g_queue_peek_head_link(displayed); + while (iter) { + notification *n = iter->data; + GList *nextiter = iter->next; + + if (n->fullscreen == FS_PUSHBACK){ + g_queue_delete_link(displayed, iter); + g_queue_insert_sorted(waiting, n, notification_cmp_data, NULL); + } + + iter = nextiter; + } + } + /* move notifications from queue to displayed */ GList *iter = g_queue_peek_head_link(waiting); while (iter) { @@ -346,7 +362,8 @@ void queues_update(bool fullscreen) if (!n) return; - if (fullscreen && n->fullscreen == FS_DELAY) { + if (fullscreen + && (n->fullscreen == FS_DELAY || n->fullscreen == FS_PUSHBACK)) { iter = nextiter; continue; } From c12873184cb18f24dd56094860ef853587769a04 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Thu, 15 Feb 2018 02:47:52 +0100 Subject: [PATCH 09/11] Debug processed XEvents --- src/x11/screen.c | 2 ++ src/x11/x.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/x11/screen.c b/src/x11/screen.c index c350236..2bd37b8 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -146,6 +146,8 @@ void screen_check_event(XEvent event) { if (event.type == randr_event_base + RRScreenChangeNotify) randr_update(); + else + LOG_D("XEvent: Ignored '%d'", event.type); } void xinerama_update(void) diff --git a/src/x11/x.c b/src/x11/x.c index 92942da..fa2bc1c 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -852,6 +852,8 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer unsigned int state; while (XPending(xctx.dpy) > 0) { XNextEvent(xctx.dpy, &ev); + LOG_D("XEvent: processing '%d'", ev.type); + switch (ev.type) { case Expose: if (ev.xexpose.count == 0 && xctx.visible) { From a7bc16874d8e32a639b443923e673d905bf65f15 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Fri, 16 Feb 2018 23:28:25 +0100 Subject: [PATCH 10/11] log wakeup --- src/dunst.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dunst.c b/src/dunst.c index 6765af4..c76e078 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -48,6 +48,8 @@ void wake_up(void) static gboolean run(void *data) { + LOG_D("RUN"); + bool fullscreen = have_fullscreen_window(); queues_check_timeouts(x_is_idle(), fullscreen); From 0cf4753a68b54968b0d5205a267339a33e20a50c Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Sat, 24 Feb 2018 17:30:15 +0100 Subject: [PATCH 11/11] Wake up for fullscreen change events The PropertyNotify handling has been changed in the dropgtk branch to ignore XEvents, when redrawing was unnecessary. But when the fullscreen state of a window changes, we can't ignore the event, because it didn't change the screen. Additionally, there had been a mistake in the handling of the cur_screen: The xctx.cur_screen field will only get updated, when the application is visible and gets redrawn. Therefore, when a PropertyNotify event arrived while the application had been hidden and the screens do not match anymore, wake_up() will be called albeit being unnecessary. Calling x_win_draw() when the screens change is also the preferable solution over wake_up(), as there is nothing subject to change in the queues when the displays change. --- src/x11/x.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index fa2bc1c..7ec682d 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -60,6 +60,7 @@ typedef struct _colored_layout { } colored_layout; cairo_ctx_t cairo_ctx; +static bool fullscreen_last = false; /* FIXME refactor setup teardown handlers into one setup and one teardown */ static void x_shortcut_setup_error_handler(void); @@ -848,6 +849,7 @@ gboolean x_mainloop_fd_check(GSource *source) */ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { + bool fullscreen_now; XEvent ev; unsigned int state; while (XPending(xctx.dpy) > 0) { @@ -910,13 +912,20 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer wake_up(); break; case PropertyNotify: + fullscreen_now = have_fullscreen_window(); + + if (fullscreen_now != fullscreen_last) { + fullscreen_last = fullscreen_now; + wake_up(); + } else if ( settings.f_mode != FOLLOW_NONE /* Ignore PropertyNotify, when we're still on the * same screen. PropertyNotify is only neccessary * to detect a focus change to another screen */ - if( settings.f_mode != FOLLOW_NONE - && get_active_screen()->scr != xctx.cur_screen) - wake_up(); + && xctx.visible + && get_active_screen()->scr != xctx.cur_screen) { + x_win_draw(); + } break; default: screen_check_event(ev);