When a window has XUrgencyHint set, bounce the app icon periodically.
---
 src/application.c |    5 ++++
 src/application.h |    2 +
 src/client.c      |    5 ++-
 src/superfluous.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/window.c      |    4 ++-
 5 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/src/application.c b/src/application.c
index 1415efa..af0fe61 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 5eeefef..d6eab3d 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 9f3a598..853befe 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 8bbef81..be809c3 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 a0ae2fd..fef6b59 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;
        }
-- 
1.7.1


-- 
To unsubscribe, send mail to [email protected].

Reply via email to