first steps to making rspanel not useless for anyone but me
authorMikael Magnusson <mikachu@comhem.se>
Fri, 1 Jun 2007 17:01:31 +0000 (17:01 +0000)
committerMikael Magnusson <mikachu@comhem.se>
Fri, 1 Jun 2007 17:01:31 +0000 (17:01 +0000)
rspanel.c

index 47d4303..bbb8513 100644 (file)
--- a/rspanel.c
+++ b/rspanel.c
@@ -41,6 +41,9 @@ int WINWIDTH = 827;
 //#define PAGER         /* use a desktop pager? */
 #define PAGER_DIGIT_WIDTH 6
 #define PAGER_BUTTON_WIDTH 20
+#ifdef PAGER
+#undef PANGO
+#endif
 
 /* don't edit these */
 #define TEXTPAD 6
@@ -122,12 +125,44 @@ char *atom_names[] = {
     "_NET_WM_NAME",
     "UTF8_STRING",
     "_NET_ACTIVE_WINDOW",
+    "_NET_RESTACK_WINDOW",
 };
 
 #define ATOM_COUNT (sizeof (atom_names) / sizeof (atom_names[0]))
 
 Atom atoms[ATOM_COUNT];
 
+typedef enum {
+KWM_WIN_ICON,
+WM_STATE,
+_MOTIF_WM_HINTS,
+_NET_WM_STATE,
+_NET_WM_STATE_SKIP_TASKBAR,
+_NET_WM_STATE_SHADED,
+_NET_WM_STATE_BELOW,
+_NET_WM_STATE_HIDDEN,
+_NET_WM_DESKTOP,
+_NET_WM_WINDOW_TYPE,
+_NET_WM_WINDOW_TYPE_DOCK,
+_NET_WM_STRUT,
+_WIN_HINTS,
+_NET_CLIENT_LIST,
+_NET_CLIENT_LIST_STACKING,
+_NET_NUMBER_OF_DESKTOPS,
+_NET_CURRENT_DESKTOP,
+_OB_WM_ACTION,
+_NET_WM_NAME,
+STRING_UTF8,
+_NET_ACTIVE_WINDOW,
+_NET_RESTACK_WINDOW,
+} atom_t;
+
+enum {
+    REMOVE = 0,
+    ADD,
+    TOGGLE
+};
+
 #define atom_KWM_WIN_ICON atoms[0]
 #define atom_WM_STATE atoms[1]
 #define atom__MOTIF_WM_HINTS atoms[2]
@@ -265,7 +300,7 @@ void get_task_kdeicon(task * tk)
 {
     unsigned long *data;
 
-    data = get_prop_data(tk->win, atom_KWM_WIN_ICON, atom_KWM_WIN_ICON, 0);
+    data = get_prop_data(tk->win, atoms[KWM_WIN_ICON], atoms[KWM_WIN_ICON], 0);
     if (data) {
         tk->icon = data[0];
         tk->mask = data[1];
@@ -288,7 +323,7 @@ int generic_get_int(Window win, Atom at)
 
 int find_desktop(Window win)
 {
-    return generic_get_int(win, atom__NET_WM_DESKTOP);
+    return generic_get_int(win, atoms[_NET_WM_DESKTOP]);
 }
 
 int is_hidden(Window win)
@@ -297,11 +332,11 @@ int is_hidden(Window win)
     int ret = 0;
     int num;
 
-    data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num);
+    data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num);
     if (data) {
         while (num) {
             num--;
-            if ((data[num]) == atom__NET_WM_STATE_SKIP_TASKBAR)
+            if ((data[num]) == atoms[_NET_WM_STATE_SKIP_TASKBAR])
                 ret = 1;
         }
         XFree(data);
@@ -315,11 +350,11 @@ int is_iconified(Window win)
     int ret = 0;
     int num;
 
-    data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num);
+    data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num);
     if (data) {
         while (num) {
             num--;
-            if ((data[num]) == atom__NET_WM_STATE_HIDDEN)
+            if ((data[num]) == atoms[_NET_WM_STATE_HIDDEN])
                 ret = 1;
         }
         XFree(data);
@@ -333,11 +368,11 @@ int is_shaded(Window win)
     int ret = 0;
     int num;
 
-    data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num);
+    data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num);
     if (data) {
         while (num) {
             num--;
-            if ((data[num]) == atom__NET_WM_STATE_SHADED)
+            if ((data[num]) == atoms[_NET_WM_STATE_SHADED])
                 ret = 1;
         }
         XFree(data);
@@ -347,12 +382,12 @@ int is_shaded(Window win)
 
 int get_current_desktop(void)
 {
-    return generic_get_int(root_win, atom__NET_CURRENT_DESKTOP);
+    return generic_get_int(root_win, atoms[_NET_CURRENT_DESKTOP]);
 }
 
 int get_number_of_desktops(void)
 {
-    return generic_get_int(root_win, atom__NET_NUMBER_OF_DESKTOPS);
+    return generic_get_int(root_win, atoms[_NET_NUMBER_OF_DESKTOPS]);
 }
 
 void add_task(Window win, int focus)
@@ -371,7 +406,7 @@ void add_task(Window win, int focus)
     tk = calloc(1, sizeof(task));
     tk->win = win;
     tk->focused = focus;
-    tk->name = get_prop_data(tk->win, atom__NET_WM_NAME, atom_STRING_UTF8, 0) ?:
+    tk->name = get_prop_data(tk->win, atoms[_NET_WM_NAME], atoms[STRING_UTF8], 0) ?:
                get_prop_data(tk->win, XA_WM_NAME, XA_STRING, 0);
 //    tk->name = get_prop_data(win, XA_WM_NAME, XA_STRING, 0);
     //tk->locale = get_prop_data(win, XA_WM_LOCALE_NAME, XA_STRING, 0);
@@ -439,12 +474,12 @@ Window gui_create_taskbar(void)
                                      /* attribs  */ &att);
 
     /* reside on ALL desktops */
-    set_prop(win, atom__NET_WM_DESKTOP, XA_CARDINAL, 0xFFFFFFFF);
-    set_prop(win, atom__NET_WM_WINDOW_TYPE, XA_ATOM,
-             atom__NET_WM_WINDOW_TYPE_DOCK);
-    set_prop(win, atom__NET_WM_STATE, XA_ATOM, atom__NET_WM_STATE_BELOW);
+    set_prop(win, atoms[_NET_WM_DESKTOP], XA_CARDINAL, 0xFFFFFFFF);
+    set_prop(win, atoms[_NET_WM_WINDOW_TYPE], XA_ATOM,
+             atoms[_NET_WM_WINDOW_TYPE_DOCK]);
+    set_prop(win, atoms[_NET_WM_STATE], XA_ATOM, atoms[_NET_WM_STATE_BELOW]);
     /* use old gnome hint since sawfish doesn't support _NET_WM_STRUT */
-    set_prop(win, atom__WIN_HINTS, XA_CARDINAL,
+    set_prop(win, atoms[_WIN_HINTS], XA_CARDINAL,
              WIN_HINTS_SKIP_FOCUS | WIN_HINTS_SKIP_WINLIST |
              WIN_HINTS_SKIP_TASKBAR | WIN_HINTS_DO_NOT_COVER);
     XChangeProperty(dd, win, XA_WM_NAME, XA_STRING, 8, PropModeReplace,
@@ -453,7 +488,7 @@ Window gui_create_taskbar(void)
     /* borderless motif hint */
     bzero(&mwm, sizeof(mwm));
     mwm.flags = MWM_HINTS_DECORATIONS;
-    XChangeProperty(dd, win, atom__MOTIF_WM_HINTS, atom__MOTIF_WM_HINTS, 32,
+    XChangeProperty(dd, win, atoms[_MOTIF_WM_HINTS], atoms[_MOTIF_WM_HINTS], 32,
                     PropModeReplace, (unsigned char *)&mwm,
                     sizeof(MWMHints) / 4);
 
@@ -724,28 +759,51 @@ void ob_action(Window win, char *action)
 
     xev.type = ClientMessage;
     xev.window = win;
-    xev.message_type = atom__OB_WM_ACTION;
+    xev.message_type = atoms[_OB_WM_ACTION];
     xev.format = 32;
     /*strncpy(xev.data.b, action, 20);*/
     xev.data.l[0] = XInternAtom(dd, act_name, False);
     XSendEvent(dd, root_win, False, SubstructureRedirectMask, (XEvent *)&xev);
 }
 
+void netwm_action(Window win, atom_t atom, Time time, long l)
+{
+    XClientMessageEvent xev = {
+    .type = ClientMessage,
+    .window = win,
+    .format = 32,
+    .data.l = {0},
+    .message_type = atoms[atom]
+    };
+    
+    if (atom == _NET_ACTIVE_WINDOW) {
+        xev.data.l[0] = 2;
+        xev.data.l[1] = time;
+        xev.data.l[2] = 0;
+    } else if (atom == _NET_CURRENT_DESKTOP) {
+        xev.data.l[0] = l;
+        xev.data.l[1] = time;
+    } else if (atom == _NET_RESTACK_WINDOW) {
+        xev.data.l[0] = 2;
+        xev.data.l[2] = l;
+    } else {
+        xev.message_type = atoms[_NET_WM_STATE];
+        xev.data.l[0] = l;
+        xev.data.l[1] = atoms[atom];
+        xev.data.l[3] = 2;
+    }
+
+    XSendEvent(dd, root_win, False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent *)&xev);
+}
+
 #ifdef PAGER
 
-void switch_desk(int new_desk)
+void switch_desk(int new_desk, Time time)
 {
-    XClientMessageEvent xev;
-
     if (get_number_of_desktops() <= new_desk)
         return;
 
-    xev.type = ClientMessage;
-    xev.window = root_win;
-    xev.message_type = atom__NET_CURRENT_DESKTOP;
-    xev.format = 32;
-    xev.data.l[0] = new_desk;
-    XSendEvent(dd, root_win, False, SubstructureRedirectMask, (XEvent *)&xev);
+    netwm_action(None, _NET_CURRENT_DESKTOP, time, new_desk);
 }
 
 void pager_draw_button(int x, int num)
@@ -917,11 +975,11 @@ void taskbar_read_clientlist(void)
         tb.my_desktop = desk;
     }
 
-    win = get_prop_data(root_win, atom__NET_ACTIVE_WINDOW, XA_WINDOW, &num);
+    win = get_prop_data(root_win, atoms[_NET_ACTIVE_WINDOW], XA_WINDOW, &num);
     if (win && num > 0)
         focus_win = win[0];
 
-    win = get_prop_data(root_win, atom__NET_CLIENT_LIST, XA_WINDOW, &num);
+    win = get_prop_data(root_win, atoms[_NET_CLIENT_LIST], XA_WINDOW, &num);
     if (!win)
         return;
 
@@ -950,13 +1008,13 @@ dontdel:
     XFree(win);
 }
 
-void handle_press(int x, int y, int button)
+void handle_press(int x, int y, int button, Time time)
 {
     task *tk;
 
 #ifdef PAGER
     if ((y > 2 && y < WINHEIGHT - 2 && x > GRILL_WIDTH) && button == 1)
-        switch_desk((x - GRILL_WIDTH) / PAGER_BUTTON_WIDTH);
+        switch_desk((x - GRILL_WIDTH) / PAGER_BUTTON_WIDTH, time);
     else
 #endif
     /* clicked left grill */
@@ -988,34 +1046,46 @@ void handle_press(int x, int y, int button)
                     case 1:
                         if (tk->iconified && tk->shaded)
                             ob_action(tk->win, "unshade");
-                        ob_action(tk->win, "activate");
+                        //ob_action(tk->win, "activate");
+                        netwm_action(tk->win, _NET_ACTIVE_WINDOW, time, 0);
                         break;
                     case 2:
                         if (tk->iconified)
-                            ob_action(tk->win, "deiconify");
+                            //ob_action(tk->win, "deiconify");
+                            netwm_action(tk->win, _NET_WM_STATE_HIDDEN, time, REMOVE);
                         else
-                            ob_action(tk->win, "iconify");
+                            netwm_action(tk->win, _NET_WM_STATE_HIDDEN, time, ADD);
+                            //ob_action(tk->win, "iconify");
                         break;
                     case 3:
                         ob_action(tk->win, "raiselower");
                         break;
                     case 4:
-                        ob_action(tk->win, "shadelower");
+                        if (is_shaded(tk->win))
+                                netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Below);
+                        else
+                                netwm_action(tk->win, _NET_WM_STATE_SHADED, time, ADD);
                         break;
                     case 5:
-                        ob_action(tk->win, "unshaderaise");
+                        if (is_shaded(tk->win))
+                            netwm_action(tk->win, _NET_WM_STATE_SHADED, time, REMOVE);
+                        else
+                                netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Above);
                         break;
                     case 9:
                         if (tk->iconified)
-                            ob_action(tk->win, "deiconify");
+                            netwm_action(tk->win, _NET_WM_STATE_SHADED, time, REMOVE);
+                            //ob_action(tk->win, "deiconify");
                         else
                             ob_action(tk->win, "focus");
                         break;
                     case 6:
-                        ob_action(tk->win, "lower");
+//                        ob_action(tk->win, "lower");
+                        netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Below);
                         break;
                     case 7:
-                        ob_action(tk->win, "raise");
+//                        ob_action(tk->win, "raise");
+                        netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Above);
                         break;
                 }
                 return;
@@ -1070,7 +1140,7 @@ void handle_propertynotify(Window win, Atom at)
     task *tk;
 
     if (win == root_win) {
-        if (at == atom__NET_CLIENT_LIST || at == atom__NET_CURRENT_DESKTOP || at == atom__NET_CLIENT_LIST_STACKING) {
+        if (at == atoms[_NET_CLIENT_LIST] || at == atoms[_NET_CURRENT_DESKTOP] || at == atoms[_NET_CLIENT_LIST_STACKING]) {
             taskbar_read_clientlist();
             gui_draw_taskbar();
         }
@@ -1081,10 +1151,10 @@ void handle_propertynotify(Window win, Atom at)
     if (!tk)
         return;
 
-    if (at == XA_WM_NAME || at == atom__NET_WM_NAME) {
+    if (at == XA_WM_NAME || at == atoms[_NET_WM_NAME]) {
         /* window's title changed */
         char *newname;
-        newname = get_prop_data(tk->win, atom__NET_WM_NAME, atom_STRING_UTF8, 0) ?:
+        newname = get_prop_data(tk->win, atoms[_NET_WM_NAME], atoms[STRING_UTF8], 0) ?:
                   get_prop_data(tk->win, XA_WM_NAME, XA_STRING, 0);
         if (newname) {
             if (tk->name && !strcmp(newname, tk->name)) {
@@ -1096,7 +1166,7 @@ void handle_propertynotify(Window win, Atom at)
             XFree(tk->name);
         tk->name = newname;
         gui_draw_task(tk);
-    } else if (at == atom__NET_WM_STATE) {
+    } else if (at == atoms[_NET_WM_STATE]) {
         /* iconified state changed? */
         if (is_iconified(tk->win) != tk->iconified) {
             tk->iconified = !tk->iconified;
@@ -1113,7 +1183,7 @@ void handle_propertynotify(Window win, Atom at)
             get_task_hinticon(tk);
             gui_draw_task(tk);
         //}
-    } else if (at == atom__NET_WM_DESKTOP) {
+    } else if (at == atoms[_NET_WM_DESKTOP]) {
         if (find_desktop(win) != get_current_desktop())
             del_task(tk->win);
     }
@@ -1165,7 +1235,7 @@ main(int argc, char *argv[])
             XNextEvent(dd, &ev);
             switch (ev.type) {
             case ButtonPress:
-                handle_press(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button);
+                handle_press(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.time);
                 break;
             case DestroyNotify:
                 del_task(ev.xdestroywindow.window);