diff --git a/src/application.c b/src/application.c index 1415efa8..af0fe618 100644 --- a/src/application.c +++ b/src/application.c @@ -260,6 +260,7 @@ WApplication *wApplicationCreate(WWindow * wwin) wapp->refcount = 1; wapp->last_focused = NULL; + wapp->urgent_bounce_timer = NULL; wapp->last_workspace = 0; @@ -409,6 +410,10 @@ void wApplicationDestroy(WApplication * wapp) if (wapp->refcount > 0) return; + if (wapp->urgent_bounce_timer) { + WMDeleteTimerHandler(wapp->urgent_bounce_timer); + wapp->urgent_bounce_timer = NULL; + } if (wapp->flags.bouncing) { /* event.c:handleDestroyNotify forced this destroy and thereby overlooked the bounce callback */ diff --git a/src/application.h b/src/application.h index 5eeefefb..d6eab3de 100644 --- a/src/application.h +++ b/src/application.h @@ -42,6 +42,7 @@ typedef struct WApplication { int last_workspace; /* last workspace used to work on the * app */ + WMHandlerID *urgent_bounce_timer; struct { unsigned int skip_next_animation:1; unsigned int hidden:1; @@ -60,6 +61,7 @@ void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance, char *wm_class); void wAppBounce(WApplication *); +void wAppBounceWhileUrgent(WApplication *); #ifdef NEWAPPICON #define wApplicationActivate(wapp) do { \ diff --git a/src/client.c b/src/client.c index 9f3a5981..853befeb 100644 --- a/src/client.c +++ b/src/client.c @@ -486,8 +486,9 @@ void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event) wwin->flags.urgent = 1; else wwin->flags.urgent = 0; - /*} else if (wwin->fake_group!=NULL) { - wwin->group_id = wwin->fake_group->leader; */ + wAppBounceWhileUrgent(wApplicationOf(wwin->main_window)); + /*} else if (wwin->fake_group!=NULL) { + wwin->group_id = wwin->fake_group->leader; */ } else { wwin->group_id = None; } diff --git a/src/superfluous.c b/src/superfluous.c index 8bbef819..be809c3d 100644 --- a/src/superfluous.c +++ b/src/superfluous.c @@ -258,6 +258,7 @@ void DoWindowBirth(WWindow *wwin) #define BOUNCE_HEIGHT 24 #define BOUNCE_LENGTH 0.3 #define BOUNCE_DAMP 0.6 +#define URGENT_BOUNCE_DELAY 3000 typedef struct AppBouncerData { WApplication *wapp; @@ -400,3 +401,56 @@ void wAppBounce(WApplication *wapp) data->timer = WMAddPersistentTimerHandler(BOUNCE_DELAY, doAppBounce, data); } } + +static int appIsUrgent(WApplication *wapp) +{ + WScreen *scr; + WWindow *wlist; + + if (!wapp->main_window_desc) { + wwarning("group leader not found for window group"); + return 0; + } + scr = wapp->main_window_desc->screen_ptr; + wlist = scr->focused_window; + if (!wlist) + return 0; + + while (wlist) { + if (wlist->main_window == wapp->main_window) { + if (wlist->flags.urgent) + return 1; + } + wlist = wlist->prev; + } + + return 0; +} + +static void doAppUrgentBounce(void *arg) +{ + WApplication *wapp = (WApplication *)arg; + + if (appIsUrgent(wapp)) { + wAppBounce(wapp); + } else { + WMDeleteTimerHandler(wapp->urgent_bounce_timer); + wapp->urgent_bounce_timer = NULL; + } +} + +void wAppBounceWhileUrgent(WApplication *wapp) +{ + if (!wapp) return; + if (appIsUrgent(wapp)) { + if (!wapp->urgent_bounce_timer) { + wapp->urgent_bounce_timer = WMAddPersistentTimerHandler(URGENT_BOUNCE_DELAY, doAppUrgentBounce, wapp); + doAppUrgentBounce(wapp); + } + } else { + if (wapp->urgent_bounce_timer) { + WMDeleteTimerHandler(wapp->urgent_bounce_timer); + wapp->urgent_bounce_timer = NULL; + } + } +} diff --git a/src/window.c b/src/window.c index ed47d968..f9441aa8 100644 --- a/src/window.c +++ b/src/window.c @@ -710,8 +710,10 @@ WWindow *wManageWindow(WScreen *scr, Window window) wwin->group_id = None; } - if (wwin->wm_hints->flags & UrgencyHint) + if (wwin->wm_hints->flags & UrgencyHint) { wwin->flags.urgent = 1; + wAppBounceWhileUrgent(wApplicationOf(wwin->main_window)); + } } else { wwin->group_id = None; }