Add support for $desktop, $desktop_number and $desktop_name
[monky] / src / x11.c
index 4769de9..8a93a41 100644 (file)
--- a/src/x11.c
+++ b/src/x11.c
@@ -7,7 +7,7 @@
  * Please see COPYING for details
  *
  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
- * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
+ * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
  *     (see AUTHORS)
  * All rights reserved.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
- * $Id$ */
+ */
 
+#include "config.h"
 #include "conky.h"
+#include "logging.h"
+#include "common.h"
 
-#ifdef X11
+#include "x11.h"
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xmd.h>
 #include <X11/Xutil.h>
+#ifdef IMLIB2
+#include "imlib2.h"
+#endif /* IMLIB2 */
+
 #ifdef XFT
 #include <X11/Xft/Xft.h>
+int use_xft = 0;
 #endif
 
 #ifdef HAVE_XDBE
 int use_xdbe;
 #endif
 
-#ifdef XFT
-int use_xft = 0;
-#endif
-
 /* some basic X11 stuff */
-Display *display;
+Display *display = NULL;
 int display_width;
 int display_height;
 int screen;
@@ -64,10 +68,12 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop);
 static Window find_subwindow(Window win, int w, int h);
 
 /* X11 initializer */
-void init_X11(void)
+void init_X11(const char *disp)
 {
-       if ((display = XOpenDisplay(0)) == NULL) {
-               CRIT_ERR("can't open display: %s", XDisplayName(0));
+       if (!display) {
+               if ((display = XOpenDisplay(disp)) == NULL) {
+                       CRIT_ERR("can't open display: %s", XDisplayName(0));
+               }
        }
 
        screen = DefaultScreen(display);
@@ -139,7 +145,7 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop)
                        XFree(buf);
                        XFree(children);
                        fprintf(stderr,
-                               "Conky: desktop window (%lx) found from __SWM_VROOT property\n",
+                               PACKAGE_NAME": desktop window (%lx) found from __SWM_VROOT property\n",
                                win);
                        fflush(stderr);
                        *p_root = win;
@@ -168,10 +174,10 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop)
 
        if (win != root) {
                fprintf(stderr,
-                       "Conky: desktop window (%lx) is subwindow of root window (%lx)\n",
+                       PACKAGE_NAME": desktop window (%lx) is subwindow of root window (%lx)\n",
                        win, root);
        } else {
-               fprintf(stderr, "Conky: desktop window (%lx) is root window\n", win);
+               fprintf(stderr, PACKAGE_NAME": desktop window (%lx) is root window\n", win);
        }
 
        fflush(stderr);
@@ -207,6 +213,13 @@ void set_transparent_background(Window win)
        // XClearWindow(display, win); not sure why this was here
 }
 
+void destroy_window(void)
+{
+       XDestroyWindow(display, window.window);
+       XFreeGC(display, window.gc);
+       memset(&window, 0, sizeof(struct conky_window));
+}
+
 void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                char **argv, int argc)
 {
@@ -218,7 +231,6 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
 #ifdef OWN_WINDOW
        if (own_window) {
-
                if (!find_desktop_window(&window.root, &window.desktop)) {
                        return;
                }
@@ -238,7 +250,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        XLowerWindow(display, window.window);
 
-                       fprintf(stderr, "Conky: window type - override\n");
+                       fprintf(stderr, PACKAGE_NAME": window type - override\n");
                        fflush(stderr);
                } else { /* window.type != TYPE_OVERRIDE */
 
@@ -252,6 +264,9 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                        XWMHints wmHint;
                        Atom xa;
 
+                       if (window.type == TYPE_DOCK) {
+                               window.x = window.y = 0;
+                       }
                        /* Parent is root window so WM can take control */
                        window.window = XCreateWindow(display, window.root, window.x,
                                window.y, w, h, 0, CopyFromParent, InputOutput, CopyFromParent,
@@ -264,7 +279,11 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                        /* allow decorated windows to be given input focus by WM */
                        wmHint.input =
                                TEST_HINT(window.hints, HINT_UNDECORATED) ? False : True;
-                       wmHint.initial_state = NormalState;
+                        if (window.type == TYPE_DOCK || window.type == TYPE_PANEL) {
+                               wmHint.initial_state = WithdrawnState;
+                        } else {
+                               wmHint.initial_state = NormalState;
+                        }
 
                        XmbSetWMProperties(display, window.window, window.title, NULL, argv,
                                argc, NULL, &wmHint, &classHint);
@@ -279,18 +298,23 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                                switch (window.type) {
                                        case TYPE_DESKTOP:
                                                prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP);
-                                               fprintf(stderr, "Conky: window type - desktop\n");
+                                               fprintf(stderr, PACKAGE_NAME": window type - desktop\n");
                                                fflush(stderr);
                                                break;
                                        case TYPE_DOCK:
                                                prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
-                                               fprintf(stderr, "Conky: window type - dock\n");
+                                               fprintf(stderr, PACKAGE_NAME": window type - dock\n");
+                                               fflush(stderr);
+                                               break;
+                                       case TYPE_PANEL:
+                                               prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
+                                               fprintf(stderr, PACKAGE_NAME": window type - panel\n");
                                                fflush(stderr);
                                                break;
                                        case TYPE_NORMAL:
                                        default:
                                                prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
-                                               fprintf(stderr, "Conky: window type - normal\n");
+                                               fprintf(stderr, PACKAGE_NAME": window type - normal\n");
                                                fflush(stderr);
                                                break;
                                }
@@ -302,7 +326,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Window decorations */
                        if (TEST_HINT(window.hints, HINT_UNDECORATED)) {
-                               /* fprintf(stderr, "Conky: hint - undecorated\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n");
                                fflush(stderr); */
 
                                xa = ATOM(_MOTIF_WM_HINTS);
@@ -315,7 +339,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Below other windows */
                        if (TEST_HINT(window.hints, HINT_BELOW)) {
-                               /* fprintf(stderr, "Conky: hint - below\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - below\n");
                                fflush(stderr); */
 
                                xa = ATOM(_WIN_LAYER);
@@ -337,7 +361,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Above other windows */
                        if (TEST_HINT(window.hints, HINT_ABOVE)) {
-                               /* fprintf(stderr, "Conky: hint - above\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - above\n");
                                fflush(stderr); */
 
                                xa = ATOM(_WIN_LAYER);
@@ -359,7 +383,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Sticky */
                        if (TEST_HINT(window.hints, HINT_STICKY)) {
-                               /* fprintf(stderr, "Conky: hint - sticky\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n");
                                fflush(stderr); */
 
                                xa = ATOM(_NET_WM_DESKTOP);
@@ -381,7 +405,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Skip taskbar */
                        if (TEST_HINT(window.hints, HINT_SKIP_TASKBAR)) {
-                               /* fprintf(stderr, "Conky: hint - skip_taskbar\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n");
                                fflush(stderr); */
 
                                xa = ATOM(_NET_WM_STATE);
@@ -395,7 +419,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
 
                        /* Skip pager */
                        if (TEST_HINT(window.hints, HINT_SKIP_PAGER)) {
-                               /* fprintf(stderr, "Conky: hint - skip_pager\n");
+                               /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n");
                                fflush(stderr); */
 
                                xa = ATOM(_NET_WM_STATE);
@@ -408,14 +432,15 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                        }
                } /* else { window.type != TYPE_OVERRIDE */
 
-               fprintf(stderr, "Conky: drawing to created window (0x%lx)\n",
+               fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n",
                        window.window);
                fflush(stderr);
 
                XMapWindow(display, window.window);
+
        } else /* if (own_window) { */
 #endif
-       /* root / desktop window */
+               /* root / desktop window */
        {
                XWindowAttributes attrs;
 
@@ -428,7 +453,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                        window.height = attrs.height;
                }
 
-               fprintf(stderr, "Conky: drawing to desktop window\n");
+               fprintf(stderr, PACKAGE_NAME": drawing to desktop window\n");
        }
 
        /* Drawable is same as window. This may be changed by double buffering. */
@@ -445,7 +470,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                                window.window, XdbeBackground);
                        if (window.back_buffer != None) {
                                window.drawable = window.back_buffer;
-                               fprintf(stderr, "Conky: drawing to double buffer\n");
+                               fprintf(stderr, PACKAGE_NAME": drawing to double buffer\n");
                        } else {
                                use_xdbe = 0;
                        }
@@ -455,10 +480,16 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
                }
        }
        if (!use_xdbe) {
-               fprintf(stderr, "Conky: drawing to single buffer\n");
+               fprintf(stderr, PACKAGE_NAME": drawing to single buffer\n");
        }
 #endif
-
+       window.visual = DefaultVisual(display, DefaultScreen(display));
+       window.colourmap = DefaultColormap(display, DefaultScreen(display));
+#ifdef IMLIB2
+       {
+               cimlib_init(display, window.drawable, window.visual, window.colourmap);
+       }
+#endif /* IMLIB2 */
        XFlush(display);
 
        /* set_transparent_background(window.window);
@@ -470,13 +501,12 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour,
        } */
 #endif
 
+       XSelectInput(display, window.window, ExposureMask
 #ifdef OWN_WINDOW
-       XSelectInput(display, window.window, ExposureMask |
-               (own_window ? (StructureNotifyMask | PropertyChangeMask |
-               ButtonPressMask | ButtonReleaseMask) : 0));
-#else
-       XSelectInput(display, window.window, ExposureMask);
+               | (own_window ? (StructureNotifyMask | PropertyChangeMask |
+               ButtonPressMask | ButtonReleaseMask) : 0)
 #endif
+               );
 }
 
 static Window find_subwindow(Window win, int w, int h)
@@ -550,4 +580,144 @@ void create_gc(void)
                GCFunction | GCGraphicsExposures, &values);
 }
 
-#endif /* X11 */
+void update_x11info(void)
+{
+        Window root;
+       Atom actual_type, atom;
+       int actual_format;
+       unsigned long nitems;
+       unsigned long bytes_after;
+       unsigned char *prop = NULL;
+
+       struct information *current_info = &info;
+       current_info->x11.monitor.number = XScreenCount(display);
+       current_info->x11.monitor.current = XDefaultScreen(display);
+
+       root = RootWindow(display, current_info->x11.monitor.current);
+
+       //Get current desktop number
+       if ((atom = XInternAtom(display, "_NET_CURRENT_DESKTOP", True)) != None) {
+         if ( (XGetWindowProperty( display, root, atom,
+                                   0, 1L, False, XA_CARDINAL,
+                                   &actual_type, &actual_format, &nitems,
+                                   &bytes_after, &prop ) == Success ) &&
+              (actual_type == XA_CARDINAL) &&
+              (nitems == 1L) ) {
+           current_info->x11.desktop.current = prop[0]+1;
+         }
+       }
+
+       //Get total number of available desktops
+       if ((atom = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", True)) != None) {
+         if ( (XGetWindowProperty( display, root, atom,
+                                   0, 1L, False, XA_CARDINAL,
+                                   &actual_type, &actual_format, &nitems,
+                                   &bytes_after, &prop ) == Success ) &&
+              (actual_type == XA_CARDINAL) &&
+              (nitems == 1L) ) {
+           current_info->x11.desktop.number = prop[0];
+         }
+       }
+
+       //Get current desktop name
+       if ((atom = XInternAtom(display, "_NET_DESKTOP_NAMES", True)) != None) {
+         if ( (XGetWindowProperty( display, root, atom,
+                                   0, (~0L), False, ATOM(UTF8_STRING),
+                                   &actual_type, &actual_format, &nitems,
+                                   &bytes_after, &prop ) == Success ) &&
+              (actual_type == ATOM(UTF8_STRING)) &&
+              (nitems > 0L) ) {
+           unsigned int i = 0, j = 0;
+           int k = 0;
+           while ( i < nitems ) {
+             if ( prop[i++] == '\0' ) {
+               if ( ++k == current_info->x11.desktop.current ) {
+                 if(current_info->x11.desktop.name) {
+                   free(current_info->x11.desktop.name);
+                   current_info->x11.desktop.name = NULL;
+                 }
+                 current_info->x11.desktop.name = malloc(i-j);
+                 //desktop names can be empty but should always be not null
+                 strcpy( current_info->x11.desktop.name, (char *)&prop[j] );
+                 break;
+               }
+               j = i;
+             }
+           }
+         }
+       }
+
+}
+
+/* reserve window manager space */
+void set_struts(int sidenum)
+{
+       Atom strut;
+       if ((strut = ATOM(_NET_WM_STRUT)) != None) {
+               /* reserve space at left, right, top, bottom */
+               signed long sizes[12] = {0};
+               int i;
+
+               /* define strut depth */
+               switch (sidenum) {
+                       case 0:
+                       {
+                               /* left side */
+                               sizes[0] = window.x + window.width;
+                               break;
+                       }
+                       case 1:
+                       {
+                               /* right side */
+                               sizes[1] = display_width - window.x;
+                               break;
+                       }
+                       case 2:
+                       {
+                               /* top side */
+                               sizes[2] = window.y + window.height;
+                               break;
+                       }
+                       case 3:
+                       {
+                               /* bottom side */
+                               sizes[3] = display_height - window.y;
+                               break;
+                       }
+               }
+
+               /* define partial strut length */
+               if (sidenum <= 1) {
+                       sizes[4 + (sidenum*2)] = window.y;
+                       sizes[5 + (sidenum*2)] = window.y + window.height;
+               } else if (sidenum <= 3) {
+                       sizes[4 + (sidenum*2)] = window.x;
+                       sizes[5 + (sidenum*2)] = window.x + window.width;
+               }
+
+               /* check constraints */
+               for (i = 0; i < 12; i++) {
+                       if (sizes[i] < 0) {
+                               sizes[i] = 0;
+                       } else {
+                               if (i <= 1 || i >= 8) {
+                                       if (sizes[i] > display_width) {
+                                               sizes[i] = display_width;
+                                       }
+                               } else {
+                                       if (sizes[i] > display_height) {
+                                               sizes[i] = display_height;
+                                       }
+                               }
+                       }
+               }
+
+               XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
+                               PropModeReplace, (unsigned char *) &sizes, 4);
+
+               if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) {
+                       XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
+                                       PropModeReplace, (unsigned char *) &sizes, 12);
+               }
+       }
+}