]> Dogcows Code - chaz/openbox/blobdiff - openbox/screen.c
using the ObMainLoop, which rulz the planet
[chaz/openbox] / openbox / screen.c
index 75cc3c4c3cbe02887fa79c4db6e90f9edc9f4bae..7913770c2b133abcfa7a56cb24b7be5b888035f0 100644 (file)
@@ -1,15 +1,17 @@
+#include "debug.h"
 #include "openbox.h"
 #include "openbox.h"
+#include "mainloop.h"
 #include "dock.h"
 #include "xerror.h"
 #include "prop.h"
 #include "startup.h"
 #include "dock.h"
 #include "xerror.h"
 #include "prop.h"
 #include "startup.h"
-#include "timer.h"
+#include "grab.h"
 #include "config.h"
 #include "screen.h"
 #include "client.h"
 #include "frame.h"
 #include "focus.h"
 #include "config.h"
 #include "screen.h"
 #include "client.h"
 #include "frame.h"
 #include "focus.h"
-#include "dispatch.h"
+#include "popup.h"
 #include "extensions.h"
 #include "render/render.h"
 
 #include "extensions.h"
 #include "render/render.h"
 
@@ -23,6 +25,7 @@
 #  include <sys/types.h>
 #  include <unistd.h>
 #endif
 #  include <sys/types.h>
 #  include <unistd.h>
 #endif
+#include <assert.h>
 
 /*! The event mask to grab on the root window */
 #define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
 
 /*! The event mask to grab on the root window */
 #define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
                        SubstructureNotifyMask | SubstructureRedirectMask | \
                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
 
                        SubstructureNotifyMask | SubstructureRedirectMask | \
                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
 
-guint    screen_num_desktops    = 0;
-guint    screen_num_monitors    = 0;
-guint    screen_desktop         = 0;
+guint    screen_num_desktops;
+guint    screen_num_monitors;
+guint    screen_desktop;
 Size     screen_physical_size;
 gboolean screen_showing_desktop;
 DesktopLayout screen_desktop_layout;
 Size     screen_physical_size;
 gboolean screen_showing_desktop;
 DesktopLayout screen_desktop_layout;
-char   **screen_desktop_names = NULL;
+char   **screen_desktop_names;
+Window   screen_support_win;
 
 
-static Rect  **area = NULL; /* array of desktop holding array of
-                               xinerama areas */
-static Rect  *monitor_area = NULL;
-static Window support_window = None;
+static Rect  **area; /* array of desktop holding array of xinerama areas */
+static Rect  *monitor_area;
+
+static Popup *desktop_cycle_popup;
 
 #ifdef USE_LIBSN
 static SnMonitorContext *sn_context;
 static int sn_busy_cnt;
 
 #ifdef USE_LIBSN
 static SnMonitorContext *sn_context;
 static int sn_busy_cnt;
-static Timer *sn_timer = NULL;
 
 static void sn_event_func(SnMonitorEvent *event, void *data);
 #endif
 
 static void set_root_cursor();
 
 
 static void sn_event_func(SnMonitorEvent *event, void *data);
 #endif
 
 static void set_root_cursor();
 
-static gboolean running;
-static int another_running(Display *d, XErrorEvent *e)
+static gboolean replace_wm()
 {
 {
-    (void)d;(void)e;
-    g_message("A window manager is already running on screen %d",
-             ob_screen);
-    running = TRUE;
-    return -1;
+    char *wm_sn;
+    Atom wm_sn_atom;
+    Window current_wm_sn_owner;
+    Time timestamp;
+
+    wm_sn = g_strdup_printf("WM_S%d", ob_screen);
+    wm_sn_atom = XInternAtom(ob_display, wm_sn, FALSE);
+    g_free(wm_sn);
+
+    current_wm_sn_owner = XGetSelectionOwner(ob_display, wm_sn_atom);
+    if (current_wm_sn_owner) {
+        if (!ob_replace_wm) {
+            g_warning("A window manager is already running on screen %d",
+                      ob_screen);
+            return FALSE;
+        }
+        xerror_set_ignore(TRUE);
+        xerror_occured = FALSE;
+
+        /* We want to find out when the current selection owner dies */
+        XSelectInput(ob_display, current_wm_sn_owner, StructureNotifyMask);
+        XSync(ob_display, FALSE);
+
+        xerror_set_ignore(FALSE);
+        if (xerror_occured)
+            current_wm_sn_owner = None;
+    }
+
+    {
+        /* Generate a timestamp */
+        XEvent event;
+
+        XSelectInput(ob_display, screen_support_win, PropertyChangeMask);
+
+        XChangeProperty(ob_display, screen_support_win,
+                        prop_atoms.wm_class, prop_atoms.string,
+                        8, PropModeAppend, NULL, 0);
+        XWindowEvent(ob_display, screen_support_win,
+                     PropertyChangeMask, &event);
+
+        XSelectInput(ob_display, screen_support_win, NoEventMask);
+
+        timestamp = event.xproperty.time;
+    }
+
+    XSetSelectionOwner(ob_display, wm_sn_atom, screen_support_win,
+                       timestamp);
+
+    if (XGetSelectionOwner(ob_display, wm_sn_atom) != screen_support_win) {
+        g_warning("Could not acquire window manager selection on screen %d",
+                  ob_screen);
+        return FALSE;
+    }
+
+    /* Wait for old window manager to go away */
+    if (current_wm_sn_owner) {
+      XEvent event;
+      gulong wait = 0;
+      const gulong timeout = G_USEC_PER_SEC * 15; /* wait for 15s max */
+
+      while (wait < timeout) {
+          if (XCheckWindowEvent(ob_display, current_wm_sn_owner,
+                                StructureNotifyMask, &event) &&
+              event.type == DestroyNotify)
+              break;
+          g_usleep(G_USEC_PER_SEC / 10);
+          wait += G_USEC_PER_SEC / 10;
+      }
+
+      if (wait >= timeout) {
+          g_warning("Timeout expired while waiting for the current WM to die "
+                    "on screen %d", ob_screen);
+          return FALSE;
+      }
+    }
+
+    /* Send client message indicating that we are now the WM */
+    prop_message(RootWindow(ob_display, ob_screen), prop_atoms.manager,
+                 timestamp, wm_sn_atom, 0, 0, SubstructureNotifyMask);
+
+
+    return TRUE;
 }
 
 gboolean screen_annex()
 {
 }
 
 gboolean screen_annex()
 {
-    XErrorHandler old;
+    XSetWindowAttributes attrib;
     pid_t pid;
     pid_t pid;
-    int i, num_support;
+    gint i, num_support;
     guint32 *supported;
 
     guint32 *supported;
 
-    running = FALSE;
-    old = XSetErrorHandler(another_running);
-    XSelectInput(ob_display, ob_root, ROOT_EVENTMASK);
-    XSync(ob_display, FALSE);
-    XSetErrorHandler(old);
-    if (running)
+    /* create the netwm support window */
+    attrib.override_redirect = TRUE;
+    screen_support_win = XCreateWindow(ob_display,
+                                       RootWindow(ob_display, ob_screen),
+                                       -100, -100, 1, 1, 0,
+                                       CopyFromParent, InputOutput,
+                                       CopyFromParent,
+                                       CWOverrideRedirect, &attrib);
+    XMapRaised(ob_display, screen_support_win);
+
+    if (!replace_wm()) {
+        XDestroyWindow(ob_display, screen_support_win);
+        return FALSE;
+    }
+
+    xerror_set_ignore(TRUE);
+    xerror_occured = FALSE;
+    XSelectInput(ob_display, RootWindow(ob_display, ob_screen),
+                 ROOT_EVENTMASK);
+    xerror_set_ignore(FALSE);
+    if (xerror_occured) {
+        g_warning("A window manager is already running on screen %d",
+                  ob_screen);
+
+        XDestroyWindow(ob_display, screen_support_win);
        return FALSE;
        return FALSE;
+    }
 
 
-    g_message("Managing screen %d", ob_screen);
 
     set_root_cursor();
 
     /* set the OPENBOX_PID hint */
     pid = getpid();
 
     set_root_cursor();
 
     /* set the OPENBOX_PID hint */
     pid = getpid();
-    PROP_SET32(ob_root, openbox_pid, cardinal, pid);
-
-    /* create the netwm support window */
-    support_window = XCreateSimpleWindow(ob_display, ob_root, 0,0,1,1,0,0,0);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               openbox_pid, cardinal, pid);
 
     /* set supporting window */
 
     /* set supporting window */
-    PROP_SET32(ob_root, net_supporting_wm_check, window, support_window);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_supporting_wm_check, window, screen_support_win);
 
     /* set properties on the supporting window */
 
     /* set properties on the supporting window */
-    PROP_SETS(support_window, net_wm_name, "Openbox");
-    PROP_SET32(support_window, net_supporting_wm_check, window,support_window);
+    PROP_SETS(screen_support_win, net_wm_name, "Openbox");
+    PROP_SET32(screen_support_win, net_supporting_wm_check,
+               window, screen_support_win);
 
     /* set the _NET_SUPPORTED_ATOMS hint */
 
     /* set the _NET_SUPPORTED_ATOMS hint */
-    num_support = 61;
+    num_support = 50;
     i = 0;
     supported = g_new(guint32, num_support);
     supported[i++] = prop_atoms.net_current_desktop;
     i = 0;
     supported = g_new(guint32, num_support);
     supported[i++] = prop_atoms.net_current_desktop;
@@ -150,23 +248,13 @@ gboolean screen_annex()
     supported[i++] = prop_atoms.net_wm_state_below;
     supported[i++] = prop_atoms.net_moveresize_window;
     supported[i++] = prop_atoms.net_wm_moveresize;
     supported[i++] = prop_atoms.net_wm_state_below;
     supported[i++] = prop_atoms.net_moveresize_window;
     supported[i++] = prop_atoms.net_wm_moveresize;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_topleft;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_top;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_topright;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_right;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_bottomright;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_bottom;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_bottomleft;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_left;
-    supported[i++] = prop_atoms.net_wm_moveresize_move;
-    supported[i++] = prop_atoms.net_wm_moveresize_size_keyboard;
-    supported[i++] = prop_atoms.net_wm_moveresize_move_keyboard;
     g_assert(i == num_support);
 /*
   supported[] = prop_atoms.net_wm_action_stick;
 */
 
     g_assert(i == num_support);
 /*
   supported[] = prop_atoms.net_wm_action_stick;
 */
 
-    PROP_SETA32(ob_root, net_supported, atom, supported, num_support);
+    PROP_SETA32(RootWindow(ob_display, ob_screen),
+                net_supported, atom, supported, num_support);
     g_free(supported);
 
     return TRUE;
     g_free(supported);
 
     return TRUE;
@@ -177,6 +265,8 @@ void screen_startup()
     GSList *it;
     guint i;
 
     GSList *it;
     guint i;
 
+    desktop_cycle_popup = popup_new(FALSE);
+
     /* get the initial size */
     screen_resize();
 
     /* get the initial size */
     screen_resize();
 
@@ -186,7 +276,8 @@ void screen_startup()
     for (i = 0, it = config_desktops_names; it; ++i, it = it->next)
         screen_desktop_names[i] = it->data; /* dont strdup */
     screen_desktop_names[i] = NULL;
     for (i = 0, it = config_desktops_names; it; ++i, it = it->next)
         screen_desktop_names[i] = it->data; /* dont strdup */
     screen_desktop_names[i] = NULL;
-    PROP_SETSS(ob_root, net_desktop_names, screen_desktop_names);
+    PROP_SETSS(RootWindow(ob_display, ob_screen),
+               net_desktop_names, screen_desktop_names);
     g_free(screen_desktop_names); /* dont free the individual strings */
     screen_desktop_names = NULL;
 
     g_free(screen_desktop_names); /* dont free the individual strings */
     screen_desktop_names = NULL;
 
@@ -199,7 +290,8 @@ void screen_startup()
 
     /* don't start in showing-desktop mode */
     screen_showing_desktop = FALSE;
 
     /* don't start in showing-desktop mode */
     screen_showing_desktop = FALSE;
-    PROP_SET32(ob_root, net_showing_desktop, cardinal, screen_showing_desktop);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_showing_desktop, cardinal, screen_showing_desktop);
 
     screen_update_layout();
 
 
     screen_update_layout();
 
@@ -214,13 +306,18 @@ void screen_shutdown()
 {
     Rect **r;
 
 {
     Rect **r;
 
-    XSelectInput(ob_display, ob_root, NoEventMask);
+    popup_free(desktop_cycle_popup);
+
+    XSelectInput(ob_display, RootWindow(ob_display, ob_screen), NoEventMask);
 
 
-    PROP_ERASE(ob_root, openbox_pid); /* we're not running here no more! */
-    PROP_ERASE(ob_root, net_supported); /* not without us */
-    PROP_ERASE(ob_root, net_showing_desktop); /* don't keep this mode */
+    /* we're not running here no more! */
+    PROP_ERASE(RootWindow(ob_display, ob_screen), openbox_pid);
+    /* not without us */
+    PROP_ERASE(RootWindow(ob_display, ob_screen), net_supported);
+    /* don't keep this mode */
+    PROP_ERASE(RootWindow(ob_display, ob_screen), net_showing_desktop);
 
 
-    XDestroyWindow(ob_display, support_window);
+    XDestroyWindow(ob_display, screen_support_win);
 
     g_strfreev(screen_desktop_names);
     for (r = area; *r; ++r)
 
     g_strfreev(screen_desktop_names);
     for (r = area; *r; ++r)
@@ -245,16 +342,17 @@ void screen_resize()
     /* Set the _NET_DESKTOP_GEOMETRY hint */
     screen_physical_size.width = geometry[0] = w;
     screen_physical_size.height = geometry[1] = h;
     /* Set the _NET_DESKTOP_GEOMETRY hint */
     screen_physical_size.width = geometry[0] = w;
     screen_physical_size.height = geometry[1] = h;
-    PROP_SETA32(ob_root, net_desktop_geometry, cardinal, geometry, 2);
+    PROP_SETA32(RootWindow(ob_display, ob_screen),
+                net_desktop_geometry, cardinal, geometry, 2);
 
 
-    if (ob_state == State_Starting)
+    if (ob_state() == OB_STATE_STARTING)
        return;
 
        return;
 
-    dock_configure();
     screen_update_areas();
     screen_update_areas();
+    dock_configure();
 
     for (it = client_list; it; it = it->next)
 
     for (it = client_list; it; it = it->next)
-        client_move_onscreen(it->data);
+        client_move_onscreen(it->data, FALSE);
 }
 
 void screen_set_num_desktops(guint num)
 }
 
 void screen_set_num_desktops(guint num)
@@ -267,11 +365,13 @@ void screen_set_num_desktops(guint num)
 
     old = screen_num_desktops;
     screen_num_desktops = num;
 
     old = screen_num_desktops;
     screen_num_desktops = num;
-    PROP_SET32(ob_root, net_number_of_desktops, cardinal, num);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_number_of_desktops, cardinal, num);
 
     /* set the viewport hint */
     viewport = g_new0(guint32, num * 2);
 
     /* set the viewport hint */
     viewport = g_new0(guint32, num * 2);
-    PROP_SETA32(ob_root, net_desktop_viewport, cardinal, viewport, num * 2);
+    PROP_SETA32(RootWindow(ob_display, ob_screen),
+                net_desktop_viewport, cardinal, viewport, num * 2);
     g_free(viewport);
 
     /* the number of rows/columns will differ */
     g_free(viewport);
 
     /* the number of rows/columns will differ */
@@ -292,7 +392,7 @@ void screen_set_num_desktops(guint num)
 
     /* move windows on desktops that will no longer exist! */
     for (it = client_list; it != NULL; it = it->next) {
 
     /* move windows on desktops that will no longer exist! */
     for (it = client_list; it != NULL; it = it->next) {
-        Client *c = it->data;
+        ObClient *c = it->data;
         if (c->desktop >= num && c->desktop != DESKTOP_ALL)
             client_set_desktop(c, num - 1, FALSE);
     }
         if (c->desktop >= num && c->desktop != DESKTOP_ALL)
             client_set_desktop(c, num - 1, FALSE);
     }
@@ -300,8 +400,6 @@ void screen_set_num_desktops(guint num)
     /* change our struts/area to match (after moving windows) */
     screen_update_areas();
 
     /* change our struts/area to match (after moving windows) */
     screen_update_areas();
 
-    dispatch_ob(Event_Ob_NumDesktops, num, old);
-
     /* change our desktop if we're on one that no longer exists! */
     if (screen_desktop >= screen_num_desktops)
        screen_set_desktop(num - 1);
     /* change our desktop if we're on one that no longer exists! */
     if (screen_desktop >= screen_num_desktops)
        screen_set_desktop(num - 1);
@@ -317,18 +415,19 @@ void screen_set_desktop(guint num)
 
     old = screen_desktop;
     screen_desktop = num;
 
     old = screen_desktop;
     screen_desktop = num;
-    PROP_SET32(ob_root, net_current_desktop, cardinal, num);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_current_desktop, cardinal, num);
 
     if (old == num) return;
 
 
     if (old == num) return;
 
-    g_message("Moving to desktop %d", num+1);
+    ob_debug("Moving to desktop %d\n", num+1);
 
     /* show windows before hiding the rest to lessen the enter/leave events */
 
     /* show windows from top to bottom */
     for (it = stacking_list; it != NULL; it = it->next) {
         if (WINDOW_IS_CLIENT(it->data)) {
 
     /* show windows before hiding the rest to lessen the enter/leave events */
 
     /* show windows from top to bottom */
     for (it = stacking_list; it != NULL; it = it->next) {
         if (WINDOW_IS_CLIENT(it->data)) {
-            Client *c = it->data;
+            ObClient *c = it->data;
             if (!c->frame->visible && client_should_show(c))
                 frame_show(c->frame);
         }
             if (!c->frame->visible && client_should_show(c))
                 frame_show(c->frame);
         }
@@ -337,7 +436,7 @@ void screen_set_desktop(guint num)
     /* hide windows from bottom to top */
     for (it = g_list_last(stacking_list); it != NULL; it = it->prev) {
         if (WINDOW_IS_CLIENT(it->data)) {
     /* hide windows from bottom to top */
     for (it = g_list_last(stacking_list); it != NULL; it = it->prev) {
         if (WINDOW_IS_CLIENT(it->data)) {
-            Client *c = it->data;
+            ObClient *c = it->data;
             if (c->frame->visible && !client_should_show(c))
                 frame_hide(c->frame);
         }
             if (c->frame->visible && !client_should_show(c))
                 frame_hide(c->frame);
         }
@@ -346,42 +445,297 @@ void screen_set_desktop(guint num)
     /* focus the last focused window on the desktop, and ignore enter events
        from the switch so it doesnt mess with the focus */
     while (XCheckTypedEvent(ob_display, EnterNotify, &e));
     /* focus the last focused window on the desktop, and ignore enter events
        from the switch so it doesnt mess with the focus */
     while (XCheckTypedEvent(ob_display, EnterNotify, &e));
-    g_message("switch fallback");
-    focus_fallback(Fallback_Desktop);
-    g_message("/switch fallback");
+#ifdef DEBUG_FOCUS
+    ob_debug("switch fallback\n");
+#endif
+    focus_fallback(OB_FOCUS_FALLBACK_DESKTOP);
+#ifdef DEBUG_FOCUS
+    ob_debug("/switch fallback\n");
+#endif
+}
+
+static void get_row_col(guint d, guint *r, guint *c)
+{
+    switch (screen_desktop_layout.orientation) {
+    case OB_ORIENTATION_HORZ:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            *r = d / screen_desktop_layout.columns;
+            *c = d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_BOTTOMLEFT:
+            *r = screen_desktop_layout.rows - 1 -
+                d / screen_desktop_layout.columns;
+            *c = d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_TOPRIGHT:
+            *r = d / screen_desktop_layout.columns;
+            *c = screen_desktop_layout.columns - 1 -
+                d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_BOTTOMRIGHT:
+            *r = screen_desktop_layout.rows - 1 -
+                d / screen_desktop_layout.columns;
+            *c = screen_desktop_layout.columns - 1 -
+                d % screen_desktop_layout.columns;
+            break;
+        }
+        break;
+    case OB_ORIENTATION_VERT:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            *r = d % screen_desktop_layout.rows;
+            *c = d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_BOTTOMLEFT:
+            *r = screen_desktop_layout.rows - 1 -
+                d % screen_desktop_layout.rows;
+            *c = d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_TOPRIGHT:
+            *r = d % screen_desktop_layout.rows;
+            *c = screen_desktop_layout.columns - 1 -
+                d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_BOTTOMRIGHT:
+            *r = screen_desktop_layout.rows - 1 -
+                d % screen_desktop_layout.rows;
+            *c = screen_desktop_layout.columns - 1 -
+                d / screen_desktop_layout.rows;
+            break;
+        }
+        break;
+    }
+}
+
+static guint translate_row_col(guint r, guint c)
+{
+    switch (screen_desktop_layout.orientation) {
+    case OB_ORIENTATION_HORZ:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            return r % screen_desktop_layout.rows *
+                screen_desktop_layout.columns +
+                c % screen_desktop_layout.columns;
+        case OB_CORNER_BOTTOMLEFT:
+            return (screen_desktop_layout.rows - 1 -
+                    r % screen_desktop_layout.rows) *
+                screen_desktop_layout.columns +
+                c % screen_desktop_layout.columns;
+        case OB_CORNER_TOPRIGHT:
+            return r % screen_desktop_layout.rows *
+                screen_desktop_layout.columns +
+                (screen_desktop_layout.columns - 1 -
+                 c % screen_desktop_layout.columns);
+        case OB_CORNER_BOTTOMRIGHT:
+            return (screen_desktop_layout.rows - 1 -
+                    r % screen_desktop_layout.rows) *
+                screen_desktop_layout.columns +
+                (screen_desktop_layout.columns - 1 -
+                 c % screen_desktop_layout.columns);
+        }
+    case OB_ORIENTATION_VERT:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            return c % screen_desktop_layout.columns *
+                screen_desktop_layout.rows +
+                r % screen_desktop_layout.rows;
+        case OB_CORNER_BOTTOMLEFT:
+            return c % screen_desktop_layout.columns *
+                screen_desktop_layout.rows +
+                (screen_desktop_layout.rows - 1 -
+                 r % screen_desktop_layout.rows);
+        case OB_CORNER_TOPRIGHT:
+            return (screen_desktop_layout.columns - 1 -
+                    c % screen_desktop_layout.columns) *
+                screen_desktop_layout.rows +
+                r % screen_desktop_layout.rows;
+        case OB_CORNER_BOTTOMRIGHT:
+            return (screen_desktop_layout.columns - 1 -
+                    c % screen_desktop_layout.columns) *
+                screen_desktop_layout.rows +
+                (screen_desktop_layout.rows - 1 -
+                 r % screen_desktop_layout.rows);
+        }
+    }
+    g_assert_not_reached();
+    return 0;
+}
+
+static void popup_cycle(guint d, gboolean show)
+{
+    Rect *a;
+
+    if (!show) {
+        popup_hide(desktop_cycle_popup);
+    } else {
+        a = screen_physical_area_monitor(0);
+        popup_position(desktop_cycle_popup, CenterGravity,
+                       a->x + a->width / 2, a->y + a->height / 2);
+        /* XXX the size and the font extents need to be related on some level
+         */
+        popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
 
 
-    dispatch_ob(Event_Ob_Desktop, num, old);
+        popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
+
+        popup_show(desktop_cycle_popup,
+                   screen_desktop_names[d], NULL);
+    }
+}
+
+guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
+                           gboolean done, gboolean cancel)
+{
+    static gboolean first = TRUE;
+    static gboolean lin;
+    static guint origd, d;
+    guint r, c;
+
+    if (cancel) {
+        d = origd;
+        goto done_cycle;
+    } else if (done) {
+        screen_set_desktop(d);
+        goto done_cycle;
+    }
+    if (first) {
+        first = FALSE;
+        lin = linear;
+        d = origd = screen_desktop;
+    }
+
+    get_row_col(d, &r, &c);
+
+    if (lin) {
+        switch (dir) {
+        case OB_DIRECTION_EAST:
+            if (d < screen_num_desktops - 1)
+                ++d;
+            else if (wrap)
+                d = 0;
+            break;
+        case OB_DIRECTION_WEST:
+            if (d > 0)
+                --d;
+            else if (wrap)
+                d = screen_num_desktops - 1;
+            break;
+        default:
+            assert(0);
+            return screen_desktop;
+        }
+    } else {
+        switch (dir) {
+        case OB_DIRECTION_EAST:
+            ++c;
+            if (c >= screen_desktop_layout.columns) {
+                if (!wrap) return d = screen_desktop;
+                c = 0;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                ++c;
+            }
+            break;
+        case OB_DIRECTION_WEST:
+            --c;
+            if (c >= screen_desktop_layout.columns) {
+                if (!wrap) return d = screen_desktop;
+                c = screen_desktop_layout.columns - 1;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                --c;
+            }
+            break;
+        case OB_DIRECTION_SOUTH:
+            ++r;
+            if (r >= screen_desktop_layout.rows) {
+                if (!wrap) return d = screen_desktop;
+                r = 0;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                ++r;
+            }
+            break;
+        case OB_DIRECTION_NORTH:
+            --r;
+            if (r >= screen_desktop_layout.rows) {
+                if (!wrap) return d = screen_desktop;
+                r = screen_desktop_layout.rows - 1;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                --r;
+            }
+            break;
+        default:
+            assert(0);
+            return d = screen_desktop;
+        }
+
+        d = translate_row_col(r, c);
+    }
+
+    if (config_desktop_popup) {
+        popup_cycle(d, TRUE);
+        return d;
+    }
+
+done_cycle:
+    first = TRUE;
+
+    popup_cycle(0, FALSE);
+
+    return d;
 }
 
 void screen_update_layout()
 {
 }
 
 void screen_update_layout()
 {
-    guint32 *data = NULL;
+    ObOrientation orient;
+    ObCorner corner;
+    guint rows;
+    guint cols;
+    guint32 *data;
     guint num;
     guint num;
+    gboolean valid = FALSE;
 
 
-    /* defaults */
-    screen_desktop_layout.orientation = prop_atoms.net_wm_orientation_horz;
-    screen_desktop_layout.start_corner = prop_atoms.net_wm_topleft;
-    screen_desktop_layout.rows = 1;
-    screen_desktop_layout.columns = screen_num_desktops;
-
-    if (PROP_GETA32(ob_root, net_desktop_layout, cardinal, &data, &num)) {
+    if (PROP_GETA32(RootWindow(ob_display, ob_screen),
+                    net_desktop_layout, cardinal, &data, &num)) {
         if (num == 3 || num == 4) {
         if (num == 3 || num == 4) {
+
             if (data[0] == prop_atoms.net_wm_orientation_vert)
             if (data[0] == prop_atoms.net_wm_orientation_vert)
-                screen_desktop_layout.orientation = data[0];
-            if (num == 3)
-                screen_desktop_layout.start_corner =
-                    prop_atoms.net_wm_topright;
+                orient = OB_ORIENTATION_VERT;
+            else if (data[0] == prop_atoms.net_wm_orientation_horz)
+                orient = OB_ORIENTATION_HORZ;
+            else
+                goto screen_update_layout_bail;
+
+            if (num < 4)
+                corner = OB_CORNER_TOPLEFT;
             else {
             else {
-                if (data[3] == prop_atoms.net_wm_topright)
-                    screen_desktop_layout.start_corner = data[3];
+                if (data[3] == prop_atoms.net_wm_topleft)
+                    corner = OB_CORNER_TOPLEFT;
+                else if (data[3] == prop_atoms.net_wm_topright)
+                    corner = OB_CORNER_TOPRIGHT;
                 else if (data[3] == prop_atoms.net_wm_bottomright)
                 else if (data[3] == prop_atoms.net_wm_bottomright)
-                    screen_desktop_layout.start_corner = data[3];
+                    corner = OB_CORNER_BOTTOMRIGHT;
                 else if (data[3] == prop_atoms.net_wm_bottomleft)
                 else if (data[3] == prop_atoms.net_wm_bottomleft)
-                    screen_desktop_layout.start_corner = data[3];
+                    corner = OB_CORNER_BOTTOMLEFT;
+                else
+                    goto screen_update_layout_bail;
             }
 
             /* fill in a zero rows/columns */
             }
 
             /* fill in a zero rows/columns */
-            if (!(data[1] == 0 && data[2] == 0)) { /* both 0's is bad data.. */
+            if ((data[1] == 0 && data[2] == 0) || /* both 0's is bad data.. */
+                (data[1] != 0 && data[2] != 0)) { /* no 0's is bad data.. */
+                goto screen_update_layout_bail;
+            } else {
                 if (data[1] == 0) {
                     data[1] = (screen_num_desktops +
                                screen_num_desktops % data[2]) / data[2];
                 if (data[1] == 0) {
                     data[1] = (screen_num_desktops +
                                screen_num_desktops % data[2]) / data[2];
@@ -389,38 +743,39 @@ void screen_update_layout()
                     data[2] = (screen_num_desktops +
                                screen_num_desktops % data[1]) / data[1];
                 }
                     data[2] = (screen_num_desktops +
                                screen_num_desktops % data[1]) / data[1];
                 }
-                screen_desktop_layout.columns = data[1];
-                screen_desktop_layout.rows = data[2];
+                cols = data[1];
+                rows = data[2];
             }
 
             /* bounds checking */
             }
 
             /* bounds checking */
-            if (screen_desktop_layout.orientation ==
-                prop_atoms.net_wm_orientation_horz) {
-                if (screen_desktop_layout.rows > screen_num_desktops)
-                    screen_desktop_layout.rows = screen_num_desktops;
-                if (screen_desktop_layout.columns >
-                    ((screen_num_desktops + screen_num_desktops %
-                      screen_desktop_layout.rows) /
-                     screen_desktop_layout.rows))
-                    screen_desktop_layout.columns =
-                        (screen_num_desktops + screen_num_desktops %
-                         screen_desktop_layout.rows) /
-                        screen_desktop_layout.rows;
+            if (orient == OB_ORIENTATION_HORZ) {
+                rows = MIN(rows, screen_num_desktops);
+                cols = MIN(cols, ((screen_num_desktops +
+                                     (screen_num_desktops % rows)) / rows));
             } else {
             } else {
-                if (screen_desktop_layout.columns > screen_num_desktops)
-                    screen_desktop_layout.columns = screen_num_desktops;
-                if (screen_desktop_layout.rows >
-                    ((screen_num_desktops + screen_num_desktops %
-                      screen_desktop_layout.columns) /
-                     screen_desktop_layout.columns))
-                    screen_desktop_layout.rows =
-                        (screen_num_desktops + screen_num_desktops %
-                         screen_desktop_layout.columns) /
-                        screen_desktop_layout.columns;
+                cols = MIN(cols, screen_num_desktops);
+                rows = MIN(rows, ((screen_num_desktops +
+                                     (screen_num_desktops % cols)) / cols));
             }
             }
+
+            valid = TRUE;
         }
         }
-       g_free(data);
+    screen_update_layout_bail:
+        g_free(data);
     }
     }
+
+    if (!valid) {
+        /* defaults */
+        orient = OB_ORIENTATION_HORZ;
+        corner = OB_CORNER_TOPLEFT;
+        rows = 1;
+        cols = screen_num_desktops;
+    }
+
+    screen_desktop_layout.orientation = orient;
+    screen_desktop_layout.start_corner = corner;
+    screen_desktop_layout.rows = rows;
+    screen_desktop_layout.columns = cols;
 }
 
 void screen_update_desktop_names()
 }
 
 void screen_update_desktop_names()
@@ -431,7 +786,8 @@ void screen_update_desktop_names()
     g_strfreev(screen_desktop_names);
     screen_desktop_names = NULL;
 
     g_strfreev(screen_desktop_names);
     screen_desktop_names = NULL;
 
-    if (PROP_GETSS(ob_root, net_desktop_names, utf8, &screen_desktop_names))
+    if (PROP_GETSS(RootWindow(ob_display, ob_screen),
+                   net_desktop_names, utf8, &screen_desktop_names))
         for (i = 0; screen_desktop_names[i] && i <= screen_num_desktops; ++i);
     else
         i = 0;
         for (i = 0; screen_desktop_names[i] && i <= screen_num_desktops; ++i);
     else
         i = 0;
@@ -456,7 +812,7 @@ void screen_show_desktop(gboolean show)
        /* bottom to top */
        for (it = g_list_last(stacking_list); it != NULL; it = it->prev) {
             if (WINDOW_IS_CLIENT(it->data)) {
        /* bottom to top */
        for (it = g_list_last(stacking_list); it != NULL; it = it->prev) {
             if (WINDOW_IS_CLIENT(it->data)) {
-                Client *client = it->data;
+                ObClient *client = it->data;
                 if (client->frame->visible && !client_should_show(client))
                     frame_hide(client->frame);
             }
                 if (client->frame->visible && !client_should_show(client))
                     frame_hide(client->frame);
             }
@@ -465,7 +821,7 @@ void screen_show_desktop(gboolean show)
         /* top to bottom */
        for (it = stacking_list; it != NULL; it = it->next) {
             if (WINDOW_IS_CLIENT(it->data)) {
         /* top to bottom */
        for (it = stacking_list; it != NULL; it = it->next) {
             if (WINDOW_IS_CLIENT(it->data)) {
-                Client *client = it->data;
+                ObClient *client = it->data;
                 if (!client->frame->visible && client_should_show(client))
                     frame_show(client->frame);
             }
                 if (!client->frame->visible && client_should_show(client))
                     frame_show(client->frame);
             }
@@ -475,20 +831,19 @@ void screen_show_desktop(gboolean show)
     if (show) {
         /* focus desktop */
         for (it = focus_order[screen_desktop]; it; it = it->next)
     if (show) {
         /* focus desktop */
         for (it = focus_order[screen_desktop]; it; it = it->next)
-            if (((Client*)it->data)->type == Type_Desktop &&
+            if (((ObClient*)it->data)->type == OB_CLIENT_TYPE_DESKTOP &&
                 client_focus(it->data))
                 break;
     } else {
                 client_focus(it->data))
                 break;
     } else {
-        focus_fallback(Fallback_NoFocus);
+        focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
     }
 
     show = !!show; /* make it boolean */
     }
 
     show = !!show; /* make it boolean */
-    PROP_SET32(ob_root, net_showing_desktop, cardinal, show);
-
-    dispatch_ob(Event_Ob_ShowDesktop, show, 0);
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_showing_desktop, cardinal, show);
 }
 
 }
 
-void screen_install_colormap(Client *client, gboolean install)
+void screen_install_colormap(ObClient *client, gboolean install)
 {
     XWindowAttributes wa;
 
 {
     XWindowAttributes wa;
 
@@ -514,8 +869,6 @@ void screen_update_areas()
 {
     guint i, x;
     guint32 *dims;
 {
     guint i, x;
     guint32 *dims;
-    Rect **old_area = area;
-    Rect **rit;
     GList *it;
 
     g_free(monitor_area);
     GList *it;
 
     g_free(monitor_area);
@@ -534,7 +887,6 @@ void screen_update_areas()
      
     dims = g_new(guint32, 4 * screen_num_desktops);
 
      
     dims = g_new(guint32, 4 * screen_num_desktops);
 
-    rit = old_area;
     for (i = 0; i < screen_num_desktops + 1; ++i) {
         Strut s;
         int l, r, t, b;
     for (i = 0; i < screen_num_desktops + 1; ++i) {
         Strut s;
         int l, r, t, b;
@@ -559,7 +911,7 @@ void screen_update_areas()
         /* apply struts */
         STRUT_SET(s, 0, 0, 0, 0);
         for (it = client_list; it; it = it->next)
         /* apply struts */
         STRUT_SET(s, 0, 0, 0, 0);
         for (it = client_list; it; it = it->next)
-            STRUT_ADD(s, ((Client*)it->data)->strut);
+            STRUT_ADD(s, ((ObClient*)it->data)->strut);
         STRUT_ADD(s, dock_strut);
 
         if (s.left) {
         STRUT_ADD(s, dock_strut);
 
         if (s.left) {
@@ -648,7 +1000,7 @@ void screen_update_areas()
                 XXX if gunna test this shit, then gotta worry about when
                 the client moves between xinerama heads..
 
                 XXX if gunna test this shit, then gotta worry about when
                 the client moves between xinerama heads..
 
-                if (RECT_CONTAINS_RECT(((Client*)it->data)->frame->area,
+                if (RECT_CONTAINS_RECT(((ObClient*)it->data)->frame->area,
                                        area[i][x])) {
 
                 }            
                                        area[i][x])) {
 
                 }            
@@ -661,7 +1013,7 @@ void screen_update_areas()
         /* the area has changed, adjust all the maximized 
            windows */
         for (it = client_list; it; it = it->next) {
         /* the area has changed, adjust all the maximized 
            windows */
         for (it = client_list; it; it = it->next) {
-            Client *c = it->data; 
+            ObClient *c = it->data; 
             if (i < screen_num_desktops) {
                 if (c->desktop == i)
                     client_reconfigure(c);
             if (i < screen_num_desktops) {
                 if (c->desktop == i)
                     client_reconfigure(c);
@@ -676,8 +1028,8 @@ void screen_update_areas()
             dims[(i * 4) + 3] = area[i][screen_num_monitors].height;
         }
     }
             dims[(i * 4) + 3] = area[i][screen_num_monitors].height;
         }
     }
-    PROP_SETA32(ob_root, net_workarea, cardinal,
-               dims, 4 * screen_num_desktops);
+    PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
+                dims, 4 * screen_num_desktops);
 
     g_free(dims);
 }
 
     g_free(dims);
 }
@@ -715,20 +1067,22 @@ static void set_root_cursor()
 {
 #ifdef USE_LIBSN
         if (sn_busy_cnt)
 {
 #ifdef USE_LIBSN
         if (sn_busy_cnt)
-            XDefineCursor(ob_display, ob_root, ob_cursors.busy);
+            XDefineCursor(ob_display, RootWindow(ob_display, ob_screen),
+                          ob_cursor(OB_CURSOR_BUSY));
         else
 #endif
         else
 #endif
-            XDefineCursor(ob_display, ob_root, ob_cursors.ptr);
+            XDefineCursor(ob_display, RootWindow(ob_display, ob_screen),
+                          ob_cursor(OB_CURSOR_POINTER));
 }
 
 #ifdef USE_LIBSN
 }
 
 #ifdef USE_LIBSN
-static void sn_timeout(void *data)
+static gboolean sn_timeout(gpointer data)
 {
 {
-    timer_stop(sn_timer);
-    sn_timer = NULL;
     sn_busy_cnt = 0;
 
     set_root_cursor();
     sn_busy_cnt = 0;
 
     set_root_cursor();
+
+    return FALSE; /* don't repeat */
 }
 
 static void sn_event_func(SnMonitorEvent *ev, void *data)
 }
 
 static void sn_event_func(SnMonitorEvent *ev, void *data)
@@ -749,29 +1103,33 @@ static void sn_event_func(SnMonitorEvent *ev, void *data)
     switch (sn_monitor_event_get_type(ev)) {
     case SN_MONITOR_EVENT_INITIATED:
         ++sn_busy_cnt;
     switch (sn_monitor_event_get_type(ev)) {
     case SN_MONITOR_EVENT_INITIATED:
         ++sn_busy_cnt;
-        if (sn_timer)
-            timer_stop(sn_timer);
+        ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
         /* 30 second timeout for apps to start */
         /* 30 second timeout for apps to start */
-        sn_timer = timer_start(30 * 1000000, sn_timeout, NULL);
+        ob_main_loop_timeout_add(ob_main_loop, 30 * G_USEC_PER_SEC,
+                                 sn_timeout, NULL, NULL);
         break;
     case SN_MONITOR_EVENT_CHANGED:
         break;
     case SN_MONITOR_EVENT_COMPLETED:
         if (sn_busy_cnt) --sn_busy_cnt;
         break;
     case SN_MONITOR_EVENT_CHANGED:
         break;
     case SN_MONITOR_EVENT_COMPLETED:
         if (sn_busy_cnt) --sn_busy_cnt;
-        if (sn_timer) {
-            timer_stop(sn_timer);
-            sn_timer = NULL;
-        }
+        ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
         break;
     case SN_MONITOR_EVENT_CANCELED:
         if (sn_busy_cnt) --sn_busy_cnt;
         break;
     case SN_MONITOR_EVENT_CANCELED:
         if (sn_busy_cnt) --sn_busy_cnt;
-        if (sn_timer) {
-            timer_stop(sn_timer);
-            sn_timer = NULL;
-        }
+        ob_main_loop_timeout_remove(ob_main_loop, sn_timeout);
     };
 
     if (sn_busy_cnt != cnt)
         set_root_cursor();
 }
 #endif
     };
 
     if (sn_busy_cnt != cnt)
         set_root_cursor();
 }
 #endif
+
+gboolean screen_pointer_pos(int *x, int *y)
+{
+    Window w;
+    int i;
+    guint u;
+
+    return !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen),
+                           &w, &w, x, y, &i, &i, &u);
+}
This page took 0.046354 seconds and 4 git commands to generate.