merge r6183-6221 from trunk
authorDana Jansens <danakj@orodu.net>
Wed, 9 May 2007 18:04:16 +0000 (18:04 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 9 May 2007 18:04:16 +0000 (18:04 +0000)
32 files changed:
Makefile.am
data/rc.xml.in
data/rc.xsd
openbox/action.c
openbox/client.c
openbox/client.h
openbox/client_list_combined_menu.c
openbox/client_list_menu.c
openbox/client_menu.c
openbox/config.c
openbox/config.h
openbox/event.c
openbox/frame.c
openbox/frame.h
openbox/framerender.c
openbox/group.c
openbox/group.h
openbox/keyboard.c
openbox/menu.h
openbox/menuframe.c
openbox/menuframe.h
openbox/moveresize.c
openbox/moveresize.h
openbox/openbox.c
openbox/place.c
openbox/prop.c
openbox/prop.h
openbox/resist.c
openbox/resist.h
openbox/screen.c
openbox/screen.h
openbox/window.c

index 9269fb5022c09caefc4f7aa2559a495ddd27229f..84bf7523eb4ccd5bf4e1b559109b30f637454c7e 100644 (file)
@@ -201,6 +201,8 @@ openbox_openbox_SOURCES = \
        openbox/popup.h \
        openbox/prop.c \
        openbox/prop.h \
+       openbox/propwin.c \
+       openbox/propwin.h \
        openbox/resist.c \
        openbox/resist.h \
        openbox/screen.c \
index 35cc4cfb21ca1705c6eaa971fa6d448ba722a2b8..8ccf1cfacf1fd2e734700bb76160fd8c58e22f87 100644 (file)
@@ -42,7 +42,6 @@
       D: omnipresent (on all desktops).
   -->
   <keepBorder>yes</keepBorder>
-  <hideDisabled>no</hideDisabled>
   <animateIconify>yes</animateIconify>
   <font place="ActiveWindow">
     <name>sans</name>
index d3df567dbd541d04b900fcb817166b5e4fba6dce..af4eda4ab9279b7487728eb8e67e2167d14595c3 100644 (file)
         <xsd:element minOccurs="0" name="titleLayout" type="xsd:string"/>
         <xsd:element minOccurs="0" name="titleNumber" type="ob:bool"/>
         <xsd:element minOccurs="0" name="keepBorder" type="ob:bool"/>
-        <xsd:element minOccurs="0" name="hideDisabled" type="ob:bool"/>
         <xsd:element minOccurs="0" name="animateIconify" type="ob:bool"/>
         <xsd:element minOccurs="0" name="font" type="ob:font"/>
     </xsd:complexType>
index f8b2b7b3845175971043169876bd2b57fbcf7f63..24388dca7432314d6a299dfffe40a2abe23daaf7 100644 (file)
@@ -1199,10 +1199,9 @@ void action_execute(union ActionData *data)
 void action_activate(union ActionData *data)
 {
     if (data->client.any.c) {
-        /* similar to the openbox dock for dockapps, don't let user actions
-           give focus to 3rd-party docks (panels) either (unless they ask for
-           it themselves). */
-        if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) {
+        if (!data->any.button || client_mouse_focusable(data->client.any.c) ||
+            data->any.context != OB_FRAME_CONTEXT_CLIENT)
+        {
             /* if using focus_delay, stop the timer now so that focus doesn't
                go moving on us */
             event_halt_focus_delay();
@@ -1220,10 +1219,9 @@ void action_activate(union ActionData *data)
 void action_focus(union ActionData *data)
 {
     if (data->client.any.c) {
-        /* similar to the openbox dock for dockapps, don't let user actions
-           give focus to 3rd-party docks (panels) either (unless they ask for
-           it themselves). */
-        if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) {
+        if (!data->any.button || client_mouse_focusable(data->client.any.c) ||
+            data->any.context != OB_FRAME_CONTEXT_CLIENT)
+        {
             /* if using focus_delay, stop the timer now so that focus doesn't
                go moving on us */
             event_halt_focus_delay();
@@ -1523,11 +1521,6 @@ void action_send_to_desktop(union ActionData *data)
 
 void action_desktop(union ActionData *data)
 {
-    static guint first = (unsigned) -1;
-
-    if (data->inter.any.interactive && first == (unsigned) -1)
-        first = screen_desktop;
-
     if (!data->inter.any.interactive ||
         (!data->inter.cancel && !data->inter.final))
     {
@@ -1538,14 +1531,8 @@ void action_desktop(union ActionData *data)
             if (data->inter.any.interactive)
                 screen_desktop_popup(data->desktop.desk, TRUE);
         }
-    } else if (data->inter.cancel) {
-        screen_set_desktop(first, TRUE);
-    }
-
-    if (!data->inter.any.interactive || data->inter.final) {
+    } else
         screen_desktop_popup(0, FALSE);
-        first = (unsigned) -1;
-    }
 }
 
 void action_desktop_dir(union ActionData *data)
@@ -1562,7 +1549,7 @@ void action_desktop_dir(union ActionData *data)
         !data->sendtodir.inter.final ||
         data->sendtodir.inter.cancel)
     {
-        screen_set_desktop(d, TRUE);
+        if (d != screen_desktop) screen_set_desktop(d, TRUE);
     }
 }
 
@@ -1583,7 +1570,7 @@ void action_send_to_desktop_dir(union ActionData *data)
         data->sendtodir.inter.cancel)
     {
         client_set_desktop(c, d, data->sendtodir.follow);
-        if (data->sendtodir.follow)
+        if (data->sendtodir.follow && d != screen_desktop)
             screen_set_desktop(d, TRUE);
     }
 }
@@ -1702,8 +1689,6 @@ void action_moveresize(union ActionData *data)
     ObClient *c = data->moveresize.any.c;
     guint32 corner;
 
-    if (!client_normal(c)) return;
-
     if (data->moveresize.keyboard) {
         corner = (data->moveresize.move ?
                   prop_atoms.net_wm_moveresize_move_keyboard :
index e2b2636baa52101935b2ec8a105df60322f8169b..3f3f161de016c79126136d3eb84491f4d8a09a5a 100644 (file)
@@ -32,6 +32,7 @@
 #include "event.h"
 #include "grab.h"
 #include "focus.h"
+#include "propwin.h"
 #include "stacking.h"
 #include "openbox.h"
 #include "group.h"
@@ -64,7 +65,6 @@ typedef struct
 GList            *client_list          = NULL;
 
 static GSList *client_destructors      = NULL;
-static GSList *client_desktop_notifies = NULL;
 
 static void client_get_all(ObClient *self);
 static void client_toggle_border(ObClient *self, gboolean show);
@@ -104,6 +104,7 @@ void client_startup(gboolean reconfig)
 
 void client_shutdown(gboolean reconfig)
 {
+    if (reconfig) return;
 }
 
 void client_add_destructor(ObClientCallback func, gpointer data)
@@ -128,29 +129,6 @@ void client_remove_destructor(ObClientCallback func)
     }
 }
 
-void client_add_desktop_notify(ObClientCallback func, gpointer data)
-{
-    ClientCallback *d = g_new(ClientCallback, 1);
-    d->func = func;
-    d->data = data;
-    client_desktop_notifies = g_slist_prepend(client_desktop_notifies, d);
-}
-
-void client_remove_desktop_notify(ObClientCallback func)
-{
-    GSList *it;
-
-    for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
-        ClientCallback *d = it->data;
-        if (d->func == func) {
-            g_free(d);
-            client_desktop_notifies =
-                g_slist_delete_link(client_desktop_notifies, it);
-            break;
-        }
-    }
-}
-
 void client_set_list()
 {
     Window *windows, *win_it;
@@ -540,6 +518,9 @@ void client_unmanage(ObClient *self)
     /* remove the window from our save set */
     XChangeSaveSet(ob_display, self->window, SetModeDelete);
 
+    /* kill the property windows */
+    propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
+
     /* update the focus lists */
     focus_order_remove(self);
     if (client_focused(self)) {
@@ -1026,7 +1007,9 @@ static void client_get_all(ObClient *self)
     client_update_title(self);
     client_update_strut(self);
     client_update_icons(self);
-    client_update_user_time(self);
+    client_update_user_time_window(self);
+    if (!self->user_time_window) /* check if this would have been called */
+        client_update_user_time(self);
     client_update_icon_geometry(self);
 }
 
@@ -1599,10 +1582,15 @@ void client_setup_decor_and_functions(ObClient *self)
         self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE);
         break;
 
+    case OB_CLIENT_TYPE_SPLASH:
+        /* these don't get get any decorations, and the only thing you can
+           do with them is move them */
+        self->decorations = 0;
+        self->functions = OB_CLIENT_FUNC_MOVE;
+
     case OB_CLIENT_TYPE_DESKTOP:
     case OB_CLIENT_TYPE_DOCK:
-    case OB_CLIENT_TYPE_SPLASH:
-        /* none of these windows are manipulated by the window manager */
+        /* these windows are not manipulated by the window manager */
         self->decorations = 0;
         self->functions = 0;
         break;
@@ -2038,8 +2026,15 @@ void client_update_icons(ObClient *self)
 void client_update_user_time(ObClient *self)
 {
     guint32 time;
+    gboolean got = FALSE;
+
+    if (self->user_time_window)
+        got = PROP_GET32(self->user_time_window,
+                         net_wm_user_time, cardinal, &time);
+    if (!got)
+        got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time);
 
-    if (PROP_GET32(self->window, net_wm_user_time, cardinal, &time)) {
+    if (got) {
         /* we set this every time, not just when it grows, because in practice
            sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes
            backward we don't want all windows to stop focusing. we'll just
@@ -2048,9 +2043,39 @@ void client_update_user_time(ObClient *self)
         */
         self->user_time = time;
 
-        /*
-        ob_debug("window %s user time %u\n", self->title, time);
-        */
+        /*ob_debug("window %s user time %u\n", self->title, time);*/
+    }
+}
+
+void client_update_user_time_window(ObClient *self)
+{
+    guint32 w;
+
+    if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w))
+        w = None;
+
+    if (w != self->user_time_window) {
+        /* remove the old window */
+        propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
+        self->user_time_window = None;
+
+        if (self->group && self->group->leader == w) {
+            ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
+                          "_NET_WM_USER_TYPE_WINDOW to its group leader\n");
+            /* do it anyways..? */
+        }
+        else if (w == self->window) {
+            ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
+                          "_NET_WM_USER_TIME_WINDOW to itself\n");
+            w = None; /* don't do it */
+        }
+
+        /* add the new window */
+        propwin_add(w, OB_PROPWIN_USER_TIME, self);
+        self->user_time_window = w;
+
+        /* and update from it */
+        client_update_user_time(self);
     }
 }
 
@@ -2394,6 +2419,22 @@ gboolean client_helper(ObClient *self)
             self->type == OB_CLIENT_TYPE_TOOLBAR);
 }
 
+gboolean client_mouse_focusable(ObClient *self)
+{
+    return !(self->type == OB_CLIENT_TYPE_MENU ||
+             self->type == OB_CLIENT_TYPE_TOOLBAR ||
+             self->type == OB_CLIENT_TYPE_SPLASH ||
+             self->type == OB_CLIENT_TYPE_DOCK);
+}
+
+gboolean client_enter_focusable(ObClient *self)
+{
+    /* you can focus desktops but it shouldn't on enter */
+    return (client_mouse_focusable(self) &&
+            self->type != OB_CLIENT_TYPE_DESKTOP);
+}
+
+
 static void client_apply_startup_state(ObClient *self, gint x, gint y)
 {
     gboolean pos = FALSE; /* has the window's position been configured? */
@@ -2446,7 +2487,7 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
         pos = TRUE;
     }
 
-    /* if the client didn't get positioned yet, then do so now
+    /* if the client didn't get positioned yet, then do so now.
        call client_move even if the window is not being moved anywhere, because
        when we reparent it and decorate it, it is getting moved and we need to
        be telling it so with a ConfigureNotify event.
@@ -2798,7 +2839,9 @@ static void client_iconify_recursive(ObClient *self,
                  self->window);
 
         if (iconic) {
-            if (self->functions & OB_CLIENT_FUNC_ICONIFY) {
+            /* don't let non-normal windows iconify along with their parents
+               or whatever */
+            if (client_normal(self)) {
                 self->iconic = iconic;
 
                 /* update the focus lists.. iconic windows go to the bottom of
@@ -2841,9 +2884,11 @@ static void client_iconify_recursive(ObClient *self,
 
 void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
 {
-    /* move up the transient chain as far as possible first */
-    self = client_search_top_normal_parent(self);
-    client_iconify_recursive(self, iconic, curdesk);
+    if (self->functions & OB_CLIENT_FUNC_ICONIFY || !iconic) {
+        /* move up the transient chain as far as possible first */
+        self = client_search_top_normal_parent(self);
+        client_iconify_recursive(self, iconic, curdesk);
+    }
 }
 
 void client_maximize(ObClient *self, gboolean max, gint dir)
@@ -3018,13 +3063,6 @@ void client_set_desktop_recursive(ObClient *self,
             client_raise(self);
         if (STRUT_EXISTS(self->strut))
             screen_update_areas();
-
-        /* call the notifies */
-        GSList *it;
-        for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
-            ClientCallback *d = it->data;
-            d->func(self, d->data);
-        }
     }
 
     /* move all transients */
index 5fb26262a9f2b8e29b5b17ada0b4f21c22acfbc1..f9a194831a3b4da8666d81d83960ff3f4da0aff5 100644 (file)
@@ -289,13 +289,17 @@ struct _ObClient
     /*! The number of icons in icons */
     guint nicons;
 
-    /* Where the window should iconify to/from */
+    /*! Where the window should iconify to/from */
     Rect icon_geometry;
 
+    /*! The time when the client last received user interaction */
     guint32 user_time;
+    /*! A separate window for the client to update it's user_time on */
+    Window  user_time_window;
 };
 
-extern GList *client_list;
+extern GList      *client_list;
+extern GHashTable *client_user_time_window_map;
 
 void client_startup(gboolean reconfig);
 void client_shutdown(gboolean reconfig);
@@ -308,10 +312,6 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data);
 void client_add_destructor(ObClientCallback func, gpointer data);
 void client_remove_destructor(ObClientCallback func);
 
-/*! Get notified when the client changes desktop */
-void client_add_desktop_notify(ObClientCallback func, gpointer data);
-void client_remove_desktop_notify(ObClientCallback func);
-
 /*! Manages all existing windows */
 void client_manage_all();
 /*! Manages a given window */
@@ -338,6 +338,17 @@ gboolean client_normal(ObClient *self);
   (utilty, menu, etc) */
 gboolean client_helper(ObClient *self);
 
+/*! Return if the client is a type which should be given focus from mouse
+  presses on the *client* window. This doesn't affect clicking on the
+  decorations. This doesn't count for focus cycling, different rules apply to
+  that. */
+gboolean client_mouse_focusable(ObClient *self);
+
+/*! Return if the client is a type which should be given focus from the
+  mouse entering the window. This doesn't count for focus cycling, different
+  rules apply to that. */
+gboolean client_enter_focusable(ObClient *self);
+
 /* Returns if the window is focused */
 gboolean client_focused(ObClient *self);
 
@@ -453,6 +464,9 @@ void client_maximize(ObClient *self, gboolean max, gint dir);
 */
 void client_shade(ObClient *self, gboolean shade);
 
+/*! Set a client window to have decorations or not */
+void client_set_undecorated(ObClient *self, gboolean undecorated);
+
 /*! Hilite the window to make the user notice it */
 void client_hilite(ObClient *self, gboolean hilite);
 
@@ -575,6 +589,8 @@ void client_update_strut(ObClient *self);
 void client_update_icons(ObClient *self);
 /*! Updates the window's user time */
 void client_update_user_time(ObClient *self);
+/*! Updates the window's user time window */
+void client_update_user_time_window(ObClient *self);
 /*! Updates the window's icon geometry (where to iconify to/from) */
 void client_update_icon_geometry(ObClient *self);
 
@@ -646,15 +662,12 @@ ObClient *client_search_transient(ObClient *self, ObClient *search);
 gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang);
 
 /*! Set a client window to be above/below other clients.
-  @layer < 0 indicates the client should be placed below other clients.<br>
-         = 0 indicates the client should be placed with other clients.<br>
+  @layer < 0 indicates the client should be placed below other clients.<br />
+         = 0 indicates the client should be placed with other clients.<br />
          > 0 indicates the client should be placed above other clients.
 */
 void client_set_layer(ObClient *self, gint layer);
 
-/*! Set a client window to have decorations or not */
-void client_set_undecorated(ObClient *self, gboolean undecorated);
-
 guint client_monitor(ObClient *self);
 
 ObClient* client_under_pointer();
index fcc95f69dfc1aa1cf4a3eb1ad04c256f0ed70048..26430f35e05c0ccebbeb58e15b0188103a986766 100644 (file)
@@ -109,7 +109,8 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
 
 /* executes it using the client in the actions, since we set that
    when we make the actions! */
-static void menu_execute(ObMenuEntry *self, guint state, gpointer data,
+static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
+                         ObClient *c, guint state, gpointer data,
                          Time time)
 {
     ObAction *a;
index 12c16815a432fd8899a6139d8a8ab54072dfa371..351790be7b9c14e3932551443c7b413980e81b89 100644 (file)
@@ -110,7 +110,8 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
 
 /* executes it using the client in the actions, since we set that
    when we make the actions! */
-static void desk_menu_execute(ObMenuEntry *self, guint state, gpointer data,
+static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f,
+                              ObClient *c, guint state, gpointer data,
                               Time time)
 {
     ObAction *a;
index 11e31965d68f5ce5a7e792af193c5eb71b86e029..a44fcbcc5e4cc8e332bec6ee8e11d509368eb63d 100644 (file)
@@ -23,6 +23,8 @@
 #include "client.h"
 #include "openbox.h"
 #include "frame.h"
+#include "moveresize.h"
+#include "prop.h"
 #include "gettext.h"
 
 #include <glib.h>
@@ -50,81 +52,177 @@ enum {
     CLIENT_CLOSE
 };
 
-static gboolean client_update(ObMenuFrame *frame, gpointer data)
+static gboolean client_menu_update(ObMenuFrame *frame, gpointer data)
 {
     ObMenu *menu = frame->menu;
-    ObMenuEntry *e;
     GList *it;
 
     if (frame->client == NULL || !client_normal(frame->client))
         return FALSE; /* don't show the menu */
 
     for (it = menu->entries; it; it = g_list_next(it)) {
-        e = it->data;
-        if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
-            e->data.normal.enabled = TRUE;
+        ObMenuEntry *e = it->data;
+        gboolean *en = &e->data.normal.enabled; /* save some typing */
+        ObClient *c = frame->client;
+
+        if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) {
+            switch (e->id) {
+            case CLIENT_ICONIFY:
+                *en = c->functions & OB_CLIENT_FUNC_ICONIFY;
+                break;
+            case CLIENT_RESTORE:
+                *en = c->max_horz || c->max_vert;
+                break;
+            case CLIENT_MAXIMIZE:
+                *en = ((c->functions & OB_CLIENT_FUNC_MAXIMIZE) &&
+                       (!c->max_horz || !c->max_vert));
+                break;
+            case CLIENT_SHADE:
+                *en = c->functions & OB_CLIENT_FUNC_SHADE;
+                break;
+            case CLIENT_MOVE:
+                *en = c->functions & OB_CLIENT_FUNC_MOVE;
+                break;
+            case CLIENT_RESIZE:
+                *en = c->functions & OB_CLIENT_FUNC_RESIZE;
+                break;
+            case CLIENT_CLOSE:
+                *en = c->functions & OB_CLIENT_FUNC_CLOSE;
+                break;
+            case CLIENT_DECORATE:
+                *en = client_normal(c);
+                break;
+            default:
+                *en = TRUE;
+            }
+        }
     }
+    return TRUE; /* show the menu */
+}
 
-    e = menu_find_entry_id(menu, CLIENT_ICONIFY);
-    e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY;
-
-    e = menu_find_entry_id(menu, CLIENT_RESTORE);
-    e->data.normal.enabled =frame->client->max_horz || frame->client->max_vert;
-
-    e = menu_find_entry_id(menu, CLIENT_MAXIMIZE);
-    e->data.normal.enabled =
-        (frame->client->functions & OB_CLIENT_FUNC_MAXIMIZE) &&
-        !frame->client->max_horz && !frame->client->max_vert;
-
-    e = menu_find_entry_id(menu, CLIENT_SHADE);
-    e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_SHADE;
-
-    e = menu_find_entry_id(menu, CLIENT_MOVE);
-    e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_MOVE;
+static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
+                                ObClient *c, guint state, gpointer data,
+                                Time time)
+{
+    gint x, y;
 
-    e = menu_find_entry_id(menu, CLIENT_RESIZE);
-    e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_RESIZE;
+    g_assert(c);
 
-    e = menu_find_entry_id(menu, CLIENT_CLOSE);
-    e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_CLOSE;
+    switch (e->id) {
+    case CLIENT_ICONIFY:
+        /* the client won't be on screen anymore so hide the menu */
+        menu_frame_hide_all();
+        f = NULL; /* and don't update */
+
+        client_iconify(c, TRUE, FALSE);
+        break;
+    case CLIENT_RESTORE:
+        client_maximize(c, FALSE, 0);
+        break;
+    case CLIENT_MAXIMIZE:
+        client_maximize(c, TRUE, 0);
+        break;
+    case CLIENT_SHADE:
+        client_shade(c, !c->shaded);
+        break;
+    case CLIENT_DECORATE:
+        client_set_undecorated(c, !c->undecorated);
+        break;
+    case CLIENT_MOVE:
+        /* this needs to grab the keyboard so hide the menu */
+        menu_frame_hide_all();
+        f = NULL; /* and don't update */
+
+        screen_pointer_pos(&x, &y);
+        moveresize_start(c, x, y, 0,
+                         prop_atoms.net_wm_moveresize_move_keyboard);
+        break;
+    case CLIENT_RESIZE:
+        /* this needs to grab the keyboard so hide the menu */
+        menu_frame_hide_all();
+        f = NULL; /* and don't update */
+
+        screen_pointer_pos(&x, &y);
+        moveresize_start(c, x, y, 0,
+                         prop_atoms.net_wm_moveresize_size_keyboard);
+        break;
+    case CLIENT_CLOSE:
+        client_close(c);
+        break;
+    default:
+        g_assert_not_reached();
+    }
 
-    e = menu_find_entry_id(menu, CLIENT_DECORATE);
-    e->data.normal.enabled = client_normal(frame->client);
-    return TRUE; /* show the menu */
+    /* update the menu cuz stuff can have changed */
+    if (f) {
+        client_menu_update(f, NULL);
+        menu_frame_render(f);
+    }
 }
 
-static gboolean layer_update(ObMenuFrame *frame, gpointer data)
+static gboolean layer_menu_update(ObMenuFrame *frame, gpointer data)
 {
     ObMenu *menu = frame->menu;
-    ObMenuEntry *e;
     GList *it;
 
     if (frame->client == NULL || !client_normal(frame->client))
         return FALSE; /* don't show the menu */
 
     for (it = menu->entries; it; it = g_list_next(it)) {
-        e = it->data;
-        if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
-            e->data.normal.enabled = TRUE;
+        ObMenuEntry *e = it->data;
+        gboolean *en = &e->data.normal.enabled; /* save some typing */
+        ObClient *c = frame->client;
+
+        if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) {
+            switch (e->id) {
+            case LAYER_TOP:
+                *en = !c->above;
+                break;
+            case LAYER_NORMAL:
+                *en = c->above || c->below;
+                break;
+            case LAYER_BOTTOM:
+                *en = !c->below;
+                break;
+            default:
+                *en = TRUE;
+            }
+        }
     }
+    return TRUE; /* show the menu */
+}
 
-    e = menu_find_entry_id(menu, LAYER_TOP);
-    e->data.normal.enabled = !frame->client->above;
-
-    e = menu_find_entry_id(menu, LAYER_NORMAL);
-    e->data.normal.enabled = (frame->client->above || frame->client->below);
+static void layer_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
+                               ObClient *c, guint state, gpointer data,
+                               Time time)
+{
+    g_assert(c);
+
+    switch (e->id) {
+    case LAYER_TOP:
+        client_set_layer(c, 1);
+        break;
+    case LAYER_NORMAL:
+        client_set_layer(c, 0);
+        break;
+    case LAYER_BOTTOM:
+        client_set_layer(c, -1);
+        break;
+    default:
+        g_assert_not_reached();
+    }
 
-    e = menu_find_entry_id(menu, LAYER_BOTTOM);
-    e->data.normal.enabled = !frame->client->below;
-    return TRUE; /* show the menu */
+    /* update the menu cuz stuff can have changed */
+    if (f) {
+        layer_menu_update(f, NULL);
+        menu_frame_render(f);
+    }
 }
 
-static gboolean send_to_update(ObMenuFrame *frame, gpointer data)
+static gboolean send_to_menu_update(ObMenuFrame *frame, gpointer data)
 {
     ObMenu *menu = frame->menu;
     guint i;
-    GSList *acts;
-    ObAction *act;
     ObMenuEntry *e;
 
     menu_clear_entries(menu);
@@ -146,12 +244,8 @@ static gboolean send_to_update(ObMenuFrame *frame, gpointer data)
             name = screen_desktop_names[i];
         }
 
-        act = action_from_string("SendToDesktop",
-                                 OB_USER_ACTION_MENU_SELECTION);
-        act->data.sendto.desk = desk;
-        act->data.sendto.follow = FALSE;
-        acts = g_slist_prepend(NULL, act);
-        e = menu_add_normal(menu, desk, name, acts, FALSE);
+        e = menu_add_normal(menu, desk, name, NULL, FALSE);
+        e->id = desk;
         if (desk == DESKTOP_ALL) {
             e->data.normal.mask = ob_rr_theme->desk_mask;
             e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
@@ -169,23 +263,16 @@ static gboolean send_to_update(ObMenuFrame *frame, gpointer data)
     return TRUE; /* show the menu */
 }
 
-static void desktop_change_callback(ObClient *c, gpointer data)
+static void send_to_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
+                                 ObClient *c, guint state, gpointer data,
+                                 Time time)
 {
-    ObMenuFrame *frame = data;
-    if (c == frame->client) {
-        /* the client won't even be on the screen anymore, so hide the menu */
-        menu_frame_hide_all();
-    }
-}
+    g_assert(c);
 
-static void show_callback(ObMenuFrame *frame, gpointer data)
-{
-    client_add_desktop_notify(desktop_change_callback, frame);
-}
-
-static void hide_callback(ObMenuFrame *frame, gpointer data)
-{
-    client_remove_desktop_notify(desktop_change_callback);
+    client_set_desktop(c, e->id, FALSE);
+    /* the client won't even be on the screen anymore, so hide the menu */
+    if (f)
+        menu_frame_hide_all();
 }
 
 static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y,
@@ -253,44 +340,30 @@ static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y,
 
 void client_menu_startup()
 {
-    GSList *acts;
     ObMenu *menu;
     ObMenuEntry *e;
 
     menu = menu_new(LAYER_MENU_NAME, _("&Layer"), TRUE, NULL);
     menu_show_all_shortcuts(menu, TRUE);
-    menu_set_update_func(menu, layer_update);
-
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("SendToTopLayer", OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, LAYER_TOP, _("Always on &top"), acts, TRUE);
+    menu_set_update_func(menu, layer_menu_update);
+    menu_set_execute_func(menu, layer_menu_execute);
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("SendToNormalLayer",
-                            OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, LAYER_NORMAL, _("&Normal"), acts, TRUE);
-
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("SendToBottomLayer",
-                            OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, LAYER_BOTTOM, _("Always on &bottom"),acts, TRUE);
+    menu_add_normal(menu, LAYER_TOP, _("Always on &top"), NULL, TRUE);
+    menu_add_normal(menu, LAYER_NORMAL, _("&Normal"), NULL, TRUE);
+    menu_add_normal(menu, LAYER_BOTTOM, _("Always on &bottom"),NULL, TRUE);
 
 
     menu = menu_new(SEND_TO_MENU_NAME, _("&Send to desktop"), TRUE, NULL);
-    menu_set_update_func(menu, send_to_update);
-    menu_set_show_func(menu, show_callback);
-    menu_set_hide_func(menu, hide_callback);
-
+    menu_set_update_func(menu, send_to_menu_update);
+    menu_set_execute_func(menu, send_to_menu_execute);
 
     menu = menu_new(CLIENT_MENU_NAME, _("Client menu"), TRUE, NULL);
     menu_show_all_shortcuts(menu, TRUE);
-    menu_set_update_func(menu, client_update);
+    menu_set_update_func(menu, client_menu_update);
     menu_set_place_func(menu, client_menu_place);
+    menu_set_execute_func(menu, client_menu_execute);
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("ToggleMaximizeFull",
-                            OB_USER_ACTION_MENU_SELECTION));
-    e = menu_add_normal(menu, CLIENT_RESTORE, _("R&estore"), acts, TRUE);
+    e = menu_add_normal(menu, CLIENT_RESTORE, _("R&estore"), NULL, TRUE);
     e->data.normal.mask = ob_rr_theme->max_toggled_mask; 
     e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
     e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
@@ -298,17 +371,11 @@ void client_menu_startup()
     e->data.normal.mask_disabled_selected_color =
         ob_rr_theme->menu_disabled_selected_color;
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("Move", OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, CLIENT_MOVE, _("&Move"), acts, TRUE);
+    menu_add_normal(menu, CLIENT_MOVE, _("&Move"), NULL, TRUE);
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("Resize", OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, CLIENT_RESIZE, _("Resi&ze"), acts, TRUE);
+    menu_add_normal(menu, CLIENT_RESIZE, _("Resi&ze"), NULL, TRUE);
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("Iconify", OB_USER_ACTION_MENU_SELECTION));
-    e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico&nify"), acts, TRUE);
+    e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico&nify"), NULL, TRUE);
     e->data.normal.mask = ob_rr_theme->iconify_mask;
     e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
     e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
@@ -316,10 +383,7 @@ void client_menu_startup()
     e->data.normal.mask_disabled_selected_color =
         ob_rr_theme->menu_disabled_selected_color;
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("ToggleMaximizeFull",
-                            OB_USER_ACTION_MENU_SELECTION));
-    e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma&ximize"), acts, TRUE);
+    e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma&ximize"), NULL, TRUE);
     e->data.normal.mask = ob_rr_theme->max_mask; 
     e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
     e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
@@ -327,9 +391,7 @@ void client_menu_startup()
     e->data.normal.mask_disabled_selected_color =
         ob_rr_theme->menu_disabled_selected_color;
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("ToggleShade", OB_USER_ACTION_MENU_SELECTION));
-    e = menu_add_normal(menu, CLIENT_SHADE, _("&Roll up/down"), acts, TRUE);
+    e = menu_add_normal(menu, CLIENT_SHADE, _("&Roll up/down"), NULL, TRUE);
     e->data.normal.mask = ob_rr_theme->shade_mask;
     e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
     e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
@@ -337,10 +399,7 @@ void client_menu_startup()
     e->data.normal.mask_disabled_selected_color =
         ob_rr_theme->menu_disabled_selected_color;
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("ToggleDecorations",
-                            OB_USER_ACTION_MENU_SELECTION));
-    menu_add_normal(menu, CLIENT_DECORATE, _("Un/&Decorate"), acts, TRUE);
+    menu_add_normal(menu, CLIENT_DECORATE, _("Un/&Decorate"), NULL, TRUE);
 
     menu_add_separator(menu, -1, NULL);
 
@@ -350,9 +409,7 @@ void client_menu_startup()
 
     menu_add_separator(menu, -1, NULL);
 
-    acts = g_slist_prepend(NULL, action_from_string
-                           ("Close", OB_USER_ACTION_MENU_SELECTION));
-    e = menu_add_normal(menu, CLIENT_CLOSE, _("&Close"), acts, TRUE);
+    e = menu_add_normal(menu, CLIENT_CLOSE, _("&Close"), NULL, TRUE);
     e->data.normal.mask = ob_rr_theme->close_mask;
     e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
     e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
index 18db15f837e2580b43d024b144f301a9591281c1..99e35b5ada0d57e92ba2e7d1a3e3cb6fd71dcd50 100644 (file)
@@ -38,7 +38,6 @@ ObPlacePolicy config_place_policy;
 
 gchar   *config_theme;
 gboolean config_theme_keepborder;
-gboolean config_theme_hidedisabled;
 
 gchar   *config_title_layout;
 
@@ -466,13 +465,18 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         g_free(c);
     }
     if ((n = parse_find_node("titleLayout", node))) {
+        gchar *c, *d;
+
         g_free(config_title_layout);
         config_title_layout = parse_string(doc, n);
+
+        /* replace duplicates with spaces */
+        for (c = config_title_layout; *c != '\0'; ++c)
+            for (d = c+1; *d != '\0'; ++d)
+                if (*c == *d) *d = ' ';
     }
     if ((n = parse_find_node("keepBorder", node)))
         config_theme_keepborder = parse_bool(doc, n);
-    if ((n = parse_find_node("hideDisabled", node)))
-        config_theme_hidedisabled = parse_bool(doc, n);
     if ((n = parse_find_node("animateIconify", node)))
         config_animate_iconify = parse_bool(doc, n);
 
@@ -827,7 +831,6 @@ void config_startup(ObParseInst *i)
     config_animate_iconify = TRUE;
     config_title_layout = g_strdup("NLIMC");
     config_theme_keepborder = TRUE;
-    config_theme_hidedisabled = FALSE;
 
     config_font_activewindow = NULL;
     config_font_inactivewindow = NULL;
index 41cf74823afb4a1fbf36f56ef729fc1878ab6c6b..94991a60dd9cf15067d4e58f11100de8ff6f5846 100644 (file)
@@ -111,8 +111,6 @@ extern gchar *config_theme;
 
 /*! Show the one-pixel border after toggleDecor */
 extern gboolean config_theme_keepborder;
-/*! Hide window frame buttons that the window doesn't allow */
-extern gboolean config_theme_hidedisabled;
 /*! Titlebar button layout */
 extern gchar *config_title_layout;
 /*! Animate windows iconifying and restoring */
index 44ae7b0a74a3ebaf400cc045830f25a9ec626958..babb5197c193ee0316f7403ad303dc2d107b2683 100644 (file)
@@ -32,6 +32,7 @@
 #include "menuframe.h"
 #include "keyboard.h"
 #include "modkeys.h"
+#include "propwin.h"
 #include "mouse.h"
 #include "mainloop.h"
 #include "framerender.h"
@@ -81,7 +82,7 @@ static gboolean event_handle_menu(XEvent *e);
 static void event_handle_dock(ObDock *s, XEvent *e);
 static void event_handle_dockapp(ObDockApp *app, XEvent *e);
 static void event_handle_client(ObClient *c, XEvent *e);
-static void event_handle_group(ObGroup *g, XEvent *e);
+static void event_handle_user_time_window_clients(GSList *l, XEvent *e);
 static void event_handle_user_input(ObClient *client, XEvent *e);
 
 static void focus_delay_dest(gpointer data);
@@ -406,11 +407,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
 static void event_process(const XEvent *ec, gpointer data)
 {
     Window window;
-    ObGroup *group = NULL;
     ObClient *client = NULL;
     ObDock *dock = NULL;
     ObDockApp *dockapp = NULL;
     ObWindow *obwin = NULL;
+    GSList *timewinclients = NULL;
     XEvent ee, *e;
     ObEventData *ed = data;
 
@@ -419,8 +420,9 @@ static void event_process(const XEvent *ec, gpointer data)
     e = &ee;
 
     window = event_get_window(e);
-    if (!(e->type == PropertyNotify &&
-          (group = g_hash_table_lookup(group_map, &window))))
+    if (e->type != PropertyNotify ||
+        !(timewinclients = propwin_get_clients(window,
+                                               OB_PROPWIN_USER_TIME)))
         if ((obwin = g_hash_table_lookup(window_map, &window))) {
             switch (obwin->type) {
             case Window_Dock:
@@ -554,8 +556,8 @@ static void event_process(const XEvent *ec, gpointer data)
             /* focus_set_client has already been called for sure */
             client_calc_layer(client);
         }
-    } else if (group)
-        event_handle_group(group, e);
+    } else if (timewinclients)
+        event_handle_user_time_window_clients(timewinclients, e);
     else if (client)
         event_handle_client(client, e);
     else if (dockapp)
@@ -662,21 +664,11 @@ static void event_handle_root(XEvent *e)
     }
 }
 
-static void event_handle_group(ObGroup *group, XEvent *e)
-{
-    GSList *it;
-
-    g_assert(e->type == PropertyNotify);
-
-    for (it = group->members; it; it = g_slist_next(it))
-        event_handle_client(it->data, e);
-}
-
 void event_enter_client(ObClient *client)
 {
     g_assert(config_focus_follow);
 
-    if (client_normal(client) && client_can_focus(client)) {
+    if (client_enter_focusable(client) && client_can_focus(client)) {
         if (config_focus_delay) {
             ObFocusDelayData *data;
 
@@ -699,6 +691,15 @@ void event_enter_client(ObClient *client)
     }
 }
 
+static void event_handle_user_time_window_clients(GSList *l, XEvent *e)
+{
+    g_assert(e->type == PropertyNotify);
+    if (e->xproperty.atom == prop_atoms.net_wm_user_time) {
+        for (; l; l = g_slist_next(l))
+            client_update_user_time(l->data);
+    }
+}
+
 static void event_handle_client(ObClient *client, XEvent *e)
 {
     XEvent ce;
@@ -1191,6 +1192,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
         else if (msgtype == prop_atoms.net_wm_user_time) {
             client_update_user_time(client);
         }
+        else if (msgtype == prop_atoms.net_wm_user_time_window) {
+            client_update_user_time_window(client);
+        }
 #ifdef SYNC
         else if (msgtype == prop_atoms.net_wm_sync_request_counter) {
             client_update_sync_request_counter(client);
index be4e688dff71c89ae6e7ec79f09467292ee3e73d..2c3fb58fc4af040d57fc97e465b212928ceef405 100644 (file)
 #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
                            f->cbwidth_y)
 
-static void layout_title(ObFrame *self);
+/* the offsets for the titlebar elements from the edge of the titlebar.
+   negative means from the right edge. */
+gint icon_off;
+gint label_off;
+gint iconify_off;
+gint desk_off;
+gint shade_off;
+gint max_off;
+gint close_off;
+
+
 static void flash_done(gpointer data);
 static gboolean flash_timeout(gpointer data);
 
+static void layout_title(ObFrame *self);
 static void set_theme_statics(ObFrame *self);
 static void free_theme_statics(ObFrame *self);
 static gboolean frame_animate_iconify(gpointer self);
@@ -369,15 +380,6 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             self->innersize.bottom += ob_rr_theme->handle_height +
                 self->rbwidth + (self->rbwidth - self->bwidth);
   
-        /* they all default off, they're turned on in layout_title */
-        self->icon_x = -1;
-        self->desk_x = -1;
-        self->shade_x = -1;
-        self->iconify_x = -1;
-        self->label_x = -1;
-        self->max_x = -1;
-        self->close_x = -1;
-
         /* position/size and map/unmap all the windows */
 
         if (!fake) {
@@ -408,7 +410,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 XUnmapWindow(ob_display, self->title);
         }
 
-        if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
+        if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
             /* layout the title bar elements */
             layout_title(self);
 
@@ -572,11 +574,12 @@ void frame_grab_client(ObFrame *self, ObClient *client)
        req's) the ButtonPress is to catch clicks on the client border */
     XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
 
-    frame_adjust_area(self, TRUE, TRUE, FALSE);
-
     /* map the client so it maps when the frame does */
     XMapWindow(ob_display, client->window);
 
+    /* adjust the frame to the client's size */
+    frame_adjust_area(self, FALSE, TRUE, FALSE);
+
     /* set all the windows for the frame in the window_map */
     g_hash_table_insert(window_map, &self->window, client);
     g_hash_table_insert(window_map, &self->plate, client);
@@ -661,139 +664,156 @@ void frame_release_client(ObFrame *self, ObClient *client)
     frame_free(self);
 }
 
+/* is there anything present between us and the label? */
+static gboolean is_button_present(ObFrame *self, const gchar *lc, gint dir) {
+    for (; *lc != '\0' && lc >= config_title_layout; lc += dir) {
+        if (*lc == ' ') continue; /* it was invalid */
+        if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
+            return TRUE;
+        if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
+            return TRUE;
+        if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
+            return TRUE;
+        if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
+            return TRUE;
+        if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
+            return TRUE;
+        if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
+            return TRUE;
+        if (*lc == 'L') return FALSE;
+    }
+    return FALSE;
+}
+
 static void layout_title(ObFrame *self)
 {
     gchar *lc;
-    gint x;
-    gboolean n, d, i, l, m, c, s;
+    gint i, x;
 
-    n = d = i = l = m = c = s = FALSE;
+    const gint bwidth = ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
+    /* position of the left most button */
+    const gint left = ob_rr_theme->paddingx + 1;
+    /* position of the right most button */
+    const gint right = self->width - bwidth;
 
-    /* figure out whats being shown, and the width of the label */
+    /* turn them all off */
+    self->icon_on = self->desk_on = self->shade_on = self->iconify_on =
+        self->max_on = self->close_on = self->label_on = FALSE;
     self->label_width = self->width - (ob_rr_theme->paddingx + 1) * 2;
-    for (lc = config_title_layout; *lc != '\0'; ++lc) {
-        switch (*lc) {
-        case 'N':
-            if (n) { *lc = ' '; break; } /* rm duplicates */
-            n = TRUE;
-            self->label_width -= (ob_rr_theme->button_size + 2 +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        case 'D':
-            if (d) { *lc = ' '; break; }
-            if (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
-                && config_theme_hidedisabled)
-                break;
-            d = TRUE;
-            self->label_width -= (ob_rr_theme->button_size +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        case 'S':
-            if (s) { *lc = ' '; break; }
-            if (!(self->decorations & OB_FRAME_DECOR_SHADE)
-                && config_theme_hidedisabled)
-                break;
-            s = TRUE;
-            self->label_width -= (ob_rr_theme->button_size +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        case 'I':
-            if (i) { *lc = ' '; break; }
-            if (!(self->decorations & OB_FRAME_DECOR_ICONIFY)
-                && config_theme_hidedisabled)
-                break;
-            i = TRUE;
-            self->label_width -= (ob_rr_theme->button_size +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        case 'L':
-            if (l) { *lc = ' '; break; }
-            l = TRUE;
-            break;
-        case 'M':
-            if (m) { *lc = ' '; break; }
-            if (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE)
-                && config_theme_hidedisabled)
-                break;
-            m = TRUE;
-            self->label_width -= (ob_rr_theme->button_size +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        case 'C':
-            if (c) { *lc = ' '; break; }
-            if (!(self->decorations & OB_FRAME_DECOR_CLOSE)
-                && config_theme_hidedisabled)
-                break;
-            c = TRUE;
-            self->label_width -= (ob_rr_theme->button_size +
-                                  ob_rr_theme->paddingx + 1);
-            break;
-        }
-    }
-    if (self->label_width < 1) self->label_width = 1;
-
-    if (!n) XUnmapWindow(ob_display, self->icon);
-    if (!d) XUnmapWindow(ob_display, self->desk);
-    if (!s) XUnmapWindow(ob_display, self->shade);
-    if (!i) XUnmapWindow(ob_display, self->iconify);
-    if (!l) XUnmapWindow(ob_display, self->label);
-    if (!m) XUnmapWindow(ob_display, self->max);
-    if (!c) XUnmapWindow(ob_display, self->close);
-
-    x = ob_rr_theme->paddingx + 1;
-    for (lc = config_title_layout; *lc != '\0'; ++lc) {
-        switch (*lc) {
-        case 'N':
-            if (!n) break;
-            self->icon_x = x;
-            XMapWindow(ob_display, self->icon);
-            XMoveWindow(ob_display, self->icon, x, ob_rr_theme->paddingy);
-            x += ob_rr_theme->button_size + 2 + ob_rr_theme->paddingx + 1;
-            break;
-        case 'D':
-            if (!d) break;
-            self->desk_x = x;
-            XMapWindow(ob_display, self->desk);
-            XMoveWindow(ob_display, self->desk, x, ob_rr_theme->paddingy + 1);
-            x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
-            break;
-        case 'S':
-            if (!s) break;
-            self->shade_x = x;
-            XMapWindow(ob_display, self->shade);
-            XMoveWindow(ob_display, self->shade, x, ob_rr_theme->paddingy + 1);
-            x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
-            break;
-        case 'I':
-            if (!i) break;
-            self->iconify_x = x;
-            XMapWindow(ob_display, self->iconify);
-            XMoveWindow(ob_display,self->iconify, x, ob_rr_theme->paddingy + 1);
-            x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
-            break;
-        case 'L':
-            if (!l) break;
-            self->label_x = x;
-            XMapWindow(ob_display, self->label);
-            XMoveWindow(ob_display, self->label, x, ob_rr_theme->paddingy);
-            x += self->label_width + ob_rr_theme->paddingx + 1;
-            break;
-        case 'M':
-            if (!m) break;
-            self->max_x = x;
-            XMapWindow(ob_display, self->max);
-            XMoveWindow(ob_display, self->max, x, ob_rr_theme->paddingy + 1);
-            x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
-            break;
-        case 'C':
-            if (!c) break;
-            self->close_x = x;
-            XMapWindow(ob_display, self->close);
-            XMoveWindow(ob_display, self->close, x, ob_rr_theme->paddingy + 1);
-            x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
-            break;
+
+    /* figure out what's being show, find each element's position, and the
+       width of the label
+
+       do the ones before the label, then after the label,
+       i will be +1 the first time through when working to the left,
+       and -1 the second time through when working to the right */
+    for (i = 1; i >= -1; i-=2) {
+        if (i > 0) {
+            x = left;
+            lc = config_title_layout;
+        } else {
+            x = right;
+            lc = config_title_layout + strlen(config_title_layout)-1;
         }
+
+        /* stop at the end of the string (or the label, which calls break) */
+        for (; *lc != '\0' && lc >= config_title_layout; lc+=i)
+            if (*lc == 'L') {
+                if (i > 0) {
+                    self->label_on = TRUE;
+                    self->label_x = x;
+                }
+                break; /* break the for loop, do other side of label */
+            } else if (*lc == 'N') {
+                if ((self->icon_on = is_button_present(self, lc, i))) {
+                    /* icon gets extra padding */
+                    self->label_width -= bwidth + 2;
+                    self->icon_x = x + (i * 1);
+                    x += i * (bwidth + 2);
+                }
+            } else if (*lc == 'D') {
+                if ((self->desk_on = is_button_present(self, lc, i))) {
+                    self->label_width -= bwidth;
+                    self->desk_x = x;
+                    x += i * bwidth;
+                }
+            } else if (*lc == 'S') {
+                if ((self->shade_on = is_button_present(self, lc, i))) {
+                    self->label_width -= bwidth;
+                    self->shade_x = x;
+                    x += i * bwidth;
+                }
+            } else if (*lc == 'I') {
+                if ((self->iconify_on = is_button_present(self, lc, i))) {
+                    self->label_width -= bwidth;
+                    self->iconify_x = x;
+                    x += i * bwidth;
+                }
+            } else if (*lc == 'M') {
+                if ((self->max_on = is_button_present(self, lc, i))) {
+                    self->label_width -= bwidth;
+                    self->max_x = x;
+                    x += i * bwidth;
+                }
+            } else if (*lc == 'C') {
+                if ((self->close_on = is_button_present(self, lc, i))) {
+                    self->label_width -= bwidth;
+                    self->close_x = x;
+                    x += i * bwidth;
+                }
+            }
     }
+
+    /* position and map the elements */
+    if (self->icon_on) {
+        XMapWindow(ob_display, self->icon);
+        XMoveWindow(ob_display, self->icon, self->icon_x,
+                    ob_rr_theme->paddingy);
+    } else
+        XUnmapWindow(ob_display, self->icon);
+
+    if (self->desk_on) {
+        XMapWindow(ob_display, self->desk);
+        XMoveWindow(ob_display, self->desk, self->desk_x,
+                    ob_rr_theme->paddingy + 1);
+    } else
+        XUnmapWindow(ob_display, self->desk);
+
+    if (self->shade_on) {
+        XMapWindow(ob_display, self->shade);
+        XMoveWindow(ob_display, self->shade, self->shade_x,
+                    ob_rr_theme->paddingy + 1);
+    } else
+        XUnmapWindow(ob_display, self->shade);
+
+    if (self->iconify_on) {
+        XMapWindow(ob_display, self->iconify);
+        XMoveWindow(ob_display, self->iconify, self->iconify_x,
+                    ob_rr_theme->paddingy + 1);
+    } else
+        XUnmapWindow(ob_display, self->iconify);
+
+    if (self->max_on) {
+        XMapWindow(ob_display, self->max);
+        XMoveWindow(ob_display, self->max, self->max_x,
+                    ob_rr_theme->paddingy + 1);
+    } else
+        XUnmapWindow(ob_display, self->max);
+
+    if (self->close_on) {
+        XMapWindow(ob_display, self->close);
+        XMoveWindow(ob_display, self->close, self->close_x,
+                    ob_rr_theme->paddingy + 1);
+    } else
+        XUnmapWindow(ob_display, self->close);
+
+    if (self->label_on) {
+        self->label_width = MAX(1, self->label_width); /* no lower than 1 */
+        XMapWindow(ob_display, self->label);
+        XMoveWindow(ob_display, self->label, self->label_x,
+                    ob_rr_theme->paddingy);
+    } else
+        XUnmapWindow(ob_display, self->label);
 }
 
 ObFrameContext frame_context_from_string(const gchar *name)
index 7be63d53307c403f5a5672396f01aa6b4d011cd1..3a5dfdb25642895d15f01c5bb53f759a5f2986dd 100644 (file)
@@ -114,8 +114,16 @@ struct _ObFrame
 
     GSList   *clients;
 
-    gint      width;         /* title and handle */
-    gint      label_width;
+    gint      icon_on;    /* if the window icon button is on */
+    gint      label_on;   /* if the window title is on */
+    gint      iconify_on; /* if the window iconify button is on */
+    gint      desk_on;    /* if the window all-desktops button is on */
+    gint      shade_on;   /* if the window shade button is on */
+    gint      max_on;     /* if the window maximize button is on */
+    gint      close_on;   /* if the window close button is on */
+
+    gint      width;         /* width of the titlebar and handle */
+    gint      label_width;   /* width of the label in the titlebar */
     gint      icon_x;        /* x-position of the window icon button */
     gint      label_x;       /* x-position of the window title */
     gint      iconify_x;     /* x-position of the window iconify button */
index f60039c80d5e6a2c850c3fb5fa2e87f67a4a2e5c..fb4340e99f9010778c3f9afbde5c410200f46477 100644 (file)
@@ -241,7 +241,7 @@ void framerender_frame(ObFrame *self)
 
 static void framerender_label(ObFrame *self, RrAppearance *a)
 {
-    if (self->label_x < 0) return;
+    if (!self->label_on) return;
     /* set the texture's text! */
     a->texture[0].data.text.string = self->client->title;
     RrPaint(a, self->label, self->label_width, ob_rr_theme->label_height);
@@ -251,7 +251,7 @@ static void framerender_icon(ObFrame *self, RrAppearance *a)
 {
     const ObClientIcon *icon;
 
-    if (self->icon_x < 0) return;
+    if (!self->icon_on) return;
 
     icon = client_icon(self->client,
                        ob_rr_theme->button_size + 2,
@@ -270,33 +270,33 @@ static void framerender_icon(ObFrame *self, RrAppearance *a)
 
 static void framerender_max(ObFrame *self, RrAppearance *a)
 {
-    if (self->max_x < 0) return;
+    if (!self->max_on) return;
     RrPaint(a, self->max, ob_rr_theme->button_size, ob_rr_theme->button_size);
 }
 
 static void framerender_iconify(ObFrame *self, RrAppearance *a)
 {
-    if (self->iconify_x < 0) return;
+    if (!self->iconify_on) return;
     RrPaint(a, self->iconify,
             ob_rr_theme->button_size, ob_rr_theme->button_size);
 }
 
 static void framerender_desk(ObFrame *self, RrAppearance *a)
 {
-    if (self->desk_x < 0) return;
+    if (!self->desk_on) return;
     RrPaint(a, self->desk, ob_rr_theme->button_size, ob_rr_theme->button_size);
 }
 
 static void framerender_shade(ObFrame *self, RrAppearance *a)
 {
-    if (self->shade_x < 0) return;
+    if (!self->shade_on) return;
     RrPaint(a, self->shade,
             ob_rr_theme->button_size, ob_rr_theme->button_size);
 }
 
 static void framerender_close(ObFrame *self, RrAppearance *a)
 {
-    if (self->close_x < 0) return;
+    if (!self->close_on) return;
     RrPaint(a, self->close,
             ob_rr_theme->button_size, ob_rr_theme->button_size);
 }
index f70b84b742c40f0076e4cdf470e8e6c8ef213d30..c0ba6ed71432075bbd3077a691102cb9e8d19ef4 100644 (file)
 #include "group.h"
 #include "client.h"
 
-GHashTable *group_map = NULL;
+static GHashTable *group_map;
 
-static guint map_hash(Window *w) { return *w; }
-static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+static guint window_hash(Window *w) { return *w; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
 
 void group_startup(gboolean reconfig)
 {
     if (reconfig) return;
 
-    group_map = g_hash_table_new((GHashFunc)map_hash,
-                                 (GEqualFunc)map_key_comp);
+    group_map = g_hash_table_new((GHashFunc)window_hash,
+                                 (GEqualFunc)window_comp);
 }
 
 void group_shutdown(gboolean reconfig)
index 844b629bef48c75ccab8f5d6a326e7b404d9bcf5..86b36b4c1ca0d1e4590df97b042884056afbedb5 100644 (file)
@@ -34,8 +34,6 @@ struct _ObGroup
     GSList *members;
 };
 
-extern GHashTable *group_map;
-
 void group_startup(gboolean reconfig);
 void group_shutdown(gboolean reconfig);
 
index cf56ad8f3b99c60640e273e4b0de9d13fc6d6ede..d8f35bccbcca5339ba8ca48e492216d1c7dae4b8 100644 (file)
@@ -78,9 +78,11 @@ static gboolean chain_timeout(gpointer data)
 
 static void set_curpos(KeyBindingTree *newpos)
 {
-    grab_keys(FALSE);
-    curpos = newpos;
-    grab_keys(TRUE);
+    if (curpos != newpos) {
+        grab_keys(FALSE);
+        curpos = newpos;
+        grab_keys(TRUE);
+    }
 
     if (curpos != NULL) {
         gchar *text = NULL;
@@ -247,7 +249,7 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client)
                   handled = TRUE;
               }
         } else if (e->type == ButtonPress) {
-            cancel = FALSE;
+            cancel = TRUE;
             done = TRUE;
             handled = FALSE;
         }
index 9fc84bb8706f3916d97dc7ddbd93e53bdc7cb8d7..990e946c5ecc8962972eab50fe6c15f24271f72b 100644 (file)
@@ -42,6 +42,8 @@ typedef void (*ObMenuHideFunc)(struct _ObMenuFrame *frame, gpointer data);
 typedef gboolean (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame,
                                      gpointer data);
 typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry,
+                                  struct _ObMenuFrame *frame,
+                                  struct _ObClient *client,
                                   guint state, gpointer data, Time time);
 typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
 /*! @param x is the mouse x coordinate. on return it should be the x coordinate
index 01d3ae1ff308b6c3b5513c619f637e740ef4f239..5ec8280db0eeb3ffdd2a58d91aaf0479a11a4991 100644 (file)
@@ -43,7 +43,6 @@ GList *menu_frame_visible;
 static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
                                               ObMenuFrame *frame);
 static void menu_entry_frame_free(ObMenuEntryFrame *self);
-static void menu_frame_render(ObMenuFrame *self);
 static void menu_frame_update(ObMenuFrame *self);
 static gboolean menu_entry_frame_submenu_timeout(gpointer data);
 
@@ -616,7 +615,7 @@ static gint menu_entry_frame_get_height(ObMenuEntryFrame *self,
     return h;
 }
 
-static void menu_frame_render(ObMenuFrame *self)
+void menu_frame_render(ObMenuFrame *self)
 {
     gint w = 0, h = 0;
     gint tw, th; /* temps */
@@ -1230,13 +1229,16 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state, Time time)
         gpointer data = self->frame->menu->data;
         GSList *acts = self->entry->data.normal.actions;
         ObClient *client = self->frame->client;
+        ObMenuFrame *frame = self->frame;
 
         /* release grabs before executing the shit */
-        if (!(state & ControlMask))
+        if (!(state & ControlMask)) {
             menu_frame_hide_all();
+            frame = NULL;
+        }
 
         if (func)
-            func(entry, state, data, time);
+            func(entry, frame, client, state, data, time);
         else
             action_run(acts, client, state, time);
     }
index 0ce96158ae84fef0532c2cbf1f23374f232f4137..4f896ec88fbf965cf057ab35400f5479c9473a50 100644 (file)
@@ -133,6 +133,8 @@ void menu_frame_hide(ObMenuFrame *self);
 void menu_frame_hide_all();
 void menu_frame_hide_all_client(struct _ObClient *client);
 
+void menu_frame_render(ObMenuFrame *self);
+
 void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
                        gboolean immediate);
 void menu_frame_select_previous(ObMenuFrame *self);
index b0b1f2a106daabeda8afb1a38aa3947084a8cc42..6a1e235421be94245bd65f399c9987e91eea58c0 100644 (file)
@@ -37,6 +37,9 @@
 #include <X11/Xlib.h>
 #include <glib.h>
 
+/* how far windows move and resize with the keyboard arrows */
+#define KEY_DIST 4
+
 gboolean moveresize_in_progress = FALSE;
 ObClient *moveresize_client = NULL;
 #ifdef SYNC
@@ -296,20 +299,23 @@ void moveresize_end(gboolean cancel)
     moveresize_client = NULL;
 }
 
-static void do_move(gboolean resist)
+static void do_move(gboolean keyboard)
 {
-    if (resist) {
-        resist_move_windows(moveresize_client, &cur_x, &cur_y);
-        resist_move_monitors(moveresize_client, &cur_x, &cur_y);
-    }
+    gint resist;
+
+    if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+    else resist = config_resist_win;
+    resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
+    if (!keyboard) resist = config_resist_edge;
+    resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
 
     client_configure(moveresize_client, cur_x, cur_y,
                      moveresize_client->area.width,
                      moveresize_client->area.height, TRUE, FALSE);
     if (config_resize_popup_show == 2) /* == "Always" */
         popup_coords(moveresize_client, "%d x %d",
-                moveresize_client->frame->area.x,
-                moveresize_client->frame->area.y);
+                     moveresize_client->frame->area.x,
+                     moveresize_client->frame->area.y);
 }
 
 static void do_resize()
@@ -378,18 +384,21 @@ static void do_resize()
                      moveresize_client->logical_size.height);
 }
 
-static void calc_resize(gboolean resist)
+static void calc_resize(gboolean keyboard)
 {
+    gint resist;
+
     /* resist_size_* needs the frame size */
     cur_x += moveresize_client->frame->size.left +
         moveresize_client->frame->size.right;
     cur_y += moveresize_client->frame->size.top +
         moveresize_client->frame->size.bottom;
 
-    if (resist) {
-        resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
-        resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
-    }
+    if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+    else resist = config_resist_win;
+    resist_size_windows(moveresize_client, resist, &cur_x, &cur_y, lockcorner);
+    if (!keyboard) resist = config_resist_edge;
+    resist_size_monitors(moveresize_client, resist, &cur_x, &cur_y,lockcorner);
 
     cur_x -= moveresize_client->frame->size.left +
         moveresize_client->frame->size.right;
@@ -419,7 +428,7 @@ gboolean moveresize_event(XEvent *e)
         if (moving) {
             cur_x = start_cx + e->xmotion.x_root - start_x;
             cur_y = start_cy + e->xmotion.y_root - start_y;
-            do_move(TRUE);
+            do_move(FALSE);
         } else {
             if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
                 cur_x = start_cw - (e->xmotion.x_root - start_x);
@@ -462,7 +471,7 @@ gboolean moveresize_event(XEvent *e)
             } else
                 g_assert_not_reached();
 
-            calc_resize(TRUE);
+            calc_resize(FALSE);
             do_resize();
         }
         used = TRUE;
@@ -482,13 +491,13 @@ gboolean moveresize_event(XEvent *e)
                 gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
 
                 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
-                    dx = MAX(4, moveresize_client->size_inc.width);
+                    dx = MAX(KEY_DIST, moveresize_client->size_inc.width);
                 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
-                    dx = -MAX(4, moveresize_client->size_inc.width);
+                    dx = -MAX(KEY_DIST, moveresize_client->size_inc.width);
                 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
-                    dy = MAX(4, moveresize_client->size_inc.height);
+                    dy = MAX(KEY_DIST, moveresize_client->size_inc.height);
                 else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */
-                    dy = -MAX(4, moveresize_client->size_inc.height);
+                    dy = -MAX(KEY_DIST, moveresize_client->size_inc.height);
 
                 cur_x += dx;
                 cur_y += dy;
@@ -500,7 +509,8 @@ gboolean moveresize_event(XEvent *e)
                     while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
                 }
 
-                do_resize(FALSE);
+                calc_resize(TRUE);
+                do_resize();
 
                 /* because the cursor moves even though the window does
                    not nessesarily (resistance), this adjusts where the curor
@@ -515,13 +525,13 @@ gboolean moveresize_event(XEvent *e)
                 gint opx, px, opy, py;
 
                 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
-                    dx = 4;
+                    dx = KEY_DIST;
                 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
-                    dx = -4;
+                    dx = -KEY_DIST;
                 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
-                    dy = 4;
+                    dy = KEY_DIST;
                 else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */
-                    dy = -4;
+                    dy = -KEY_DIST;
 
                 cur_x += dx;
                 cur_y += dy;
@@ -535,7 +545,7 @@ gboolean moveresize_event(XEvent *e)
                 }
                 screen_pointer_pos(&px, &py);
 
-                do_move(FALSE);
+                do_move(TRUE);
 
                 /* because the cursor moves even though the window does
                    not nessesarily (resistance), this adjusts where the curor
index ec5ce10dfe65eb083a7d6a74932066fc221dcfcd..2f8d3e6a02cb781fc395a2d5087614d9cfd1075a 100644 (file)
@@ -36,6 +36,7 @@ extern XSyncAlarm moveresize_alarm;
 void moveresize_startup(gboolean reconfig);
 void moveresize_shutdown(gboolean reconfig);
 
+/*! @param corner This is one of the prop_atoms.net_wm_moveresize_ atoms */
 void moveresize_start(struct _ObClient *c,
                       gint x, gint y, guint button, guint32 corner);
 void moveresize_end(gboolean cancel);
index 9cb38b562db417e2f1980603d5db9fabb61463e8..db26f0d2582fe836c50e0e44a00374614e9eff14 100644 (file)
@@ -38,6 +38,7 @@
 #include "menuframe.h"
 #include "grab.h"
 #include "group.h"
+#include "propwin.h"
 #include "config.h"
 #include "mainloop.h"
 #include "gettext.h"
@@ -282,6 +283,7 @@ gint main(gint argc, gchar **argv)
             sn_startup(reconfigure);
             screen_startup(reconfigure);
             grab_startup(reconfigure);
+            propwin_startup(reconfigure);
             group_startup(reconfigure);
             client_startup(reconfigure);
             dock_startup(reconfigure);
@@ -339,6 +341,7 @@ gint main(gint argc, gchar **argv)
             dock_shutdown(reconfigure);
             client_shutdown(reconfigure);
             group_shutdown(reconfigure);
+            propwin_shutdown(reconfigure);
             grab_shutdown(reconfigure);
             screen_shutdown(reconfigure);
             focus_shutdown(reconfigure);
index f37973b3ed9bfce0298c5f4bc9985b9163abd131..214bb59c01e77718c5c50902cface0a503bde02c 100644 (file)
@@ -425,7 +425,7 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y,
 
 static gboolean place_transient(ObClient *client, gint *x, gint *y)
 {
-    if (client->transient_for) {
+    if (client->transient_for && client->type == OB_CLIENT_TYPE_DIALOG) {
         if (client->transient_for != OB_TRAN_GROUP) {
             ObClient *c = client;
             ObClient *p = client->transient_for;
index 0485045e344459938fb4f92d5fa132fe038f2c39..704c9109c17d4852f7ef66a5c8dc85506328e575 100644 (file)
@@ -92,6 +92,7 @@ void prop_startup()
 /*   CREATE(net_wm_pid, "_NET_WM_PID"); */
     CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
     CREATE(net_wm_user_time, "_NET_WM_USER_TIME");
+    CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW");
     CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT");
     CREATE(net_frame_extents, "_NET_FRAME_EXTENTS");
 
index eaa1bf2d8897f495e07d3c15c9348920f6571bec..f8b44a73027ef678ef84244aad379a54af004da3 100644 (file)
@@ -130,6 +130,7 @@ typedef struct Atoms {
 /*  Atom net_wm_pid; */
     Atom net_wm_allowed_actions;
     Atom net_wm_user_time;
+    Atom net_wm_user_time_window;
     Atom net_frame_extents;
 
     /* application protocols */
index e5d49faa4ccaad19b119dc441a43b385e499f073..077c46677413f45db27e0f75917d5b479557a98c 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <glib.h>
 
-void resist_move_windows(ObClient *c, gint *x, gint *y)
+void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y)
 {
     GList *it;
     gint l, t, r, b; /* requested edges */
@@ -34,6 +34,8 @@ void resist_move_windows(ObClient *c, gint *x, gint *y)
     gint w, h; /* current size */
     ObClient *snapx = NULL, *snapy = NULL;
 
+    if (!resist) return;
+
     w = c->frame->area.width;
     h = c->frame->area.height;
 
@@ -47,73 +49,72 @@ void resist_move_windows(ObClient *c, gint *x, gint *y)
     cr = RECT_RIGHT(c->frame->area);
     cb = RECT_BOTTOM(c->frame->area);
     
-    if (config_resist_win)
-        for (it = stacking_list; it; it = g_list_next(it)) {
-            ObClient *target;
-            gint tl, tt, tr, tb; /* 1 past the target's edges on each side */
-
-            if (!WINDOW_IS_CLIENT(it->data))
-                continue;
-            target = it->data;
-
-            /* don't snap to self or non-visibles */
-            if (!target->frame->visible || target == c) continue; 
-
-            /* don't snap to windows in layers beneath */
-            if(target->layer < c->layer && !config_resist_layers_below)
-                continue;
-
-            tl = RECT_LEFT(target->frame->area) - 1;
-            tt = RECT_TOP(target->frame->area) - 1;
-            tr = RECT_RIGHT(target->frame->area) + 1;
-            tb = RECT_BOTTOM(target->frame->area) + 1;
-
-            /* snapx and snapy ensure that the window snaps to the top-most
-               window edge available, without going all the way from
-               bottom-to-top in the stacking list
-            */
-            if (snapx == NULL) {
-                if (ct < tb && cb > tt) {
-                    if (cl >= tr && l < tr && l >= tr - config_resist_win)
-                        *x = tr, snapx = target;
-                    else if (cr <= tl && r > tl &&
-                             r <= tl + config_resist_win)
-                        *x = tl - w + 1, snapx = target;
-                    if (snapx != NULL) {
-                        /* try to corner snap to the window */
-                        if (ct > tt && t <= tt &&
-                            t > tt - config_resist_win)
-                            *y = tt + 1, snapy = target;
-                        else if (cb < tb && b >= tb &&
-                                 b < tb + config_resist_win)
-                            *y = tb - h, snapy = target;
-                    }
+    for (it = stacking_list; it; it = g_list_next(it)) {
+        ObClient *target;
+        gint tl, tt, tr, tb; /* 1 past the target's edges on each side */
+
+        if (!WINDOW_IS_CLIENT(it->data))
+            continue;
+        target = it->data;
+
+        /* don't snap to self or non-visibles */
+        if (!target->frame->visible || target == c) continue; 
+
+        /* don't snap to windows in layers beneath */
+        if(target->layer < c->layer && !config_resist_layers_below)
+            continue;
+
+        tl = RECT_LEFT(target->frame->area) - 1;
+        tt = RECT_TOP(target->frame->area) - 1;
+        tr = RECT_RIGHT(target->frame->area) + 1;
+        tb = RECT_BOTTOM(target->frame->area) + 1;
+
+        /* snapx and snapy ensure that the window snaps to the top-most
+           window edge available, without going all the way from
+           bottom-to-top in the stacking list
+        */
+        if (snapx == NULL) {
+            if (ct < tb && cb > tt) {
+                if (cl >= tr && l < tr && l >= tr - resist)
+                    *x = tr, snapx = target;
+                else if (cr <= tl && r > tl &&
+                         r <= tl + resist)
+                    *x = tl - w + 1, snapx = target;
+                if (snapx != NULL) {
+                    /* try to corner snap to the window */
+                    if (ct > tt && t <= tt &&
+                        t > tt - resist)
+                        *y = tt + 1, snapy = target;
+                    else if (cb < tb && b >= tb &&
+                             b < tb + resist)
+                        *y = tb - h, snapy = target;
                 }
             }
-            if (snapy == NULL) {
-                if (cl < tr && cr > tl) {
-                    if (ct >= tb && t < tb && t >= tb - config_resist_win)
-                        *y = tb, snapy = target;
-                    else if (cb <= tt && b > tt &&
-                             b <= tt + config_resist_win)
-                        *y = tt - h + 1, snapy = target;
-                    if (snapy != NULL) {
-                        /* try to corner snap to the window */
-                        if (cl > tl && l <= tl &&
-                            l > tl - config_resist_win)
-                            *x = tl + 1, snapx = target;
-                        else if (cr < tr && r >= tr &&
-                                 r < tr + config_resist_win)
-                            *x = tr - w, snapx = target;
-                    }
+        }
+        if (snapy == NULL) {
+            if (cl < tr && cr > tl) {
+                if (ct >= tb && t < tb && t >= tb - resist)
+                    *y = tb, snapy = target;
+                else if (cb <= tt && b > tt &&
+                         b <= tt + resist)
+                    *y = tt - h + 1, snapy = target;
+                if (snapy != NULL) {
+                    /* try to corner snap to the window */
+                    if (cl > tl && l <= tl &&
+                        l > tl - resist)
+                        *x = tl + 1, snapx = target;
+                    else if (cr < tr && r >= tr &&
+                             r < tr + resist)
+                        *x = tr - w, snapx = target;
                 }
             }
-
-            if (snapx && snapy) break;
         }
+
+        if (snapx && snapy) break;
+    }
 }
 
-void resist_move_monitors(ObClient *c, gint *x, gint *y)
+void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
 {
     Rect *area, *parea;
     guint i;
@@ -123,6 +124,8 @@ void resist_move_monitors(ObClient *c, gint *x, gint *y)
     gint cl, ct, cr, cb; /* current edges */
     gint w, h; /* current size */
 
+    if (!resist) return;
+
     w = c->frame->area.width;
     h = c->frame->area.height;
 
@@ -136,45 +139,44 @@ void resist_move_monitors(ObClient *c, gint *x, gint *y)
     cr = RECT_RIGHT(c->frame->area);
     cb = RECT_BOTTOM(c->frame->area);
     
-    if (config_resist_edge) {
-        for (i = 0; i < screen_num_monitors; ++i) {
-            area = screen_area_monitor(c->desktop, i);
-            parea = screen_physical_area_monitor(i);
-
-            if (!RECT_INTERSECTS_RECT(*parea, c->frame->area))
-                continue;
-
-            al = RECT_LEFT(*area);
-            at = RECT_TOP(*area);
-            ar = RECT_RIGHT(*area);
-            ab = RECT_BOTTOM(*area);
-            pl = RECT_LEFT(*parea);
-            pt = RECT_TOP(*parea);
-            pr = RECT_RIGHT(*parea);
-            pb = RECT_BOTTOM(*parea);
-
-            if (cl >= al && l < al && l >= al - config_resist_edge)
-                *x = al;
-            else if (cr <= ar && r > ar && r <= ar + config_resist_edge)
-                *x = ar - w + 1;
-            else if (cl >= pl && l < pl && l >= pl - config_resist_edge)
-                *x = pl;
-            else if (cr <= pr && r > pr && r <= pr + config_resist_edge)
-                *x = pr - w + 1;
-
-            if (ct >= at && t < at && t >= at - config_resist_edge)
-                *y = at;
-            else if (cb <= ab && b > ab && b < ab + config_resist_edge)
-                *y = ab - h + 1;
-            else if (ct >= pt && t < pt && t >= pt - config_resist_edge)
-                *y = pt;
-            else if (cb <= pb && b > pb && b < pb + config_resist_edge)
-                *y = pb - h + 1;
-        }
+    for (i = 0; i < screen_num_monitors; ++i) {
+        area = screen_area_monitor(c->desktop, i);
+        parea = screen_physical_area_monitor(i);
+
+        if (!RECT_INTERSECTS_RECT(*parea, c->frame->area))
+            continue;
+
+        al = RECT_LEFT(*area);
+        at = RECT_TOP(*area);
+        ar = RECT_RIGHT(*area);
+        ab = RECT_BOTTOM(*area);
+        pl = RECT_LEFT(*parea);
+        pt = RECT_TOP(*parea);
+        pr = RECT_RIGHT(*parea);
+        pb = RECT_BOTTOM(*parea);
+
+        if (cl >= al && l < al && l >= al - resist)
+            *x = al;
+        else if (cr <= ar && r > ar && r <= ar + resist)
+            *x = ar - w + 1;
+        else if (cl >= pl && l < pl && l >= pl - resist)
+            *x = pl;
+        else if (cr <= pr && r > pr && r <= pr + resist)
+            *x = pr - w + 1;
+
+        if (ct >= at && t < at && t >= at - resist)
+            *y = at;
+        else if (cb <= ab && b > ab && b < ab + resist)
+            *y = ab - h + 1;
+        else if (ct >= pt && t < pt && t >= pt - resist)
+            *y = pt;
+        else if (cb <= pb && b > pb && b < pb + resist)
+            *y = pb - h + 1;
     }
 }
 
-void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn)
+void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h,
+                         ObCorner corn)
 {
     GList *it;
     ObClient *target; /* target */
@@ -184,6 +186,8 @@ void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn)
     gint incw, inch;
     ObClient *snapx = NULL, *snapy = NULL;
 
+    if (!resist) return;
+
     incw = c->size_inc.width;
     inch = c->size_inc.height;
 
@@ -192,79 +196,78 @@ void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn)
     t = RECT_TOP(c->frame->area);
     b = RECT_BOTTOM(c->frame->area);
 
-    if (config_resist_win) {
-        for (it = stacking_list; it; it = g_list_next(it)) {
-            if (!WINDOW_IS_CLIENT(it->data))
-                continue;
-            target = it->data;
-
-            /* don't snap to invisibles or ourself */
-            if (!target->frame->visible || target == c) continue; 
-
-            /* don't snap to windows in layers beneath */
-            if(target->layer < c->layer && !config_resist_layers_below)
-                continue;
-
-            tl = RECT_LEFT(target->frame->area);
-            tr = RECT_RIGHT(target->frame->area);
-            tt = RECT_TOP(target->frame->area);
-            tb = RECT_BOTTOM(target->frame->area);
-
-            if (snapx == NULL) {
-                /* horizontal snapping */
-                if (t < tb && b > tt) {
-                    switch (corn) {
-                    case OB_CORNER_TOPLEFT:
-                    case OB_CORNER_BOTTOMLEFT:
-                        dlt = l;
-                        drb = r + *w - c->frame->area.width;
-                        if (r < tl && drb >= tl &&
-                            drb < tl + config_resist_win)
-                            *w = tl - l, snapx = target;
-                        break;
-                    case OB_CORNER_TOPRIGHT:
-                    case OB_CORNER_BOTTOMRIGHT:
-                        dlt = l - *w + c->frame->area.width;
-                        drb = r;
-                        if (l > tr && dlt <= tr &&
-                            dlt > tr - config_resist_win)
-                            *w = r - tr, snapx = target;
-                        break;
-                    }
+    for (it = stacking_list; it; it = g_list_next(it)) {
+        if (!WINDOW_IS_CLIENT(it->data))
+            continue;
+        target = it->data;
+
+        /* don't snap to invisibles or ourself */
+        if (!target->frame->visible || target == c) continue; 
+
+        /* don't snap to windows in layers beneath */
+        if(target->layer < c->layer && !config_resist_layers_below)
+            continue;
+
+        tl = RECT_LEFT(target->frame->area);
+        tr = RECT_RIGHT(target->frame->area);
+        tt = RECT_TOP(target->frame->area);
+        tb = RECT_BOTTOM(target->frame->area);
+
+        if (snapx == NULL) {
+            /* horizontal snapping */
+            if (t < tb && b > tt) {
+                switch (corn) {
+                case OB_CORNER_TOPLEFT:
+                case OB_CORNER_BOTTOMLEFT:
+                    dlt = l;
+                    drb = r + *w - c->frame->area.width;
+                    if (r < tl && drb >= tl &&
+                        drb < tl + resist)
+                        *w = tl - l, snapx = target;
+                    break;
+                case OB_CORNER_TOPRIGHT:
+                case OB_CORNER_BOTTOMRIGHT:
+                    dlt = l - *w + c->frame->area.width;
+                    drb = r;
+                    if (l > tr && dlt <= tr &&
+                        dlt > tr - resist)
+                        *w = r - tr, snapx = target;
+                    break;
                 }
             }
+        }
 
-            if (snapy == NULL) {
-                /* vertical snapping */
-                if (l < tr && r > tl) {
-                    switch (corn) {
-                    case OB_CORNER_TOPLEFT:
-                    case OB_CORNER_TOPRIGHT:
-                        dlt = t;
-                        drb = b + *h - c->frame->area.height;
-                        if (b < tt && drb >= tt &&
-                            drb < tt + config_resist_win)
-                            *h = tt - t, snapy = target;
-                        break;
-                    case OB_CORNER_BOTTOMLEFT:
-                    case OB_CORNER_BOTTOMRIGHT:
-                        dlt = t - *h + c->frame->area.height;
-                        drb = b;
-                        if (t > tb && dlt <= tb &&
-                            dlt > tb - config_resist_win)
-                            *h = b - tb, snapy = target;
-                        break;
-                    }
+        if (snapy == NULL) {
+            /* vertical snapping */
+            if (l < tr && r > tl) {
+                switch (corn) {
+                case OB_CORNER_TOPLEFT:
+                case OB_CORNER_TOPRIGHT:
+                    dlt = t;
+                    drb = b + *h - c->frame->area.height;
+                    if (b < tt && drb >= tt &&
+                        drb < tt + resist)
+                        *h = tt - t, snapy = target;
+                    break;
+                case OB_CORNER_BOTTOMLEFT:
+                case OB_CORNER_BOTTOMRIGHT:
+                    dlt = t - *h + c->frame->area.height;
+                    drb = b;
+                    if (t > tb && dlt <= tb &&
+                        dlt > tb - resist)
+                        *h = b - tb, snapy = target;
+                    break;
                 }
             }
-
-            /* snapped both ways */
-            if (snapx && snapy) break;
         }
+
+        /* snapped both ways */
+        if (snapx && snapy) break;
     }
 }
 
-void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn)
+void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
+                          ObCorner corn)
 {
     gint l, t, r, b; /* my left, top, right and bottom sides */
     gint dlt, drb; /* my destination left/top and right/bottom sides */
@@ -274,6 +277,8 @@ void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn)
     gint incw, inch;
     guint i;
 
+    if (!resist) return;
+
     l = RECT_LEFT(c->frame->area);
     r = RECT_RIGHT(c->frame->area);
     t = RECT_TOP(c->frame->area);
@@ -299,50 +304,48 @@ void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn)
         pr = RECT_RIGHT(*parea);
         pb = RECT_BOTTOM(*parea);
 
-        if (config_resist_edge) {
-            /* horizontal snapping */
-            switch (corn) {
-            case OB_CORNER_TOPLEFT:
-            case OB_CORNER_BOTTOMLEFT:
-                dlt = l;
-                drb = r + *w - c->frame->area.width;
-                if (r <= ar && drb > ar && drb <= ar + config_resist_edge)
-                    *w = ar - l + 1;
-                else if (r <= pr && drb > pr && drb <= pr + config_resist_edge)
-                    *w = pr - l + 1;
-                break;
-            case OB_CORNER_TOPRIGHT:
-            case OB_CORNER_BOTTOMRIGHT:
-                dlt = l - *w + c->frame->area.width;
-                drb = r;
-                if (l >= al && dlt < al && dlt >= al - config_resist_edge)
-                    *w = r - al + 1;
-                else if (l >= pl && dlt < pl && dlt >= pl - config_resist_edge)
-                    *w = r - pl + 1;
-                break;
-            }
+        /* horizontal snapping */
+        switch (corn) {
+        case OB_CORNER_TOPLEFT:
+        case OB_CORNER_BOTTOMLEFT:
+            dlt = l;
+            drb = r + *w - c->frame->area.width;
+            if (r <= ar && drb > ar && drb <= ar + resist)
+                *w = ar - l + 1;
+            else if (r <= pr && drb > pr && drb <= pr + resist)
+                *w = pr - l + 1;
+            break;
+        case OB_CORNER_TOPRIGHT:
+        case OB_CORNER_BOTTOMRIGHT:
+            dlt = l - *w + c->frame->area.width;
+            drb = r;
+            if (l >= al && dlt < al && dlt >= al - resist)
+                *w = r - al + 1;
+            else if (l >= pl && dlt < pl && dlt >= pl - resist)
+                *w = r - pl + 1;
+            break;
+        }
 
-            /* vertical snapping */
-            switch (corn) {
-            case OB_CORNER_TOPLEFT:
-            case OB_CORNER_TOPRIGHT:
-                dlt = t;
-                drb = b + *h - c->frame->area.height;
-                if (b <= ab && drb > ab && drb <= ab + config_resist_edge)
-                    *h = ab - t + 1;
-                else if (b <= pb && drb > pb && drb <= pb + config_resist_edge)
-                    *h = pb - t + 1;
-                break;
-            case OB_CORNER_BOTTOMLEFT:
-            case OB_CORNER_BOTTOMRIGHT:
-                dlt = t - *h + c->frame->area.height;
-                drb = b;
-                if (t >= at && dlt < at && dlt >= at - config_resist_edge)
-                    *h = b - at + 1;
-                else if (t >= pt && dlt < pt && dlt >= pt - config_resist_edge)
-                    *h = b - pt + 1;
-                break;
-            }
+        /* vertical snapping */
+        switch (corn) {
+        case OB_CORNER_TOPLEFT:
+        case OB_CORNER_TOPRIGHT:
+            dlt = t;
+            drb = b + *h - c->frame->area.height;
+            if (b <= ab && drb > ab && drb <= ab + resist)
+                *h = ab - t + 1;
+            else if (b <= pb && drb > pb && drb <= pb + resist)
+                *h = pb - t + 1;
+            break;
+        case OB_CORNER_BOTTOMLEFT:
+        case OB_CORNER_BOTTOMRIGHT:
+            dlt = t - *h + c->frame->area.height;
+            drb = b;
+            if (t >= at && dlt < at && dlt >= at - resist)
+                *h = b - at + 1;
+            else if (t >= pt && dlt < pt && dlt >= pt - resist)
+                *h = b - pt + 1;
+            break;
         }
     }
 }
index b961bbeb9c88962c76e463dab2ee016cce7e0fc8..7c3ed3c385e1b97d305b0361b7685704ab0f35d4 100644 (file)
@@ -23,9 +23,11 @@ struct _ObClient;
 
 #include <glib.h>
 
-void resist_move_windows(struct _ObClient *c, gint *x, gint *y);
-void resist_move_monitors(struct _ObClient *c, gint *x, gint *y);
-void resist_size_windows(struct _ObClient *c, gint *w, gint *h, ObCorner corn);
-void resist_size_monitors(struct _ObClient *c, gint *w, gint *h,ObCorner corn);
+void resist_move_windows(struct _ObClient *c, gint resist, gint *x, gint *y);
+void resist_move_monitors(struct _ObClient *c, gint resist, gint *x, gint *y);
+void resist_size_windows(struct _ObClient *c, gint resist, gint *w, gint *h,
+                         ObCorner corn);
+void resist_size_monitors(struct _ObClient *c, gint resist, gint *w, gint *h,
+                          ObCorner corn);
 
 #endif
index d48d0dda2284fc6b1ec80cd1bfcf7a8de93ff3cb..9265c73b3499100e8e107c7d16005a6cb2432114 100644 (file)
@@ -273,6 +273,7 @@ gboolean screen_annex(const gchar *program_name)
     supported[i++] = prop_atoms.net_moveresize_window;
     supported[i++] = prop_atoms.net_wm_moveresize;
     supported[i++] = prop_atoms.net_wm_user_time;
+    supported[i++] = prop_atoms.net_wm_user_time_window;
     supported[i++] = prop_atoms.net_frame_extents;
     supported[i++] = prop_atoms.net_startup_id;
 #ifdef SYNC
@@ -647,20 +648,12 @@ void screen_desktop_popup(guint d, gboolean show)
 guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                            gboolean dialog, gboolean done, gboolean cancel)
 {
-    static gboolean first = TRUE;
-    static guint origd, d;
-    guint r, c;
-
-    if (cancel) {
-        d = origd;
-        goto done_cycle;
-    } else if (done && dialog) {
-        goto done_cycle;
-    }
-    if (first) {
-        first = FALSE;
-        d = origd = screen_desktop;
-    }
+    guint d, r, c;
+
+    d = screen_desktop;
+
+    if ((cancel || done) && dialog)
+        goto show_cycle_dialog;
 
     get_row_col(d, &r, &c);
 
@@ -773,16 +766,10 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
     }
 
 show_cycle_dialog:
-    if (dialog) {
+    if (dialog && !cancel && !done) {
         screen_desktop_popup(d, TRUE);
-        return d;
-    }
-
-done_cycle:
-    first = TRUE;
-
-    screen_desktop_popup(0, FALSE);
-
+    } else
+        screen_desktop_popup(0, FALSE);
     return d;
 }
 
@@ -1267,7 +1254,16 @@ gboolean screen_pointer_pos(gint *x, gint *y)
     Window w;
     gint i;
     guint u;
-
-    return !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen),
-                           &w, &w, x, y, &i, &i, &u);
+    gboolean ret;
+
+    ret = !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen),
+                          &w, &w, x, y, &i, &i, &u);
+    if (!ret) {
+        for (i = 0; i < ScreenCount(ob_display); ++i)
+            if (i != ob_screen)
+                if (XQueryPointer(ob_display, RootWindow(ob_display, i),
+                                  &w, &w, x, y, &i, &i, &u))
+                    break;
+    }
+    return ret;
 }
index ccaa4f5726edb486efd68994465e9c2654f1c6e6..a84170f84e45145d2e4bf9d8a1b43c171ab693f2 100644 (file)
@@ -107,6 +107,8 @@ guint screen_find_monitor(Rect *search);
   gotta call it to let it know it should change. */
 void screen_set_root_cursor();
 
+/*! Gives back the pointer's position in x and y. Returns TRUE if the pointer
+  is on this screen and FALSE if it is on another screen. */
 gboolean screen_pointer_pos(gint *x, gint *y);
 
 #endif
index 7b3428bd8fce3b38c4b4c15a59641bfda9793c84..19b39c0912d4174650dcd3bcc12f5603cbed0caa 100644 (file)
 
 GHashTable *window_map;
 
+static guint window_hash(Window *w) { return *w; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
 void window_startup(gboolean reconfig)
 {
     if (reconfig) return;
 
-    window_map = g_hash_table_new(g_int_hash, g_int_equal);
+    window_map = g_hash_table_new((GHashFunc)window_hash,
+                                  (GEqualFunc)window_comp);
 }
 
 void window_shutdown(gboolean reconfig)