merge r7519-7571 from trunk
authorDana Jansens <danakj@orodu.net>
Tue, 19 Jun 2007 21:26:21 +0000 (21:26 +0000)
committerDana Jansens <danakj@orodu.net>
Tue, 19 Jun 2007 21:26:21 +0000 (21:26 +0000)
40 files changed:
data/rc.xml
data/rc.xsd
openbox/action.c
openbox/action.h
openbox/client.c
openbox/client.h
openbox/client_menu.c
openbox/config.c
openbox/config.h
openbox/dock.c
openbox/dock.h
openbox/event.c
openbox/focus.c
openbox/focus.h
openbox/focus_cycle.c
openbox/focus_cycle.h
openbox/focus_cycle_popup.c
openbox/frame.c
openbox/frame.h
openbox/framerender.c
openbox/geom.h
openbox/grab.c
openbox/keyboard.c
openbox/menuframe.c
openbox/moveresize.c
openbox/openbox.c
openbox/place.c
openbox/popup.c
openbox/resist.c
openbox/screen.c
openbox/screen.h
openbox/stacking.c
po/LINGUAS
po/ua.po [new file with mode: 0644]
render/gradient.c
render/render.c
render/render.h
render/theme.c
themes/Onyx-Citrus/openbox-3/themerc
themes/Onyx/openbox-3/themerc

index d16ae5a2757f1b28216c42361c1dfc1047b36605..1a4230c7efa07c87c5a5580de083ff209e886528 100644 (file)
@@ -32,6 +32,9 @@
 <placement>
   <policy>Smart</policy>
   <!-- 'Smart' or 'UnderMouse' -->
+  <center>yes</center>
+  <!-- whether to place windows in the center of the free area found or
+       the top left corner -->
 </placement>
 
 <theme>
       <action name="Focus"/>
       <action name="Raise"/>
     </mousebind>
-    <mousebind button="Left" action="Click">
-      <action name="Unshade"/>
-    </mousebind>
     <mousebind button="Left" action="Drag">
       <action name="Move"/>
     </mousebind>
       <action name="Shade"/>
       <action name="FocusToBottom"/>
       <action name="Unfocus"/>
+      <action name="Lower"/>
     </mousebind>
     <mousebind button="Down" action="Click">
       <action name="Unshade"/>
+      <action name="Raise"/>
     </mousebind>
 
     <mousebind button="Right" action="Press">
index e256e4481894470badeed8f76803a0159982e873..0357deed6d0868c00e7105568b293bbb5dad4d90 100644 (file)
@@ -53,6 +53,7 @@
             <xsd:documentation>defines how new windows are placed</xsd:documentation>
         </xsd:annotation>
         <xsd:element name="policy" type="ob:placementpolicy"/>
+        <xsd:element name="center" type="ob:bool"/>
     </xsd:complexType>
     <xsd:complexType name="theme">
         <xsd:element minOccurs="0" name="name" type="xsd:string"/>
index 6248d143ee8c14425c9262385546345edbc702af..7bc8ab658e849ef4f25e87be71c2c58f48e10b63 100644 (file)
@@ -470,6 +470,16 @@ void setup_action_showmenu(ObAction **a, ObUserAction uact)
     }
 }
 
+void setup_action_addremove_desktop_current(ObAction **a, ObUserAction uact)
+{
+    (*a)->data.addremovedesktop.current = TRUE;
+}
+
+void setup_action_addremove_desktop_last(ObAction **a, ObUserAction uact)
+{
+    (*a)->data.addremovedesktop.current = FALSE;
+}
+
 void setup_action_focus(ObAction **a, ObUserAction uact)
 {
     (*a)->data.any.client_action = OB_CLIENT_ACTION_OPTIONAL;
@@ -927,6 +937,26 @@ ActionString actionstrings[] =
         action_break_chroot,
         NULL
     },
+    {
+        "adddesktoplast",
+        action_add_desktop,
+        setup_action_addremove_desktop_last
+    },
+    {
+        "removedesktoplast",
+        action_remove_desktop,
+        setup_action_addremove_desktop_last
+    },
+    {
+        "adddesktopcurrent",
+        action_add_desktop,
+        setup_action_addremove_desktop_current
+    },
+    {
+        "removedesktopcurrent",
+        action_remove_desktop,
+        setup_action_addremove_desktop_current
+    },
     {
         NULL,
         NULL,
@@ -1407,7 +1437,7 @@ void action_toggle_omnipresent(union ActionData *data)
 { 
     client_set_desktop(data->client.any.c,
                        data->client.any.c->desktop == DESKTOP_ALL ?
-                       screen_desktop : DESKTOP_ALL, FALSE);
+                       screen_desktop : DESKTOP_ALL, FALSE, TRUE);
 }
 
 void action_move_relative_horz(union ActionData *data)
@@ -1430,11 +1460,12 @@ void action_move_to_center(union ActionData *data)
 {
     ObClient *c = data->client.any.c;
     Rect *area;
-    area = screen_area_monitor(c->desktop, 0);
+    area = screen_area(c->desktop, client_monitor(c), NULL);
     client_action_start(data);
-    client_move(c, area->width / 2 - c->area.width / 2,
-                area->height / 2 - c->area.height / 2);
+    client_move(c, area->x + area->width / 2 - c->area.width / 2,
+                area->y + area->height / 2 - c->area.height / 2);
     client_action_end(data, FALSE);
+    g_free(area);
 }
 
 void action_resize_relative_horz(union ActionData *data)
@@ -1580,7 +1611,7 @@ void action_send_to_desktop(union ActionData *data)
 
     if (data->sendto.desk < screen_num_desktops ||
         data->sendto.desk == DESKTOP_ALL) {
-        client_set_desktop(c, data->sendto.desk, data->sendto.follow);
+        client_set_desktop(c, data->sendto.desk, data->sendto.follow, FALSE);
         if (data->sendto.follow && data->sendto.desk != screen_desktop)
             screen_set_desktop(data->sendto.desk, TRUE);
     }
@@ -1638,7 +1669,7 @@ void action_send_to_desktop_dir(union ActionData *data)
     if (!data->sendtodir.inter.any.interactive ||
         (data->sendtodir.inter.final && !data->sendtodir.inter.cancel))
     {
-        client_set_desktop(c, d, data->sendtodir.follow);
+        client_set_desktop(c, d, data->sendtodir.follow, FALSE);
         if (data->sendtodir.follow && d != screen_desktop)
             screen_set_desktop(d, TRUE);
     }
@@ -1646,7 +1677,8 @@ void action_send_to_desktop_dir(union ActionData *data)
 
 void action_desktop_last(union ActionData *data)
 {
-    screen_set_desktop(screen_last_desktop, TRUE);
+    if (screen_last_desktop < screen_num_desktops)
+        screen_set_desktop(screen_last_desktop, TRUE);
 }
 
 void action_toggle_decorations(union ActionData *data)
@@ -1897,7 +1929,7 @@ void action_growtoedge(union ActionData *data)
     ObClient *c = data->diraction.any.c;
     Rect *a;
 
-    a = screen_area(c->desktop);
+    a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
     x = c->frame->area.x;
     y = c->frame->area.y;
     /* get the unshaded frame's dimensions..if it is shaded */
@@ -1956,6 +1988,7 @@ void action_growtoedge(union ActionData *data)
     client_action_start(data);
     client_move_resize(c, x, y, width, height);
     client_action_end(data, FALSE);
+    g_free(a);
 }
 
 void action_send_to_layer(union ActionData *data)
@@ -2001,3 +2034,76 @@ void action_break_chroot(union ActionData *data)
     /* break out of one chroot */
     keyboard_reset_chains(1);
 }
+
+void action_add_desktop(union ActionData *data)
+{
+    client_action_start(data);
+    screen_set_num_desktops(screen_num_desktops+1);
+
+    /* move all the clients over */
+    if (data->addremovedesktop.current) {
+        GList *it;
+
+        for (it = client_list; it; it = g_list_next(it)) {
+            ObClient *c = it->data;
+            if (c->desktop != DESKTOP_ALL && c->desktop >= screen_desktop)
+                client_set_desktop(c, c->desktop+1, FALSE, TRUE);
+        }
+    }
+
+    client_action_end(data, config_focus_under_mouse);
+}
+
+void action_remove_desktop(union ActionData *data)
+{
+    guint rmdesktop, movedesktop;
+    GList *it, *stacking_copy;
+
+    if (screen_num_desktops < 2) return;
+
+    client_action_start(data);
+
+    /* what desktop are we removing and moving to? */
+    if (data->addremovedesktop.current)
+        rmdesktop = screen_desktop;
+    else
+        rmdesktop = screen_num_desktops - 1;
+    if (rmdesktop < screen_num_desktops - 1)
+        movedesktop = rmdesktop + 1;
+    else
+        movedesktop = rmdesktop;
+
+    /* make a copy of the list cuz we're changing it */
+    stacking_copy = g_list_copy(stacking_list);
+    for (it = g_list_last(stacking_copy); it; it = g_list_previous(it)) {
+        if (WINDOW_IS_CLIENT(it->data)) {
+            ObClient *c = it->data;
+            guint d = c->desktop;
+            if (d != DESKTOP_ALL && d >= movedesktop) {
+                client_set_desktop(c, c->desktop - 1, TRUE, TRUE);
+                ob_debug("moving window %s\n", c->title);
+            }
+            /* raise all the windows that are on the current desktop which
+               is being merged */
+            if ((screen_desktop == rmdesktop - 1 ||
+                 screen_desktop == rmdesktop) &&
+                (d == DESKTOP_ALL || d == screen_desktop))
+            {
+                stacking_raise(CLIENT_AS_WINDOW(c));
+                ob_debug("raising window %s\n", c->title);
+            }
+        }
+    }
+
+    /* act like we're changing desktops */
+    if (screen_desktop < screen_num_desktops - 1) {
+        gint d = screen_desktop;
+        screen_desktop = screen_last_desktop;
+        screen_set_desktop(d, TRUE);
+        ob_debug("fake desktop change\n");
+    }
+
+    screen_set_num_desktops(screen_num_desktops-1);
+
+    client_action_end(data, config_focus_under_mouse);
+}
index 38452e44081747b0b984432a134df992e9ac0a26..17e35766a640d336f2d5b44abe2f1674a5f1aba1 100644 (file)
@@ -142,6 +142,11 @@ struct ShowMenu {
     gchar *name;
 };
 
+struct AddRemoveDesktop {
+    struct AnyAction any;
+    gboolean current;
+};
+
 struct CycleWindows {
     struct InteractiveAction inter;
     gboolean linear;
@@ -175,6 +180,7 @@ union ActionData {
     struct CycleWindows cycle;
     struct Layer layer;
     struct Stacking stacking;
+    struct AddRemoveDesktop addremovedesktop;
 };
 
 struct _ObAction {
@@ -356,5 +362,9 @@ void action_show_desktop(union ActionData *data);
 void action_unshow_desktop(union ActionData *data);
 /* Any */
 void action_break_chroot(union ActionData *data);
+/* AddRemoveDesktop */
+void action_add_desktop(union ActionData *data);
+/* AddRemoveDesktop */
+void action_remove_desktop(union ActionData *data);
 
 #endif
index 29b27d1d8760a5da1288f9b0dcba0669e7e18483..cf6965ae24ade67a84338309fe434ebad6d9d0fe 100644 (file)
@@ -314,20 +314,13 @@ void client_manage(Window window)
     /* focus the new window? */
     if (ob_state() != OB_STATE_STARTING &&
         (!self->session || self->session->focused) &&
-        !self->iconic &&
         /* this means focus=true for window is same as config_focus_new=true */
         ((config_focus_new || (settings && settings->focus == 1)) ||
          client_search_focus_tree_full(self)) &&
         /* this checks for focus=false for the window */
         (!settings || settings->focus != 0) &&
-        /* note the check against type Normal/Dialog/Utility,
-           not client_normal(self), which would also include other types.
-           in this case we want more strict rules for focus */
-        (self->type == OB_CLIENT_TYPE_NORMAL ||
-         self->type == OB_CLIENT_TYPE_UTILITY ||
-         self->type == OB_CLIENT_TYPE_DIALOG))
+        focus_valid_target(self, FALSE, TRUE, FALSE, FALSE))
     {
-        /* XXX use focus_cycle_valid_target instead... */
         activate = TRUE;
     }
 
@@ -401,25 +394,30 @@ void client_manage(Window window)
     */
     if (ob_state() == OB_STATE_RUNNING &&
         (transient ||
-         (!(self->sized & USSize) &&
+         (!(self->sized & USSize || self->positioned & USPosition) &&
           client_normal(self) &&
           !self->session)))
     {
-        /* make a copy to modify */
-        Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
+        Rect placer;
+
+        RECT_SET(placer, placex, placey, placew, placeh);
+        frame_rect_to_frame(self->frame, &placer);
+
+        Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer);
 
         /* shrink by the frame's area */
-        a.width -= self->frame->size.left + self->frame->size.right;
-        a.height -= self->frame->size.top + self->frame->size.bottom;
+        a->width -= self->frame->size.left + self->frame->size.right;
+        a->height -= self->frame->size.top + self->frame->size.bottom;
 
         /* fit the window inside the area */
-        if (placew > a.width || self->area.height > a.height) {
-            placew = MIN(self->area.width, a.width);
-            placeh = MIN(self->area.height, a.height);
+        if (placew > a->width || self->area.height > a->height) {
+            placew = MIN(self->area.width, a->width);
+            placeh = MIN(self->area.height, a->height);
 
             ob_debug("setting window size to %dx%d\n",
                      self->area.width, self->area.height);
         }
+        g_free(a);
     }
 
 
@@ -924,15 +922,14 @@ void client_move_onscreen(ObClient *self, gboolean rude)
 gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
                               gboolean rude)
 {
-    Rect *mon_a, *all_a;
     gint ox = *x, oy = *y;
     gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude;
     gint fw, fh;
     Rect desired;
+    guint i;
 
     RECT_SET(desired, *x, *y, w, h);
-    all_a = screen_area(self->desktop);
-    mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired));
+    frame_rect_to_frame(self->frame, &desired);
 
     /* get where the frame would be */
     frame_client_gravity(self->frame, x, y, w, h);
@@ -941,30 +938,8 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     fw = self->frame->size.left + w + self->frame->size.right;
     fh = self->frame->size.top + h + self->frame->size.bottom;
 
-    /* This makes sure windows aren't entirely outside of the screen so you
-       can't see them at all.
-       It makes sure 10% of the window is on the screen at least. At don't let
-       it move itself off the top of the screen, which would hide the titlebar
-       on you. (The user can still do this if they want too, it's only limiting
-       the application.
-
-       XXX watch for xinerama dead areas...
-    */
-    if (client_normal(self)) {
-        if (!self->strut.right && *x + fw/10 >= all_a->x + all_a->width - 1)
-            *x = all_a->x + all_a->width - fw/10;
-        if (!self->strut.bottom && *y + fh/10 >= all_a->y + all_a->height - 1)
-            *y = all_a->y + all_a->height - fh/10;
-        if (!self->strut.left && *x + fw*9/10 - 1 < all_a->x)
-            *x = all_a->x - fw*9/10;
-        if (!self->strut.top && *y + fh*9/10 - 1 < all_a->y)
-            *y = all_a->y - fw*9/10;
-    }
-
-    /* If rudeness wasn't requested, then figure out of the client is currently
-       entirely on the screen. If it is, and the position isn't changing by
-       request, and it is enlarging, then be rude even though it wasn't
-       requested */
+    /* If rudeness wasn't requested, then still be rude in a given direction
+       if the client is not moving, only resizing in that direction */
     if (!rude) {
         Point oldtl, oldtr, oldbl, oldbr;
         Point newtl, newtr, newbl, newbr;
@@ -1001,19 +976,48 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
             rudeb = TRUE;
     }
 
-    /* This here doesn't let windows even a pixel outside the struts/screen.
-     * When called from client_manage, programs placing themselves are
-     * forced completely onscreen, while things like
-     * xterm -geometry resolution-width/2 will work fine. Trying to
-     * place it completely offscreen will be handled in the above code.
-     * Sorry for this confused comment, i am tired. */
-    if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x;
-    if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width)
-        *x = mon_a->x + MAX(0, mon_a->width - fw);
+    for (i = 0; i < screen_num_monitors; ++i) {
+        Rect *a;
+
+        if (!screen_physical_area_monitor_contains(i, &desired))
+            continue;
+
+        a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &desired);
 
-    if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y;
-    if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height)
-        *y = mon_a->y + MAX(0, mon_a->height - fh);
+        /* This makes sure windows aren't entirely outside of the screen so you
+           can't see them at all.
+           It makes sure 10% of the window is on the screen at least. At don't
+           let it move itself off the top of the screen, which would hide the
+           titlebar on you. (The user can still do this if they want too, it's
+           only limiting the application.
+        */
+        if (client_normal(self)) {
+            if (!self->strut.right && *x + fw/10 >= a->x + a->width - 1)
+                *x = a->x + a->width - fw/10;
+            if (!self->strut.bottom && *y + fh/10 >= a->y + a->height - 1)
+                *y = a->y + a->height - fh/10;
+            if (!self->strut.left && *x + fw*9/10 - 1 < a->x)
+                *x = a->x - fw*9/10;
+            if (!self->strut.top && *y + fh*9/10 - 1 < a->y)
+                *y = a->y - fw*9/10;
+        }
+
+        /* This here doesn't let windows even a pixel outside the
+           struts/screen. When called from client_manage, programs placing
+           themselves are forced completely onscreen, while things like
+           xterm -geometry resolution-width/2 will work fine. Trying to
+           place it completely offscreen will be handled in the above code.
+           Sorry for this confused comment, i am tired. */
+        if (rudel && !self->strut.left && *x < a->x) *x = a->x;
+        if (ruder && !self->strut.right && *x + fw > a->x + a->width)
+            *x = a->x + MAX(0, a->width - fw);
+
+        if (rudet && !self->strut.top && *y < a->y) *y = a->y;
+        if (rudeb && !self->strut.bottom && *y + fh > a->y + a->height)
+            *y = a->y + MAX(0, a->height - fh);
+
+        g_free(a);
+    }
 
     /* get where the client should be */
     frame_frame_gravity(self->frame, x, y, w, h);
@@ -1745,7 +1749,8 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
     client_change_allowed_actions(self);
 
     if (reconfig)
-        client_reconfigure(self);
+        /* force reconfigure to make sure decorations are updated */
+        client_reconfigure(self, TRUE);
 }
 
 static void client_change_allowed_actions(ObClient *self)
@@ -1803,13 +1808,6 @@ static void client_change_allowed_actions(ObClient *self)
     }
 }
 
-void client_reconfigure(ObClient *self)
-{
-    client_configure(self, self->area.x, self->area.y,
-                     self->area.width, self->area.height,
-                     FALSE, TRUE);
-}
-
 void client_update_wmhints(ObClient *self)
 {
     XWMHints *hints;
@@ -1975,12 +1973,12 @@ void client_update_strut(ObClient *self)
     if (!got &&
         PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) {
         if (num == 4) {
-            const Rect *a;
+            Rect *a;
 
             got = TRUE;
 
             /* use the screen's width/height */
-            a = screen_physical_area();
+            a = screen_physical_area_all_monitors();
 
             STRUT_PARTIAL_SET(strut,
                               data[0], data[2], data[1], data[3],
@@ -1988,6 +1986,7 @@ void client_update_strut(ObClient *self)
                               a->x, a->x + a->width - 1,
                               a->y, a->y + a->height - 1,
                               a->x, a->x + a->width - 1);
+            g_free(a);
         }
         g_free(data);
     }
@@ -2085,8 +2084,11 @@ void client_update_icons(ObClient *self)
     /* set the default icon onto the window
        in theory, this could be a race, but if a window doesn't set an icon
        or removes it entirely, it's not very likely it is going to set one
-       right away afterwards */
-    if (self->nicons == 0) {
+       right away afterwards
+
+       if it has parents, then one of them will have an icon already 
+    */
+    if (self->nicons == 0 && !self->parents) {
         RrPixel32 *icon = ob_rr_theme->def_win_icon;
         gulong *data;
 
@@ -2388,6 +2390,9 @@ gboolean client_has_parent(ObClient *self)
 static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
+    Rect *monitor;
+
+    monitor = screen_physical_area_monitor(client_monitor(self));
 
     if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
@@ -2401,15 +2406,15 @@ static ObStackingLayer calc_layer(ObClient *self)
               */
               (self->decorations == 0 &&
                !(self->max_horz && self->max_vert) &&
-               RECT_EQUAL(self->area,
-                          *screen_physical_area_monitor
-                          (client_monitor(self))))) &&
+               RECT_EQUAL(self->area, *monitor))) &&
              (client_focused(self) || client_search_focus_tree(self)))
         l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->above) l = OB_STACKING_LAYER_ABOVE;
     else if (self->below) l = OB_STACKING_LAYER_BELOW;
     else l = OB_STACKING_LAYER_NORMAL;
 
+    g_free(monitor);
+
     return l;
 }
 
@@ -2610,7 +2615,7 @@ static void client_apply_startup_state(ObClient *self,
     /* if the window hasn't been configured yet, then do so now */
     if (!fullscreen && !max_vert && !max_horz) {
         self->area = oldarea;
-        client_configure(self, x, y, w, h, FALSE, TRUE);
+        client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
     }
 
     /* set the desktop hint, to make sure that it always exists */
@@ -2687,7 +2692,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
                           gint *logicalw, gint *logicalh,
                           gboolean user)
 {
-    Rect desired_area = {*x, *y, *w, *h};
+    Rect desired = {*x, *y, *w, *h};
+    frame_rect_to_frame(self->frame, &desired);
 
     /* make the frame recalculate its dimentions n shit without changing
        anything visible for real, this way the constraints below can work with
@@ -2704,7 +2710,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
         Rect *a;
         guint i;
 
-        i = screen_find_monitor(&desired_area);
+        i = screen_find_monitor(&desired);
         a = screen_physical_area_monitor(i);
 
         *x = a->x;
@@ -2714,12 +2720,16 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 
         user = FALSE; /* ignore if the client can't be moved/resized when it
                          is fullscreening */
+
+        g_free(a);
     } else if (self->max_horz || self->max_vert) {
         Rect *a;
         guint i;
 
-        i = screen_find_monitor(&desired_area);
-        a = screen_area_monitor(self->desktop, i);
+        /* use all possible struts when maximizing to the full screen */
+        i = screen_find_monitor(&desired);
+        a = screen_area(self->desktop, i,
+                        (self->max_horz && self->max_vert ? NULL : &desired));
 
         /* set the size and position if maximized */
         if (self->max_horz) {
@@ -2733,6 +2743,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 
         user = FALSE; /* ignore if the client can't be moved/resized when it
                          is maximizing */
+
+        g_free(a);
     }
 
     /* gets the client's position */
@@ -2741,7 +2753,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     /* work within the prefered sizes given by the window */
     if (!(*w == self->area.width && *h == self->area.height)) {
         gint basew, baseh, minw, minh;
-        gint incw, inch, minratio, maxratio;
+        gint incw, inch;
+        gfloat minratio, maxratio;
 
         incw = self->fullscreen || self->max_horz ? 1 : self->size_inc.width;
         inch = self->fullscreen || self->max_vert ? 1 : self->size_inc.height;
@@ -2845,11 +2858,11 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 
 
 void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
-                      gboolean user, gboolean final)
+                      gboolean user, gboolean final, gboolean force_reply)
 {
     gint oldw, oldh;
     gboolean send_resize_client;
-    gboolean moved = FALSE, resized = FALSE;
+    gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
     gboolean fmoved, fresized;
     guint fdecor = self->frame->decorations;
     gboolean fhorz = self->frame->max_horz;
@@ -2898,34 +2911,49 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
     }
 
     /* adjust the frame */
-    if (fmoved || fresized)
+    if (fmoved || fresized) {
+        gulong ignore_start;
+        if (!user)
+            ignore_start = event_start_ignore_all_enters();
+
         frame_adjust_area(self->frame, fmoved, fresized, FALSE);
 
+        if (!user)
+            event_end_ignore_all_enters(ignore_start);
+    }
+
+    if (!user || final) {
+        gint oldrx = self->root_pos.x;
+        gint oldry = self->root_pos.y;
+        /* we have reset the client to 0 border width, so don't include
+           it in these coords */
+        POINT_SET(self->root_pos,
+                  self->frame->area.x + self->frame->size.left -
+                  self->border_width,
+                  self->frame->area.y + self->frame->size.top -
+                  self->border_width);
+        if (self->root_pos.x != oldrx || self->root_pos.y != oldry)
+            rootmoved = TRUE;
+    }
+
     /* This is kinda tricky and should not be changed.. let me explain!
 
        When user = FALSE, then the request is coming from the application
        itself, and we are more strict about when to send a synthetic
        ConfigureNotify.  We strictly follow the rules of the ICCCM sec 4.1.5
-       in this case.
+       in this case (if force_reply is true)
 
        When user = TRUE, then the request is coming from "us", like when we
-       maximize a window or sometihng.  In this case we are more lenient.  We
+       maximize a window or something.  In this case we are more lenient.  We
        used to follow the same rules as above, but _Java_ Swing can't handle
        this. So just to appease Swing, when user = TRUE, we always send
        a synthetic ConfigureNotify to give the window its root coordinates.
     */
-    if ((!user && !resized) || (user && final))
+    if ((!user && !resized && (rootmoved || force_reply)) ||
+        (user && final && rootmoved))
     {
         XEvent event;
 
-        /* we have reset the client to 0 border width, so don't include
-           it in these coords */
-        POINT_SET(self->root_pos,
-                  self->frame->area.x + self->frame->size.left -
-                  self->border_width,
-                  self->frame->area.y + self->frame->size.top -
-                  self->border_width);
-
         event.type = ConfigureNotify;
         event.xconfigure.display = ob_display;
         event.xconfigure.event = self->window;
@@ -3043,7 +3071,7 @@ static void client_iconify_recursive(ObClient *self,
 
             if (curdesk && self->desktop != screen_desktop &&
                 self->desktop != DESKTOP_ALL)
-                client_set_desktop(self, screen_desktop, FALSE);
+                client_set_desktop(self, screen_desktop, FALSE, FALSE);
 
             /* this puts it after the current focused window */
             focus_order_remove(self);
@@ -3158,7 +3186,7 @@ void client_shade(ObClient *self, gboolean shade)
     client_change_state(self);
     client_change_wm_state(self); /* the window is being hidden/shown */
     /* resize the frame to just the titlebar */
-    frame_adjust_area(self->frame, FALSE, FALSE, FALSE);
+    frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
 }
 
 void client_close(ObClient *self)
@@ -3216,7 +3244,8 @@ void client_hilite(ObClient *self, gboolean hilite)
 
 void client_set_desktop_recursive(ObClient *self,
                                   guint target,
-                                  gboolean donthide)
+                                  gboolean donthide,
+                                  gboolean dontraise)
 {
     guint old;
     GSList *it;
@@ -3234,28 +3263,32 @@ void client_set_desktop_recursive(ObClient *self,
         frame_adjust_state(self->frame);
         /* 'move' the window to the new desktop */
         if (!donthide)
-            client_showhide(self);
+            client_hide(self);
+        client_show(self);
         /* raise if it was not already on the desktop */
-        if (old != DESKTOP_ALL)
+        if (old != DESKTOP_ALL && !dontraise)
             stacking_raise(CLIENT_AS_WINDOW(self));
-        /* the new desktop's geometry may be different, so we may need to
-           resize, for example if we are maximized */
-        client_reconfigure(self);
         if (STRUT_EXISTS(self->strut))
             screen_update_areas();
+        else
+            /* the new desktop's geometry may be different, so we may need to
+               resize, for example if we are maximized */
+            client_reconfigure(self, FALSE);
     }
 
     /* move all transients */
     for (it = self->transients; it; it = g_slist_next(it))
         if (it->data != self)
             if (client_is_direct_child(self, it->data))
-                client_set_desktop_recursive(it->data, target, donthide);
+                client_set_desktop_recursive(it->data, target,
+                                             donthide, dontraise);
 }
 
-void client_set_desktop(ObClient *self, guint target, gboolean donthide)
+void client_set_desktop(ObClient *self, guint target,
+                        gboolean donthide, gboolean dontraise)
 {
     self = client_search_top_direct_parent(self);
-    client_set_desktop_recursive(self, target, donthide);
+    client_set_desktop_recursive(self, target, donthide, dontraise);
 }
 
 gboolean client_is_direct_child(ObClient *parent, ObClient *child)
@@ -3587,7 +3620,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
         self->desktop != screen_desktop)
     {
         if (here)
-            client_set_desktop(self, screen_desktop, FALSE);
+            client_set_desktop(self, screen_desktop, FALSE, TRUE);
         else
             screen_set_desktop(self->desktop, FALSE);
     } else if (!self->frame->visible)
@@ -3654,7 +3687,7 @@ static void client_bring_windows_recursive(ObClient *self,
         if (iconic && self->iconic)
             client_iconify(self, FALSE, TRUE, FALSE);
         else
-            client_set_desktop(self, desktop, FALSE);
+            client_set_desktop(self, desktop, FALSE, FALSE);
     }
 }
 
@@ -3858,13 +3891,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
     gint dest, monitor_dest;
     gint my_edge_start, my_edge_end, my_offset;
     GList *it;
-    Rect *a, *monitor;
+    Rect *a, *mon;
     
     if(!client_list)
         return -1;
 
-    a = screen_area(c->desktop);
-    monitor = screen_area_monitor(c->desktop, client_monitor(c));
+    a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
+    mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area);
 
     switch(dir) {
     case OB_DIRECTION_NORTH:
@@ -3874,7 +3907,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         
         /* default: top of screen */
         dest = a->y + (hang ? c->frame->area.height : 0);
-        monitor_dest = monitor->y + (hang ? c->frame->area.height : 0);
+        monitor_dest = mon->y + (hang ? c->frame->area.height : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
         if (monitor_dest != dest && my_offset > monitor_dest)
@@ -3907,7 +3940,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
 
         /* default: bottom of screen */
         dest = a->y + a->height - (hang ? c->frame->area.height : 0);
-        monitor_dest = monitor->y + monitor->height -
+        monitor_dest = mon->y + mon->height -
                        (hang ? c->frame->area.height : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
@@ -3942,7 +3975,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
 
         /* default: leftmost egde of screen */
         dest = a->x + (hang ? c->frame->area.width : 0);
-        monitor_dest = monitor->x + (hang ? c->frame->area.width : 0);
+        monitor_dest = mon->x + (hang ? c->frame->area.width : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
         if (monitor_dest != dest && my_offset > monitor_dest)
@@ -3975,7 +4008,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         
         /* default: rightmost edge of screen */
         dest = a->x + a->width - (hang ? c->frame->area.width : 0);
-        monitor_dest = monitor->x + monitor->width -
+        monitor_dest = mon->x + mon->width -
                        (hang ? c->frame->area.width : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
@@ -4011,6 +4044,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         g_assert_not_reached();
         dest = 0; /* suppress warning */
     }
+
+    g_free(a);
+    g_free(mon);
     return dest;
 }
 
index 98f9e6e41afd9441537c3daf5a5c1430b868fed8..ed6779264454bdca6e9c82ea5d662ae21f0bba3b 100644 (file)
@@ -379,16 +379,21 @@ void client_convert_gravity_resize(ObClient *self, gint gravity,
                                    gint w, gint h);
 
 #define client_move(self, x, y) \
-  client_configure(self, x, y, self->area.width, self->area.height, TRUE, TRUE)
+  client_configure(self, x, y, self->area.width, self->area.height, TRUE, TRUE,\
+                   FALSE)
 #define client_resize(self, w, h) \
-  client_configure(self, self->area.x, self->area.y, w, h, TRUE, TRUE)
+  client_configure(self, self->area.x, self->area.y, w, h, TRUE, TRUE, FALSE)
 #define client_move_resize(self, x, y, w, h) \
-  client_configure(self, x, y, w, h, TRUE, TRUE)
+  client_configure(self, x, y, w, h, TRUE, TRUE, FALSE)
+#define client_reconfigure(self, force) \
+  client_configure(self, ((ObClient*)self)->area.x, ((ObClient*)self)->area.y, \
+                   ((ObClient*)self)->area.width, \
+                   ((ObClient*)self)->area.height, FALSE, TRUE, force)
 
 /*! Figure out where a window will end up and what size it will be if you
   told it to move/resize to these coordinates.
 
-  These values are what client_configure_full will give the window.
+  These values are what client_configure will give the window.
 
   @param x The x coordiante of the new position for the client.
   @param y The y coordiante of the new position for the client.
@@ -422,12 +427,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
                interactive move/resize, and then be TRUE for the last call
                only.
   @param force_reply Send a ConfigureNotify to the client regardless of if
-                     the position changed.
+                     the position/size changed.
 */
 void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
-                      gboolean user, gboolean final);
-
-void client_reconfigure(ObClient *self);
+                      gboolean user, gboolean final, gboolean force_reply);
 
 /*! Finds coordinates to keep a client on the screen.
   @param self The client
@@ -496,8 +499,11 @@ void client_kill(ObClient *self);
 /*! Sends the window to the specified desktop
   @param donthide If TRUE, the window will not be shown/hidden after its
                   desktop has been changed. Generally this should be FALSE.
+  @param dontraise If TRUE, the window will not be raised. Generally this should
+                   be FALSE.
 */
-void client_set_desktop(ObClient *self, guint target, gboolean donthide);
+void client_set_desktop(ObClient *self, guint target, gboolean donthide,
+                        gboolean dontraise);
 
 /*! Show the client if it should be shown. Returns if the window is shown. */
 gboolean client_show(ObClient *self);
index ce29db10b5945d0ad0220a507391b8103b74a4bd..cc67a4613568408d7f1e991ac8f93b8f64e85095 100644 (file)
@@ -286,7 +286,7 @@ static void send_to_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
 {
     g_assert(c);
 
-    client_set_desktop(c, e->id, FALSE);
+    client_set_desktop(c, e->id, FALSE, FALSE);
     /* the client won't even be on the screen anymore, so hide the menu */
     if (f)
         menu_frame_hide_all();
index 10a60fb4b35743380113f065483c5b4875b81f22..2eb8e13c4fe5623ae2459511f44453b92bc751af 100644 (file)
@@ -36,6 +36,7 @@ gboolean config_focus_last;
 gboolean config_focus_under_mouse;
 
 ObPlacePolicy config_place_policy;
+gboolean      config_place_center;
 
 gchar   *config_theme;
 gboolean config_theme_keepborder;
@@ -495,6 +496,8 @@ static void parse_placement(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     if ((n = parse_find_node("policy", node)))
         if (parse_contains("UnderMouse", doc, n))
             config_place_policy = OB_PLACE_POLICY_MOUSE;
+    if ((n = parse_find_node("center", node)))
+        config_place_center = parse_bool(doc, n);
 }
 
 static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
@@ -869,6 +872,7 @@ void config_startup(ObParseInst *i)
     parse_register(i, "focus", parse_focus, NULL);
 
     config_place_policy = OB_PLACE_POLICY_SMART;
+    config_place_center = TRUE;
 
     parse_register(i, "placement", parse_placement, NULL);
 
index f45196e29d8b59c054d6ff02cd82203768f21121..e8c70eb2489dc980beab81ee5b7e9eaf95cfdb4d 100644 (file)
@@ -76,6 +76,8 @@ extern gboolean config_focus_last;
 extern gboolean config_focus_under_mouse;
 
 extern ObPlacePolicy config_place_policy;
+/*! Place windows in the center of the free area */
+extern gboolean config_place_center;
 
 /*! When true windows' contents are refreshed while they are resized; otherwise
   they are not updated until the resize is complete */
index ff5b74cf9a34432d1cae4bffb30cfbdf8e901323..c128e4704464fe08608446a4bb4699c1680e81c4 100644 (file)
@@ -94,6 +94,10 @@ void dock_startup(gboolean reconfig)
                      RrColorPixel(ob_rr_theme->osd_border_color));
     XSetWindowBorderWidth(ob_display, dock->frame, ob_rr_theme->obwidth);
 
+    /* Setting the window type so xcompmgr can tell what it is */
+    PROP_SET32(dock->frame, net_wm_window_type, atom,
+               prop_atoms.net_wm_window_type_dock);
+
     g_hash_table_insert(window_map, &dock->frame, dock);
     stacking_add(DOCK_AS_WINDOW(dock));
 }
@@ -214,13 +218,13 @@ void dock_remove(ObDockApp *app, gboolean reparent)
 void dock_configure()
 {
     GList *it;
-    gint spot;
+    gint hspot, vspot;
     gint gravity;
-    gint minw, minh;
+    gint l, r, t, b;
     gint strw, strh;
     Rect *a;
 
-    RrMinSize(dock->a_frame, &minw, &minh);
+    RrMargins(dock->a_frame, &l, &t, &r, &b);
 
     dock->w = dock->h = 0;
 
@@ -239,21 +243,25 @@ void dock_configure()
         }
     }
 
-    spot = (config_dock_orient == OB_ORIENTATION_HORZ ? minw : minh) / 2;
+    dock->w += l + r;
+    dock->h += t + b;
+
+    hspot = l;
+    vspot = t;
 
     /* position the apps */
     for (it = dock->dock_apps; it; it = g_list_next(it)) {
         ObDockApp *app = it->data;
         switch (config_dock_orient) {
         case OB_ORIENTATION_HORZ:
-            app->x = spot;
+            app->x = hspot;
             app->y = (dock->h - app->h) / 2;
-            spot += app->w;
+            hspot += app->w;
             break;
         case OB_ORIENTATION_VERT:
             app->x = (dock->w - app->w) / 2;
-            app->y = spot;
-            spot += app->h;
+            app->y = vspot;
+            vspot += app->h;
             break;
         }
 
@@ -264,7 +272,7 @@ void dock_configure()
     dock->w += ob_rr_theme->obwidth * 2;
     dock->h += ob_rr_theme->obwidth * 2;
 
-    a = screen_physical_area();
+    a = screen_physical_area_all_monitors();
 
     /* calculate position */
     if (config_dock_floating) {
@@ -435,8 +443,8 @@ void dock_configure()
             break;
         case OB_DIRECTION_NORTH:
             STRUT_PARTIAL_SET(dock_strut, 0, strh, 0, 0,
-                              dock->x, dock->x + dock->w - 1,
-                              0, 0, 0, 0, 0, 0);
+                              0, 0, dock->x, dock->x + dock->w - 1,
+                              0, 0, 0, 0);
             break;
         case OB_DIRECTION_NORTHEAST:
             switch (config_dock_orient) {
@@ -498,9 +506,6 @@ void dock_configure()
         }
     }
 
-    dock->w += minw;
-    dock->h += minh;
-
     /* not used for actually sizing shit */
     dock->w -= ob_rr_theme->obwidth * 2;
     dock->h -= ob_rr_theme->obwidth * 2;
@@ -522,6 +527,8 @@ void dock_configure()
     dock->h += ob_rr_theme->obwidth * 2;
 
     screen_update_areas();
+
+    g_free(a);
 }
 
 void dock_app_configure(ObDockApp *app, gint w, gint h)
@@ -630,3 +637,8 @@ void dock_hide(gboolean hide)
         }
     }
 }
+
+void dock_get_area(Rect *a)
+{
+    RECT_SET(*a, dock->x, dock->y, dock->w, dock->h);
+}
index 051747c3f163789553c4beafc7e21098148de12b..48d6af49671223e13e69eed0a7364d2db1e16732 100644 (file)
@@ -82,4 +82,6 @@ void dock_remove(ObDockApp *app, gboolean reparent);
 void dock_app_drag(ObDockApp *app, XMotionEvent *e);
 void dock_app_configure(ObDockApp *app, gint w, gint h);
 
+void dock_get_area(Rect *a);
+
 #endif
index 12ecdac0398bbc5d7b6ecf2f78c9e8ff19448a93..8089792cc8748b630890f4f5a82a62fc92d99277 100644 (file)
@@ -1160,7 +1160,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
         {
             gint lw,lh;
-            gulong ignore_start;
 
             client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
 
@@ -1179,9 +1178,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
             ob_debug("Granting ConfigureRequest x %d y %d w %d h %d\n",
                      x, y, w, h);
-            ignore_start = event_start_ignore_all_enters();
-            client_configure(client, x, y, w, h, FALSE, TRUE);
-            event_end_ignore_all_enters(ignore_start);
+            client_configure(client, x, y, w, h, FALSE, TRUE, TRUE);
         }
         break;
     }
@@ -1264,7 +1261,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             if ((unsigned)e->xclient.data.l[0] < screen_num_desktops ||
                 (unsigned)e->xclient.data.l[0] == DESKTOP_ALL)
                 client_set_desktop(client, (unsigned)e->xclient.data.l[0],
-                                   FALSE);
+                                   FALSE, FALSE);
         } else if (msgtype == prop_atoms.net_wm_state) {
             gulong ignore_start;
 
@@ -1343,7 +1340,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 moveresize_end(TRUE);
         } else if (msgtype == prop_atoms.net_moveresize_window) {
             gint ograv, x, y, w, h;
-            gulong ignore_start;
 
             ograv = client->gravity;
 
@@ -1388,10 +1384,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
             client_find_onscreen(client, &x, &y, w, h, FALSE);
 
-            /* ignore enter events caused by these like ob actions do */
-            ignore_start = event_start_ignore_all_enters();
-            client_configure(client, x, y, w, h, FALSE, TRUE);
-            event_end_ignore_all_enters(ignore_start);
+            client_configure(client, x, y, w, h, FALSE, TRUE, FALSE);
 
             client->gravity = ograv;
         } else if (msgtype == prop_atoms.net_restack_window) {
@@ -1434,7 +1427,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
                     /* send a synthetic ConfigureNotify, cuz this is supposed
                        to be like a ConfigureRequest. */
-                    client_reconfigure(client);
+                    client_reconfigure(client, TRUE);
                 } else
                     ob_debug_type(OB_DEBUG_APP_BUGS,
                                   "_NET_RESTACK_WINDOW sent for window %s "
@@ -1481,25 +1474,15 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
         msgtype = e->xproperty.atom;
         if (msgtype == XA_WM_NORMAL_HINTS) {
-            gint x, y, w, h, lw, lh;
-
             ob_debug("Update NORMAL hints\n");
             client_update_normal_hints(client);
             /* normal hints can make a window non-resizable */
             client_setup_decor_and_functions(client, FALSE);
 
-            /* make sure the client's sizes are within its bounds */
-            RECT_TO_DIMS(client->area, x, y, w, h);
-            client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
-            if (!RECT_EQUAL_DIMS(client->area, x, y, w, h)) {
-                gulong ignore_start;
-
-                ob_debug("Configuring client x %d y %d w %d h %d\n",
-                         x, y, w, h);
-                ignore_start = event_start_ignore_all_enters();
-                client_configure(client, x, y, w, h, FALSE, TRUE);
-                event_end_ignore_all_enters(ignore_start);
-            }
+            /* make sure the client's sizes are within its bounds, but only
+               reconfigure the window if it needs to. emacs will update its
+               normal hints every time it receives a conigurenotify */
+            client_reconfigure(client, FALSE);
         } else if (msgtype == XA_WM_HINTS) {
             client_update_wmhints(client);
         } else if (msgtype == XA_WM_TRANSIENT_FOR) {
index 6d66382a5dc5d2d8f7a09c3af2d2b013cb396e0a..f34021a47b5f4528b497d05e8e849a1924386913 100644 (file)
@@ -23,6 +23,7 @@
 #include "grab.h"
 #include "client.h"
 #include "config.h"
+#include "group.h"
 #include "focus_cycle.h"
 #include "screen.h"
 #include "prop.h"
@@ -126,7 +127,7 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            backup fallback though)
         */
         if ((allow_omnipresent || c->desktop == screen_desktop) &&
-            focus_cycle_target_valid(c, FALSE, FALSE, FALSE, FALSE) &&
+            focus_valid_target(c, FALSE, FALSE, FALSE, FALSE) &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
@@ -145,7 +146,7 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            a splashscreen or a desktop window (save the desktop as a
            backup fallback though)
         */
-        if (focus_cycle_target_valid(c, FALSE, FALSE, FALSE, TRUE) &&
+        if (focus_valid_target(c, FALSE, FALSE, FALSE, TRUE) &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
@@ -267,3 +268,92 @@ ObClient *focus_order_find_first(guint desktop)
     }
     return NULL;
 }
+
+/*! Returns if a focus target has valid group siblings that can be cycled
+  to in its place */
+static gboolean focus_target_has_siblings(ObClient *ft,
+                                          gboolean iconic_windows,
+                                          gboolean all_desktops)
+                                                         
+{
+    GSList *it;
+
+    if (!ft->group) return FALSE;
+
+    for (it = ft->group->members; it; it = g_slist_next(it)) {
+        ObClient *c = it->data;
+        /* check that it's not a helper window to avoid infinite recursion */
+        if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
+            focus_valid_target(c, iconic_windows, all_desktops, FALSE, FALSE))
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+gboolean focus_valid_target(ObClient *ft,
+                            gboolean iconic_windows,
+                            gboolean all_desktops,
+                            gboolean dock_windows,
+                            gboolean desktop_windows)
+{
+    gboolean ok = FALSE;
+
+    /* it's on this desktop unless you want all desktops.
+
+       do this check first because it will usually filter out the most
+       windows */
+    ok = (all_desktops || ft->desktop == screen_desktop ||
+          ft->desktop == DESKTOP_ALL);
+
+    /* the window can receive focus somehow */
+    ok = ok && (ft->can_focus || ft->focus_notify);
+
+    /* the window is not iconic, or we're allowed to go to iconic ones */
+    ok = ok && (iconic_windows || !ft->iconic);
+
+    /* it's the right type of window */
+    if (dock_windows || desktop_windows)
+        ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) ||
+                    (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP));
+    /* modal windows are important and can always get focus if they are
+       visible and stuff, so don't change 'ok' based on their type */ 
+    else if (!ft->modal)
+        /* normal non-helper windows are valid targets */
+        ok = ok &&
+            ((client_normal(ft) && !client_helper(ft))
+             ||
+             /* helper windows are valid targets if... */
+             (client_helper(ft) &&
+              /* ...a window in its group already has focus ... */
+              ((focus_client && ft->group == focus_client->group) ||
+               /* ... or if there are no other windows in its group 
+                  that can be cycled to instead */
+               !focus_target_has_siblings(ft, iconic_windows, all_desktops))));
+
+    /* it's not set to skip the taskbar (unless it is a type that would be
+       expected to set this hint, or modal) */
+    ok = ok && ((ft->type == OB_CLIENT_TYPE_DOCK ||
+                 ft->type == OB_CLIENT_TYPE_DESKTOP ||
+                 ft->type == OB_CLIENT_TYPE_TOOLBAR ||
+                 ft->type == OB_CLIENT_TYPE_MENU ||
+                 ft->type == OB_CLIENT_TYPE_UTILITY) ||
+                ft->modal ||
+                !ft->skip_taskbar);
+
+    /* it's not going to just send focus off somewhere else (modal window),
+       unless that modal window is not one of our valid targets, then let
+       you choose this window and bring the modal one here */
+    {
+        ObClient *cft = client_focus_target(ft);
+        ok = ok && (ft == cft || !focus_valid_target(cft,
+                                                     iconic_windows,
+                                                     all_desktops,
+                                                     dock_windows,
+                                                     desktop_windows));
+    }
+
+    return ok;
+}
+
index f54da05cb803e97a2c934b5dab3050602c1c5c3f..f5033aee455ab429e60c5cab9ab17a8299dfb538 100644 (file)
@@ -63,4 +63,10 @@ void focus_order_to_bottom(struct _ObClient *c);
 
 struct _ObClient *focus_order_find_first(guint desktop);
 
+gboolean focus_valid_target(struct _ObClient *ft,
+                            gboolean iconic_windows,
+                            gboolean all_desktops,
+                            gboolean dock_windows,
+                            gboolean desktop_windows);
+
 #endif
index bd8a08465e95ef47aff9b01df6551441e14f7d37..a5ac4e68ce4d84f55c35cb8512fc863aca9fc677 100644 (file)
@@ -26,7 +26,6 @@
 #include "screen.h"
 #include "openbox.h"
 #include "debug.h"
-#include "group.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -37,13 +36,10 @@ static gboolean focus_cycle_all_desktops;
 static gboolean focus_cycle_dock_windows;
 static gboolean focus_cycle_desktop_windows;
 
-static gboolean  focus_target_has_siblings  (ObClient *ft,
-                                             gboolean iconic_windows,
-                                             gboolean all_desktops);
-static ObClient *focus_find_directional    (ObClient *c,
-                                            ObDirection dir,
-                                            gboolean dock_windows,
-                                            gboolean desktop_windows);
+static ObClient *focus_find_directional(ObClient *c,
+                                        ObDirection dir,
+                                        gboolean dock_windows,
+                                        gboolean desktop_windows);
 
 void focus_cycle_startup(gboolean reconfig)
 {
@@ -60,106 +56,17 @@ void focus_cycle_stop(ObClient *ifclient)
     /* stop focus cycling if the given client is a valid focus target,
        and so the cycling is being disrupted */
     if (focus_cycle_target && ifclient &&
-        focus_cycle_target_valid(ifclient,
-                                 focus_cycle_iconic_windows,
-                                 focus_cycle_all_desktops,
-                                 focus_cycle_dock_windows,
-                                 focus_cycle_desktop_windows))
+        focus_valid_target(ifclient,
+                           focus_cycle_iconic_windows,
+                           focus_cycle_all_desktops,
+                           focus_cycle_dock_windows,
+                           focus_cycle_desktop_windows))
     {
         focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
         focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
     }
 }
 
-/*! Returns if a focus target has valid group siblings that can be cycled
-  to in its place */
-static gboolean focus_target_has_siblings(ObClient *ft,
-                                          gboolean iconic_windows,
-                                          gboolean all_desktops)
-                                                         
-{
-    GSList *it;
-
-    if (!ft->group) return FALSE;
-
-    for (it = ft->group->members; it; it = g_slist_next(it)) {
-        ObClient *c = it->data;
-        /* check that it's not a helper window to avoid infinite recursion */
-        if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
-            focus_cycle_target_valid(c, iconic_windows, all_desktops, FALSE,
-                                     FALSE))
-        {
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-gboolean focus_cycle_target_valid(ObClient *ft,
-                                  gboolean iconic_windows,
-                                  gboolean all_desktops,
-                                  gboolean dock_windows,
-                                  gboolean desktop_windows)
-{
-    gboolean ok = FALSE;
-
-    /* it's on this desktop unless you want all desktops.
-
-       do this check first because it will usually filter out the most
-       windows */
-    ok = (all_desktops || ft->desktop == screen_desktop ||
-          ft->desktop == DESKTOP_ALL);
-
-    /* the window can receive focus somehow */
-    ok = ok && (ft->can_focus || ft->focus_notify);
-
-    /* the window is not iconic, or we're allowed to go to iconic ones */
-    ok = ok && (iconic_windows || !ft->iconic);
-
-    /* it's the right type of window */
-    if (dock_windows || desktop_windows)
-        ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) ||
-                    (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP));
-    /* modal windows are important and can always get focus if they are
-       visible and stuff, so don't change 'ok' based on their type */ 
-    else if (!ft->modal)
-        /* normal non-helper windows are valid targets */
-        ok = ok &&
-            ((client_normal(ft) && !client_helper(ft))
-             ||
-             /* helper windows are valid targets if... */
-             (client_helper(ft) &&
-              /* ...a window in its group already has focus ... */
-              ((focus_client && ft->group == focus_client->group) ||
-               /* ... or if there are no other windows in its group 
-                  that can be cycled to instead */
-               !focus_target_has_siblings(ft, iconic_windows, all_desktops))));
-
-    /* it's not set to skip the taskbar (unless it is a type that would be
-       expected to set this hint, or modal) */
-    ok = ok && ((ft->type == OB_CLIENT_TYPE_DOCK ||
-                 ft->type == OB_CLIENT_TYPE_DESKTOP ||
-                 ft->type == OB_CLIENT_TYPE_TOOLBAR ||
-                 ft->type == OB_CLIENT_TYPE_MENU ||
-                 ft->type == OB_CLIENT_TYPE_UTILITY) ||
-                ft->modal ||
-                !ft->skip_taskbar);
-
-    /* it's not going to just send focus off somewhere else (modal window),
-       unless that modal window is not one of our valid targets, then let
-       you choose this window and bring the modal one here */
-    {
-        ObClient *cft = client_focus_target(ft);
-        ok = ok && (ft == cft || !focus_cycle_target_valid(cft,
-                                                           iconic_windows,
-                                                           all_desktops,
-                                                           dock_windows,
-                                                           desktop_windows));
-    }
-
-    return ok;
-}
-
 void focus_cycle(gboolean forward, gboolean all_desktops,
                  gboolean dock_windows, gboolean desktop_windows,
                  gboolean linear, gboolean interactive,
@@ -211,11 +118,11 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
             if (it == NULL) it = g_list_last(list);
         }
         ft = it->data;
-        if (focus_cycle_target_valid(ft,
-                                     focus_cycle_iconic_windows,
-                                     focus_cycle_all_desktops,
-                                     focus_cycle_dock_windows,
-                                     focus_cycle_desktop_windows))
+        if (focus_valid_target(ft,
+                               focus_cycle_iconic_windows,
+                               focus_cycle_all_desktops,
+                               focus_cycle_dock_windows,
+                               focus_cycle_desktop_windows))
         {
             if (interactive) {
                 if (ft != focus_cycle_target) { /* prevents flicker */
@@ -283,8 +190,8 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
         /* the currently selected window isn't interesting */
         if (cur == c)
             continue;
-        if (!focus_cycle_target_valid(it->data, FALSE, FALSE, dock_windows,
-                                      desktop_windows))
+        if (!focus_valid_target(it->data, FALSE, FALSE, dock_windows,
+                                desktop_windows))
             continue;
 
         /* find the centre coords of this window, from the
@@ -385,11 +292,11 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
         GList *it;
 
         for (it = focus_order; it; it = g_list_next(it))
-            if (focus_cycle_target_valid(it->data,
-                                         focus_cycle_iconic_windows,
-                                         focus_cycle_all_desktops,
-                                         focus_cycle_dock_windows,
-                                         focus_cycle_desktop_windows))
+            if (focus_valid_target(it->data,
+                                   focus_cycle_iconic_windows,
+                                   focus_cycle_all_desktops,
+                                   focus_cycle_dock_windows,
+                                   focus_cycle_desktop_windows))
                 ft = it->data;
     }
         
index afdbdc799d049015d7589f582f2a89173424b5e0..2e32805f1948bef39a109a807c519471eb0a051a 100644 (file)
@@ -44,10 +44,4 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
 
 void focus_cycle_stop(struct _ObClient *ifclient);
 
-gboolean  focus_cycle_target_valid(struct _ObClient *ft,
-                                   gboolean iconic_windows,
-                                   gboolean all_desktops,
-                                   gboolean dock_windows,
-                                   gboolean desktop_windows);
-
 #endif
index 3ec14a5c40dadcb8d0613bd7123653e005844052..477619f557c37afc448cc2abba1961cbb2d9672a 100644 (file)
@@ -22,7 +22,6 @@
 #include "client.h"
 #include "screen.h"
 #include "focus.h"
-#include "focus_cycle.h"
 #include "openbox.h"
 #include "window.h"
 #include "event.h"
@@ -175,11 +174,11 @@ static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
     for (it = g_list_last(focus_order); it; it = g_list_previous(it)) {
         ObClient *ft = it->data;
 
-        if (focus_cycle_target_valid(ft,
-                                     iconic_windows,
-                                     all_desktops,
-                                     dock_windows,
-                                     desktop_windows))
+        if (focus_valid_target(ft,
+                               iconic_windows,
+                               all_desktops,
+                               dock_windows,
+                               desktop_windows))
         {
             gchar *text = popup_get_name(ft);
 
@@ -252,7 +251,7 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c)
     const ObFocusCyclePopupTarget *newtarget;
     gint newtargetx, newtargety;
 
-    screen_area = screen_physical_area_monitor_active();
+    screen_area = screen_physical_area_active();
 
     /* get the outside margins */
     RrMargins(p->a_bg, &ml, &mt, &mr, &mb);
@@ -434,6 +433,8 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c)
     RrPaint(p->a_text, p->text, textw, texth);
 
     p->last_target = newtarget;
+
+    g_free(screen_area);
 }
 
 void focus_cycle_popup_show(ObClient *c, gboolean iconic_windows,
@@ -505,13 +506,14 @@ void focus_cycle_popup_single_show(struct _ObClient *c,
         g_assert(popup.targets == NULL);
 
         /* position the popup */
-        a = screen_physical_area_monitor_active();
+        a = screen_physical_area_active();
         icon_popup_position(single_popup, CenterGravity,
                             a->x + a->width / 2, a->y + a->height / 2);
         icon_popup_height(single_popup, POPUP_HEIGHT);
         icon_popup_min_width(single_popup, POPUP_WIDTH);
         icon_popup_max_width(single_popup, MAX(a->width/3, POPUP_WIDTH));
         icon_popup_text_width(single_popup, popup.maxtextw);
+        g_free(a);
     }
 
     text = popup_get_name(c);
index 746bc610725a4038d785d088ae891149b6bc69a4..096b783943167ec33f096f25b70ddd58f66ad9ed 100644 (file)
@@ -124,6 +124,11 @@ ObFrame *frame_new(ObClient *client)
 
     mask |= CWEventMask;
     attrib.event_mask = ELEMENT_EVENTMASK;
+    self->innerleft = createWindow(self->window, NULL, mask, &attrib);
+    self->innertop = createWindow(self->window, NULL, mask, &attrib);
+    self->innerright = createWindow(self->window, NULL, mask, &attrib);
+    self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
+
     self->title = createWindow(self->window, NULL, mask, &attrib);
     self->titleleft = createWindow(self->window, NULL, mask, &attrib);
     self->titletop = createWindow(self->window, NULL, mask, &attrib);
@@ -141,11 +146,6 @@ ObFrame *frame_new(ObClient *client)
     self->left = createWindow(self->window, NULL, mask, &attrib);
     self->right = createWindow(self->window, NULL, mask, &attrib);
 
-    self->innerleft = createWindow(self->window, NULL, mask, &attrib);
-    self->innertop = createWindow(self->window, NULL, mask, &attrib);
-    self->innerright = createWindow(self->window, NULL, mask, &attrib);
-    self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
-
     self->label = createWindow(self->title, NULL, mask, &attrib);
     self->max = createWindow(self->title, NULL, mask, &attrib);
     self->close = createWindow(self->title, NULL, mask, &attrib);
@@ -248,6 +248,7 @@ void frame_show(ObFrame *self)
 {
     if (!self->visible) {
         self->visible = TRUE;
+        framerender_frame(self);
         XMapWindow(ob_display, self->client->window);
         XMapWindow(ob_display, self->window);
     }
@@ -334,6 +335,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
         self->decorations = self->client->decorations;
         self->max_horz = self->client->max_horz;
         self->max_vert = self->client->max_vert;
+        self->shaded = self->client->shaded;
 
         if (self->decorations & OB_FRAME_DECOR_BORDER ||
             (self->client->undecorated && config_theme_keepborder))
@@ -350,7 +352,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
 
         if (self->max_horz) {
             self->cbwidth_l = self->cbwidth_r = 0;
-            self->width = self->client->area.width - self->bwidth * 2;
+            self->width = self->client->area.width;
             if (self->max_vert)
                 self->cbwidth_b = 0;
         } else
@@ -427,9 +429,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 gint titlesides;
 
                 /* height of titleleft and titleright */
-                titlesides = (!self->max_horz ?
-                              ob_rr_theme->grip_width :
-                              self->size.top - self->bwidth);
+                titlesides = (!self->max_horz ? ob_rr_theme->grip_width : 0);
 
                 XMoveResizeWindow(ob_display, self->titletop,
                                   ob_rr_theme->grip_width + self->bwidth, 0,
@@ -474,7 +474,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
 
                 if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
                     XMoveResizeWindow(ob_display, self->titlebottom,
-                                      self->bwidth,
+                                      (self->max_horz ? 0 : self->bwidth),
                                       ob_rr_theme->title_height + self->bwidth,
                                       self->width,
                                       self->bwidth);
@@ -494,7 +494,8 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
 
             if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
                 XMoveResizeWindow(ob_display, self->title,
-                                  self->bwidth, self->bwidth,
+                                  (self->max_horz ? 0 : self->bwidth),
+                                  self->bwidth,
                                   self->width, ob_rr_theme->title_height);
 
                 XMapWindow(ob_display, self->title);
@@ -534,49 +535,63 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             layout_title(self);
 
         if (!fake) {
+            gint sidebwidth = self->max_horz ? 0 : self->bwidth;
+
             if (self->bwidth && self->size.bottom) {
                 XMoveResizeWindow(ob_display, self->handlebottom,
                                   ob_rr_theme->grip_width +
-                                  self->bwidth * 2,
+                                  self->bwidth + sidebwidth,
                                   self->size.top + self->client->area.height +
                                   self->size.bottom - self->bwidth,
                                   self->width - (ob_rr_theme->grip_width +
-                                                 self->bwidth) * 2,
+                                                 sidebwidth) * 2,
                                   self->bwidth);
 
-                XMoveResizeWindow(ob_display, self->lgripleft,
-                                  0,
-                                  self->size.top + self->client->area.height +
-                                  self->size.bottom -
-                                  (!self->max_horz ?
-                                   ob_rr_theme->grip_width :
-                                   self->size.bottom - self->cbwidth_b),
-                                  self->bwidth,
-                                  (!self->max_horz ?
-                                   ob_rr_theme->grip_width :
-                                   self->size.bottom - self->cbwidth_b));
-                XMoveResizeWindow(ob_display, self->rgripright,
-                                  self->size.left + self->client->area.width +
-                                  self->size.right - self->bwidth,
-                                  self->size.top + self->client->area.height +
-                                  self->size.bottom -
-                                  (!self->max_horz ?
-                                   ob_rr_theme->grip_width :
-                                   self->size.bottom - self->cbwidth_b),
-                                  self->bwidth,
-                                  (!self->max_horz ?
-                                   ob_rr_theme->grip_width :
-                                   self->size.bottom - self->cbwidth_b));
+                
+                if (sidebwidth) {
+                    XMoveResizeWindow(ob_display, self->lgripleft,
+                                      0,
+                                      self->size.top +
+                                      self->client->area.height +
+                                      self->size.bottom -
+                                      (!self->max_horz ?
+                                       ob_rr_theme->grip_width :
+                                       self->size.bottom - self->cbwidth_b),
+                                      self->bwidth,
+                                      (!self->max_horz ?
+                                       ob_rr_theme->grip_width :
+                                       self->size.bottom - self->cbwidth_b));
+                    XMoveResizeWindow(ob_display, self->rgripright,
+                                  self->size.left +
+                                      self->client->area.width +
+                                      self->size.right - self->bwidth,
+                                      self->size.top +
+                                      self->client->area.height +
+                                      self->size.bottom -
+                                      (!self->max_horz ?
+                                       ob_rr_theme->grip_width :
+                                       self->size.bottom - self->cbwidth_b),
+                                      self->bwidth,
+                                      (!self->max_horz ?
+                                       ob_rr_theme->grip_width :
+                                       self->size.bottom - self->cbwidth_b));
+
+                    XMapWindow(ob_display, self->lgripleft);
+                    XMapWindow(ob_display, self->rgripright);
+                } else {
+                    XUnmapWindow(ob_display, self->lgripleft);
+                    XUnmapWindow(ob_display, self->rgripright);
+                }
 
                 XMoveResizeWindow(ob_display, self->lgripbottom,
-                                  self->bwidth,
+                                  sidebwidth,
                                   self->size.top + self->client->area.height +
                                   self->size.bottom - self->bwidth,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->bwidth);
                 XMoveResizeWindow(ob_display, self->rgripbottom,
                                   self->size.left + self->client->area.width +
-                                  self->size.right - self->bwidth * 2 -
+                                  self->size.right - self->bwidth - sidebwidth -
                                   ob_rr_theme->grip_width,
                                   self->size.top + self->client->area.height +
                                   self->size.bottom - self->bwidth,
@@ -584,8 +599,6 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->bwidth);
 
                 XMapWindow(ob_display, self->handlebottom);
-                XMapWindow(ob_display, self->lgripleft);
-                XMapWindow(ob_display, self->rgripright);
                 XMapWindow(ob_display, self->lgripbottom);
                 XMapWindow(ob_display, self->rgripbottom);
 
@@ -594,10 +607,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 {
                     XMoveResizeWindow(ob_display, self->handletop,
                                       ob_rr_theme->grip_width +
-                                      self->bwidth * 2,
+                                      self->bwidth + sidebwidth,
                                       FRAME_HANDLE_Y(self),
                                       self->width - (ob_rr_theme->grip_width +
-                                                     self->bwidth) * 2,
+                                                     sidebwidth) * 2,
                                       self->bwidth);
                     XMapWindow(ob_display, self->handletop);
 
@@ -616,7 +629,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                           ob_rr_theme->handle_height);
 
                         XMoveResizeWindow(ob_display, self->lgriptop,
-                                          self->bwidth,
+                                          sidebwidth,
                                           FRAME_HANDLE_Y(self),
                                           ob_rr_theme->grip_width +
                                           self->bwidth,
@@ -624,8 +637,8 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                         XMoveResizeWindow(ob_display, self->rgriptop,
                                           self->size.left +
                                           self->client->area.width +
-                                          self->size.right - self->bwidth * 2 -
-                                          ob_rr_theme->grip_width,
+                                          self->size.right - self->bwidth -
+                                          sidebwidth - ob_rr_theme->grip_width,
                                           FRAME_HANDLE_Y(self),
                                           ob_rr_theme->grip_width +
                                           self->bwidth,
@@ -668,7 +681,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 ob_rr_theme->handle_height > 0)
             {
                 XMoveResizeWindow(ob_display, self->handle,
-                                  self->bwidth,
+                                  sidebwidth,
                                   FRAME_HANDLE_Y(self) + self->bwidth,
                                   self->width, ob_rr_theme->handle_height);
                 XMapWindow(ob_display, self->handle);
@@ -772,6 +785,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                     self->size.left, self->size.top);
 
         if (resized) {
+            self->need_render = TRUE;
             framerender_frame(self);
             frame_adjust_shape(self);
         }
@@ -804,15 +818,18 @@ static void frame_adjust_cursors(ObFrame *self)
     if ((self->functions & OB_CLIENT_FUNC_RESIZE) !=
         (self->client->functions & OB_CLIENT_FUNC_RESIZE) ||
         self->max_horz != self->client->max_horz ||
-        self->max_vert != self->client->max_vert)
+        self->max_vert != self->client->max_vert ||
+        self->shaded != self->client->shaded)
     {
         gboolean r = (self->client->functions & OB_CLIENT_FUNC_RESIZE) &&
             !(self->client->max_horz && self->client->max_vert);
         gboolean topbot = !self->client->max_vert;
+        gboolean sh = self->client->shaded;
         XSetWindowAttributes a;
 
-        /* these ones turn off when max vert */
-        a.cursor = ob_cursor(r && topbot ? OB_CURSOR_NORTH : OB_CURSOR_NONE);
+        /* these ones turn off when max vert, and some when shaded */
+        a.cursor = ob_cursor(r && topbot && !sh ?
+                             OB_CURSOR_NORTH : OB_CURSOR_NONE);
         XChangeWindowAttributes(ob_display, self->topresize, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->titletop, CWCursor, &a);
         a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
@@ -821,17 +838,21 @@ static void frame_adjust_cursors(ObFrame *self)
         XChangeWindowAttributes(ob_display, self->handlebottom, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->innerbottom, CWCursor, &a);
 
-        /* these ones don't */
-        a.cursor = ob_cursor(r ? OB_CURSOR_NORTHWEST : OB_CURSOR_NONE);
+        /* these ones change when shaded */
+        a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST) :
+                             OB_CURSOR_NONE);
+        XChangeWindowAttributes(ob_display, self->titleleft, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->tltresize, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->tllresize, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->titletopleft, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->titleleft, CWCursor, &a);
-        a.cursor = ob_cursor(r ? OB_CURSOR_NORTHEAST : OB_CURSOR_NONE);
+        a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST) :
+                             OB_CURSOR_NONE);
+        XChangeWindowAttributes(ob_display, self->titleright, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->trtresize, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->trrresize, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->titletopright, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->titleright, CWCursor, &a);
+
+        /* these ones are pretty static */
         a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
         XChangeWindowAttributes(ob_display, self->left, CWCursor, &a);
         XChangeWindowAttributes(ob_display, self->innerleft, CWCursor, &a);
@@ -863,23 +884,27 @@ void frame_adjust_client_area(ObFrame *self)
 
 void frame_adjust_state(ObFrame *self)
 {
+    self->need_render = TRUE;
     framerender_frame(self);
 }
 
 void frame_adjust_focus(ObFrame *self, gboolean hilite)
 {
     self->focused = hilite;
+    self->need_render = TRUE;
     framerender_frame(self);
     XFlush(ob_display);
 }
 
 void frame_adjust_title(ObFrame *self)
 {
+    self->need_render = TRUE;
     framerender_frame(self);
 }
 
 void frame_adjust_icon(ObFrame *self)
 {
+    self->need_render = TRUE;
     framerender_frame(self);
 }
 
@@ -1330,6 +1355,10 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y)
              (win == self->titletop || win == self->topresize))
         /* can't resize vertically when max vert */
         return OB_FRAME_CONTEXT_TITLEBAR;
+    else if (self->shaded &&
+             (win == self->titletop || win == self->topresize))
+        /* can't resize vertically when shaded */
+        return OB_FRAME_CONTEXT_TITLEBAR;
 
     if (win == self->window)            return OB_FRAME_CONTEXT_FRAME;
     if (win == self->label)             return OB_FRAME_CONTEXT_TITLEBAR;
@@ -1494,6 +1523,13 @@ void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h)
     }
 }
 
+void frame_rect_to_frame(ObFrame *self, Rect *r)
+{
+    r->width += self->size.left + self->size.right;
+    r->height += self->size.top + self->size.bottom;
+    frame_client_gravity(self, &r->x, &r->y, r->width, r->height);
+}
+
 static void flash_done(gpointer data)
 {
     ObFrame *self = data;
@@ -1572,10 +1608,12 @@ static gboolean frame_animate_iconify(gpointer p)
 
     if (self->client->icon_geometry.width == 0) {
         /* there is no icon geometry set so just go straight down */
-        Rect *a = screen_physical_area();
+        Rect *a = screen_physical_area_monitor
+            (screen_find_monitor(&self->area));
         iconx = self->area.x + self->area.width / 2 + 32;
         icony = a->y + a->width;
         iconw = 64;
+        g_free(a);
     } else {
         iconx = self->client->icon_geometry.x;
         icony = self->client->icon_geometry.y;
@@ -1639,7 +1677,7 @@ void frame_end_iconify_animation(ObFrame *self)
     else {
         /* Send a ConfigureNotify when the animation is done, this fixes
            KDE's pager showing the window in the wrong place. */
-        client_reconfigure(self->client);
+        client_reconfigure(self->client, TRUE);
     }
 
     /* we're not animating any more ! */
index eb868dcbbbd83af8a956a23dd7d568921968a69f..cf840bdf1b4aabee568579411a8bd38a2787992e 100644 (file)
@@ -167,6 +167,7 @@ struct _ObFrame
     gint      cbwidth_b;     /* client border width */
     gboolean  max_horz;      /* when maxed some decorations are hidden */
     gboolean  max_vert;      /* when maxed some decorations are hidden */
+    gboolean  shaded;        /* decorations adjust when shaded */
 
     /* the leftmost and rightmost elements in the titlebar */
     ObFrameContext leftmost;
@@ -184,6 +185,7 @@ struct _ObFrame
     gboolean  iconify_hover;
 
     gboolean  focused;
+    gboolean  need_render;
 
     gboolean  flashing;
     gboolean  flash_on;
@@ -231,6 +233,10 @@ void frame_client_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h);
 */
 void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h);
 
+/*! Convert a rectangle in client coordinates/sizes to what it would be
+  for the frame, given its current decorations sizes */
+void frame_rect_to_frame(ObFrame *self, Rect *r);
+
 void frame_flash_start(ObFrame *self);
 void frame_flash_stop(ObFrame *self);
 
index a02567bd0a24df31e007a2845d026b4e3dd75371..fe789d9618585af727dbd736e6e0a0e731d592d9 100644 (file)
@@ -36,6 +36,11 @@ void framerender_frame(ObFrame *self)
 {
     if (frame_iconify_animating(self))
         return; /* delay redrawing until the animation is done */
+    if (!self->need_render)
+        return;
+    if (!self->visible)
+        return;
+    self->need_render = FALSE;
 
     {
         gulong px;
index 67a82cded06ae4a984b5015f354f628c99f19557..43eb8ea3ab128b598174cb2e4948af7e6b5e4d21 100644 (file)
@@ -142,4 +142,7 @@ typedef struct _StrutPartial {
      (s1).bottom_start == (s2).bottom_start && \
      (s1).bottom_end == (s2).bottom_end)
 
+#define RANGES_INTERSECT(r1x, r1w, r2x, r2w) \
+    (r1x < r2x + r2w && r1x + r1w > r2x)
+
 #endif
index 85027d5dceb02c2931ffbc0e4f67018e88272803..3fa45b7c3d106eb2794a7029f7a40579cd079a72 100644 (file)
@@ -220,7 +220,7 @@ void grab_key_passive_count(int change)
 
 void ungrab_passive_key()
 {
-    ob_debug("ungrabbing %d passive grabs\n", passive_count);
+    /*ob_debug("ungrabbing %d passive grabs\n", passive_count);*/
     if (passive_count) {
         /* kill out passive grab */
         XUngrabKeyboard(ob_display, event_curtime);
index 9fd38def9452a03d1534cb3cef0a0ab2cedbcc47..7fdd18704eee5cfed3483054d070b2446474b1ed 100644 (file)
@@ -98,11 +98,12 @@ static void set_curpos(KeyBindingTree *newpos)
             g_free(oldtext);
         }
 
-        a = screen_physical_area_monitor_active();
+        a = screen_physical_area_active();
         popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10);
         /* 1 second delay for the popup to show */
         popup_delay_show(popup, G_USEC_PER_SEC, text);
         g_free(text);
+        g_free(a);
     } else {
         popup_hide(popup);
     }
index 6b3e729b0e0ed56868c1ca172d7bc6825880703c..fdb24afbad7b388ab6b89a279f20c6ef4092b12b 100644 (file)
@@ -343,6 +343,8 @@ void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y,
         *dx = MAX(*dx, a->x - x);
         *dy = MAX(*dy, a->y - y);
     }
+
+    g_free(a);
 }
 
 static void menu_entry_frame_render(ObMenuEntryFrame *self)
@@ -888,6 +890,8 @@ static void menu_frame_update(ObMenuFrame *self)
         }
     }
 
+    g_free(a);
+
     menu_frame_render(self);
 }
 
@@ -949,7 +953,9 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
     /* find the monitor the menu is on */
     for (i = 0; i < screen_num_monitors; ++i) {
         Rect *a = screen_physical_area_monitor(i);
-        if (RECT_CONTAINS(*a, x, y)) {
+        gboolean contains = RECT_CONTAINS(*a, x, y);
+        g_free(a);
+        if (contains) {
             self->monitor = i;
             break;
         }
index 232cc9b9716abe38d3a79138f1e969264fbe9758..534cd01148297c80793bae3cf16500c29c6b2e6c 100644 (file)
@@ -299,7 +299,7 @@ void moveresize_end(gboolean cancel)
         client_configure(moveresize_client, x, y,
                          (cancel ? start_cw : cur_x),
                          (cancel ? start_ch : cur_y),
-                         TRUE, TRUE);
+                         TRUE, TRUE, FALSE);
     }
 
     moveresize_in_progress = FALSE;
@@ -319,7 +319,7 @@ static void do_move(gboolean keyboard)
     client_configure(moveresize_client, cur_x, cur_y,
                      moveresize_client->area.width,
                      moveresize_client->area.height,
-                     TRUE, FALSE);
+                     TRUE, FALSE, FALSE);
     if (config_resize_popup_show == 2) /* == "Always" */
         popup_coords(moveresize_client, "%d x %d",
                      moveresize_client->frame->area.x,
@@ -377,7 +377,7 @@ static void do_resize()
 #endif
 
     get_resize_position(&x, &y, FALSE);
-    client_configure(moveresize_client, x, y, cur_x, cur_y, TRUE, FALSE);
+    client_configure(moveresize_client, x, y, cur_x, cur_y, TRUE, FALSE, FALSE);
 
     /* this would be better with a fixed width font ... XXX can do it better
        if there are 2 text boxes */
index e8d5ae4ddfab1dd05234068adbc99dcf38e46e2b..1e1e3bf0f5f6268478525550ba043c8cb46ecd42 100644 (file)
@@ -337,7 +337,7 @@ gint main(gint argc, gchar **argv)
                     frame_adjust_area(c->frame, TRUE, TRUE, FALSE);
                     /* the decor sizes may have changed, so the windows may
                        end up in new positions */
-                    client_reconfigure(c);
+                    client_reconfigure(c, FALSE);
                 }
             }
 
index c30a27f947776eef381f5fd473f0ff4b2fb4b7ca..845becdb93d67fe74036f37757aa28de7c664458 100644 (file)
 #include "frame.h"
 #include "focus.h"
 #include "config.h"
+#include "dock.h"
 #include "debug.h"
 
+extern ObDock *dock;
+
 static void add_choice(guint *choice, guint mychoice)
 {
     guint i;
@@ -45,17 +48,17 @@ static Rect *pick_pointer_head(ObClient *c)
 
     screen_pointer_pos(&px, &py);
      
-    for (i = 0; i < screen_num_monitors; ++i) {  
-        if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) {
-            return screen_area_monitor(c->desktop, i);
-        }
+    for (i = 0; i < screen_num_monitors; ++i) {
+        Rect *monitor = screen_physical_area_monitor(i);
+        gboolean contain = RECT_CONTAINS(*monitor, px, py);
+        g_free(monitor);
+        if (contain)
+            return screen_area(c->desktop, i, NULL);
     }
     g_assert_not_reached();
 }
 
-/*! Pick a monitor to place a window on.
-  The returned array value should be freed with g_free. The areas within the
-  array should not be freed. */
+/*! Pick a monitor to place a window on. */
 static Rect **pick_head(ObClient *c)
 {
     Rect **area;
@@ -112,19 +115,23 @@ static Rect **pick_head(ObClient *c)
 
     screen_pointer_pos(&px, &py);
 
-    for (i = 0; i < screen_num_monitors; i++)
-        if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) {
+    for (i = 0; i < screen_num_monitors; i++) {
+        Rect *monitor = screen_physical_area_monitor(i);
+        gboolean contain = RECT_CONTAINS(*monitor, px, py);
+        g_free(monitor);
+        if (contain) {
             add_choice(choice, i);
             ob_debug("placement adding choice %d for mouse pointer\n", i);
             break;
         }
+    }
 
     /* add any leftover choices */
     for (i = 0; i < screen_num_monitors; ++i)
         add_choice(choice, i);
 
     for (i = 0; i < screen_num_monitors; ++i)
-        area[i] = screen_area_monitor(c->desktop, choice[i]);
+        area[i] = screen_area(c->desktop, choice[i], NULL);
 
     return area;
 }
@@ -148,6 +155,8 @@ static gboolean place_random(ObClient *client, gint *x, gint *y)
     if (b > t) *y = g_random_int_range(t, b + 1);
     else       *y = areas[i]->y;
 
+    for (i = 0; i < screen_num_monitors; ++i)
+        g_free(areas[i]);
     g_free(areas);
 
     return TRUE;
@@ -214,14 +223,15 @@ static GSList* area_remove(GSList *list, Rect *a)
 }
 
 enum {
-    IGNORE_FULLSCREEN = 1 << 0,
-    IGNORE_MAXIMIZED  = 1 << 1,
-    IGNORE_MENUTOOL   = 1 << 2,
-    /*IGNORE_SHADED     = 1 << 3,*/
-    IGNORE_NONGROUP   = 1 << 3,
-    IGNORE_BELOW      = 1 << 4,
-    IGNORE_NONFOCUS   = 1 << 5,
-    IGNORE_END        = 1 << 6
+    IGNORE_FULLSCREEN = 1,
+    IGNORE_MAXIMIZED  = 2,
+    IGNORE_MENUTOOL   = 3,
+    /*IGNORE_SHADED     = 3,*/
+    IGNORE_NONGROUP   = 4,
+    IGNORE_BELOW      = 5,
+    /*IGNORE_NONFOCUS   = 1 << 5,*/
+    IGNORE_DOCK       = 6,
+    IGNORE_END        = 7
 };
 
 static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
@@ -231,6 +241,7 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
     gboolean ret;
     gint maxsize;
     GSList *spaces = NULL, *sit, *maxit;
+    guint i;
 
     areas = pick_head(c);
     ret = FALSE;
@@ -238,7 +249,7 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
     maxit = NULL;
 
     /* try ignoring different things to find empty space */
-    for (ignore = 0; ignore < IGNORE_END && !ret; ignore = (ignore << 1) + 1) {
+    for (ignore = 0; ignore < IGNORE_END && !ret; ignore++) {
         guint i;
 
         /* try all monitors in order of preference */
@@ -267,31 +278,38 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
                     test->type == OB_CLIENT_TYPE_DESKTOP) continue;
 
 
-                if ((ignore & IGNORE_FULLSCREEN) &&
+                if ((ignore >= IGNORE_FULLSCREEN) &&
                     test->fullscreen) continue;
-                if ((ignore & IGNORE_MAXIMIZED) &&
+                if ((ignore >= IGNORE_MAXIMIZED) &&
                     test->max_horz && test->max_vert) continue;
-                if ((ignore & IGNORE_MENUTOOL) &&
+                if ((ignore >= IGNORE_MENUTOOL) &&
                     (test->type == OB_CLIENT_TYPE_MENU ||
                      test->type == OB_CLIENT_TYPE_TOOLBAR) &&
                     client_has_parent(c)) continue;
                 /*
-                if ((ignore & IGNORE_SHADED) &&
+                if ((ignore >= IGNORE_SHADED) &&
                     test->shaded) continue;
                 */
-                if ((ignore & IGNORE_NONGROUP) &&
+                if ((ignore >= IGNORE_NONGROUP) &&
                     client_has_group_siblings(c) &&
                     test->group != c->group) continue;
-                if ((ignore & IGNORE_BELOW) &&
+                if ((ignore >= IGNORE_BELOW) &&
                     test->layer < c->layer) continue;
-                if ((ignore & IGNORE_NONFOCUS) &&
+                /*
+                if ((ignore >= IGNORE_NONFOCUS) &&
                     focus_client != test) continue;
-
+                */
                 /* don't ignore this window, so remove it from the available
                    area */
                 spaces = area_remove(spaces, &test->frame->area);
             }
 
+            if (ignore < IGNORE_DOCK) {
+                Rect a;
+                dock_get_area(&a);
+                spaces = area_remove(spaces, &a);
+            }
+
             for (sit = spaces; sit; sit = g_slist_next(sit)) {
                 Rect *r = sit->data;
 
@@ -308,8 +326,12 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
                 Rect *r = maxit->data;
 
                 /* center it in the area */
-                *x = r->x + (r->width - c->frame->area.width) / 2;
-                *y = r->y + (r->height - c->frame->area.height) / 2;
+                *x = r->x;
+                *y = r->y;
+                if (config_place_center) {
+                    *x += (r->width - c->frame->area.width) / 2;
+                    *y += (r->height - c->frame->area.height) / 2;
+                }
                 ret = TRUE;
             }
 
@@ -320,6 +342,8 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
         }
     }
 
+    for (i = 0; i < screen_num_monitors; ++i)
+        g_free(areas[i]);
     g_free(areas);
     return ret;
 }
@@ -360,13 +384,18 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y,
         screen = pick_pointer_head(client);
     else if (settings->monitor > 0 &&
              (guint)settings->monitor <= screen_num_monitors)
-        screen = screen_area_monitor(client->desktop,
-                                     (guint)settings->monitor - 1);
+        screen = screen_area(client->desktop, (guint)settings->monitor - 1,
+                             NULL);
     else {
-        Rect **all = NULL;
-        all = pick_head(client);
-        screen = all[0];
-        g_free(all); /* the areas themselves don't need to be freed */
+        Rect **areas;
+        guint i;
+
+        areas = pick_head(client);
+        screen = areas[0];
+
+        for (i = 0; i < screen_num_monitors; ++i)
+            g_free(areas[i]);
+        g_free(areas);
     }
 
     if (settings->center_x)
@@ -422,12 +451,15 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y)
         client->type == OB_CLIENT_TYPE_SPLASH)
     {
         Rect **areas;
+        guint i;
 
         areas = pick_head(client);
 
         *x = (areas[0]->width - client->frame->area.width) / 2 + areas[0]->x;
         *y = (areas[0]->height - client->frame->area.height) / 2 + areas[0]->y;
 
+        for (i = 0; i < screen_num_monitors; ++i)
+            g_free(areas[i]);
         g_free(areas);
         return TRUE;
     }
@@ -450,7 +482,6 @@ gboolean place_client(ObClient *client, gint *x, gint *y,
         (config_place_policy == OB_PLACE_POLICY_MOUSE &&
          place_under_mouse(client, x, y)) ||
         place_nooverlap(client, x, y) ||
-        place_under_mouse(client, x, y) ||
         place_random(client, x, y);
     g_assert(ret);
 
index 77f751fcf888ba77be89c7b2facaf4c359906c1f..f5072748734953f70dff767858596bab3ea6f232 100644 (file)
@@ -154,9 +154,10 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
     gint emptyx, emptyy; /* empty space between elements */
     gint textx, texty, textw, texth;
     gint iconx, icony, iconw, iconh;
-    Rect *area;
+    Rect *area, mon;
 
-    area = screen_physical_area();
+    RECT_SET(mon, self->x, self->y, 1, 1);
+    area = screen_physical_area_monitor(screen_find_monitor(&mon));
 
     /* when there is no icon and the text is not parent relative, then 
        fill the whole dialog with the text appearance, don't use the bg at all
@@ -281,6 +282,8 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
             popup_show_timeout(self);
         }
     }
+
+    g_free(area);
 }
 
 void popup_hide(ObPopup *self)
index ab71d132f68efc7470d9fe49fca72888ef2b229e..211a012c78215461a5983d3ee5fc4deb7aa95d81 100644 (file)
@@ -61,6 +61,8 @@ void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y)
 
         /* don't snap to self or non-visibles */
         if (!target->frame->visible || target == c) continue; 
+        /* don't snap to windows set to below and skip_taskbar (desklets) */
+        if (target->below && !c->below && target->skip_taskbar) continue;
 
         tl = RECT_LEFT(target->frame->area) - 1;
         tt = RECT_TOP(target->frame->area) - 1;
@@ -123,6 +125,7 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
     gint pl, pt, pr, pb; /* physical screen area edges */
     gint cl, ct, cr, cb; /* current edges */
     gint w, h; /* current size */
+    Rect desired_area;
 
     if (!resist) return;
 
@@ -140,13 +143,19 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
     ct = RECT_TOP(c->frame->area);
     cr = RECT_RIGHT(c->frame->area);
     cb = RECT_BOTTOM(c->frame->area);
+
+    RECT_SET(desired_area, *x, *y, c->area.width, c->area.height);
     
     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))
+        if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
+            g_free(parea);
             continue;
+        }
+
+        area = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS,
+                           &desired_area);
 
         al = RECT_LEFT(*area);
         at = RECT_TOP(*area);
@@ -174,6 +183,9 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
             *y = pt;
         else if (cb <= pb && b > pb && b < pb + resist)
             *y = pb - h + 1;
+
+        g_free(area);
+        g_free(parea);
     }
 
     frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height);
@@ -207,6 +219,8 @@ void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h,
 
         /* don't snap to invisibles or ourself */
         if (!target->frame->visible || target == c) continue; 
+        /* don't snap to windows set to below and skip_taskbar (desklets) */
+        if (target->below && !c->below && target->skip_taskbar) continue;
 
         tl = RECT_LEFT(target->frame->area);
         tr = RECT_RIGHT(target->frame->area);
@@ -276,6 +290,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
     gint pl, pt, pr, pb; /* physical screen boundaries */
     gint incw, inch;
     guint i;
+    Rect desired_area;
 
     if (!resist) return;
 
@@ -287,12 +302,18 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
     incw = c->size_inc.width;
     inch = c->size_inc.height;
 
+    RECT_SET(desired_area, c->area.x, c->area.y, *w, *h);
+
     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))
+        if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
+            g_free(parea);
             continue;
+        }
+
+        area = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS,
+                           &desired_area);
 
         /* get the screen boundaries */
         al = RECT_LEFT(*area);
@@ -347,5 +368,8 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
                 *h = b - pt + 1;
             break;
         }
+
+        g_free(area);
+        g_free(parea);
     }
 }
index 7e2d8645ce3fd3602f7c1d37615f90246cbfec7e..f9b1eb6c643da0489eb01ff139b8e794db1335ca 100644 (file)
@@ -65,8 +65,13 @@ gchar  **screen_desktop_names;
 Window   screen_support_win;
 Time     screen_desktop_user_time = CurrentTime;
 
-static Rect  **area; /* array of desktop holding array of xinerama areas */
-static Rect  *monitor_area;
+/*! An array of desktops, holding array of areas per monitor */
+static Rect  *monitor_area = NULL;
+/*! An array of desktops, holding an array of struts */
+static GSList *struts_top = NULL;
+static GSList *struts_left = NULL;
+static GSList *struts_right = NULL;
+static GSList *struts_bottom = NULL;
 
 static ObPagerPopup *desktop_cycle_popup;
 
@@ -436,8 +441,6 @@ void screen_startup(gboolean reconfig)
 
 void screen_shutdown(gboolean reconfig)
 {
-    Rect **r;
-
     pager_popup_free(desktop_cycle_popup);
 
     if (reconfig)
@@ -457,11 +460,6 @@ void screen_shutdown(gboolean reconfig)
 
     g_strfreev(screen_desktop_names);
     screen_desktop_names = NULL;
-
-    for (r = area; *r; ++r)
-        g_free(*r);
-    g_free(area);
-    area = NULL;
 }
 
 void screen_resize()
@@ -498,7 +496,7 @@ void screen_set_num_desktops(guint num)
 {
     guint old;
     gulong *viewport;
-    GList *it;
+    GList *it, *stacking_copy;
 
     g_assert(num > 0);
 
@@ -518,11 +516,21 @@ void screen_set_num_desktops(guint num)
     /* the number of rows/columns will differ */
     screen_update_layout();
 
-    /* move windows on desktops that will no longer exist! */
-    for (it = client_list; it; it = g_list_next(it)) {
-        ObClient *c = it->data;
-        if (c->desktop >= num && c->desktop != DESKTOP_ALL)
-            client_set_desktop(c, num - 1, FALSE);
+    /* move windows on desktops that will no longer exist!
+       make a copy of the list cuz we're changing it */
+    stacking_copy = g_list_copy(stacking_list);
+    for (it = g_list_last(stacking_copy); it; it = g_list_previous(it)) {
+        if (WINDOW_IS_CLIENT(it->data)) {
+            ObClient *c = it->data;
+            if (c->desktop != DESKTOP_ALL && c->desktop >= num)
+                client_set_desktop(c, num - 1, FALSE, TRUE);
+            /* raise all the windows that are on the current desktop which
+               is being merged */
+            else if (screen_desktop == num - 1 &&
+                     (c->desktop == DESKTOP_ALL ||
+                      c->desktop == screen_desktop))
+                stacking_raise(WINDOW_AS_CLIENT(c));
+        }
     }
  
     /* change our struts/area to match (after moving windows) */
@@ -563,7 +571,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
     ignore_start = event_start_ignore_all_enters();
 
     if (moveresize_client)
-        client_set_desktop(moveresize_client, num, TRUE);
+        client_set_desktop(moveresize_client, num, TRUE, FALSE);
 
     /* show windows before hiding the rest to lessen the enter/leave events */
 
@@ -581,6 +589,11 @@ void screen_set_desktop(guint num, gboolean dofocus)
     allow_omni = focus_client && (client_normal(focus_client) &&
                                   focus_client->desktop == DESKTOP_ALL);
 
+    /* the client moved there already so don't move focus. prevent flicker
+       on sendtodesktop + follow */
+    if (focus_client && focus_client->desktop == screen_desktop)
+        dofocus = FALSE;
+
     /* have to try focus here because when you leave an empty desktop
        there is no focus out to watch for. also, we have different rules
        here. we always allow it to look under the mouse pointer if
@@ -733,7 +746,7 @@ void screen_desktop_popup(guint d, gboolean show)
     if (!show) {
         pager_popup_hide(desktop_cycle_popup);
     } else {
-        a = screen_physical_area_monitor_active();
+        a = screen_physical_area_active();
         pager_popup_position(desktop_cycle_popup, CenterGravity,
                              a->x + a->width / 2, a->y + a->height / 2);
         pager_popup_icon_size_multiplier(desktop_cycle_popup,
@@ -1086,249 +1099,294 @@ void screen_install_colormap(ObClient *client, gboolean install)
     }
 }
 
-static inline void
-screen_area_add_strut_left(const StrutPartial *s, const Rect *monitor_area,
-                           gint edge, Strut *ret)
-{
-    if (s->left &&
-        ((s->left_end <= s->left_start) ||
-         (RECT_TOP(*monitor_area) < s->left_end &&
-          RECT_BOTTOM(*monitor_area) > s->left_start)))
-        ret->left = MAX(ret->left, edge);
-}
-
-static inline void
-screen_area_add_strut_top(const StrutPartial *s, const Rect *monitor_area,
-                          gint edge, Strut *ret)
-{
-    if (s->top &&
-        ((s->top_end <= s->top_start) ||
-         (RECT_LEFT(*monitor_area) < s->top_end &&
-          RECT_RIGHT(*monitor_area) > s->top_start)))
-        ret->top = MAX(ret->top, edge);
-}
-
-static inline void
-screen_area_add_strut_right(const StrutPartial *s, const Rect *monitor_area,
-                            gint edge, Strut *ret)
-{
-    if (s->right &&
-        ((s->right_end <= s->right_start) ||
-         (RECT_TOP(*monitor_area) < s->right_end &&
-          RECT_BOTTOM(*monitor_area) > s->right_start)))
-        ret->right = MAX(ret->right, edge);
-}
-
-static inline void
-screen_area_add_strut_bottom(const StrutPartial *s, const Rect *monitor_area,
-                             gint edge, Strut *ret)
-{
-    if (s->bottom &&
-        ((s->bottom_end <= s->bottom_start) ||
-         (RECT_LEFT(*monitor_area) < s->bottom_end &&
-          RECT_RIGHT(*monitor_area) > s->bottom_start)))
-        ret->bottom = MAX(ret->bottom, edge);
+#define STRUT_LEFT_ON_MONITOR(s, i) \
+    (RANGES_INTERSECT(s->left_start, s->left_end - s->left_start + 1, \
+                      monitor_area[i].y, monitor_area[i].height))
+#define STRUT_RIGHT_ON_MONITOR(s, i) \
+    (RANGES_INTERSECT(s->right_start, s->right_end - s->right_start + 1, \
+                      monitor_area[i].y, monitor_area[i].height))
+#define STRUT_TOP_ON_MONITOR(s, i) \
+    (RANGES_INTERSECT(s->top_start, s->top_end - s->top_start + 1, \
+                      monitor_area[i].x, monitor_area[i].width))
+#define STRUT_BOTTOM_ON_MONITOR(s, i) \
+    (RANGES_INTERSECT(s->bottom_start, s->bottom_end - s->bottom_start + 1, \
+                      monitor_area[i].x, monitor_area[i].width))
+
+typedef struct {
+    guint desktop;
+    StrutPartial *strut;
+} ObScreenStrut;
+
+#define RESET_STRUT_LIST(sl) \
+    (g_slist_free(sl), sl = NULL)
+
+#define ADD_STRUT_TO_LIST(sl, d, s) \
+{ \
+    ObScreenStrut *ss = g_new(ObScreenStrut, 1); \
+    ss->desktop = d; \
+    ss->strut = s;  \
+    sl = g_slist_prepend(sl, ss); \
 }
 
 void screen_update_areas()
 {
-    guint i, x;
+    guint i, j;
     gulong *dims;
     GList *it;
-    gint o;
+    GSList *sit;
+
+    ob_debug("updating screen areas\n");
 
     g_free(monitor_area);
     extensions_xinerama_screens(&monitor_area, &screen_num_monitors);
 
-    if (area) {
-        for (i = 0; area[i]; ++i)
-            g_free(area[i]);
-        g_free(area);
-    }
-
-    area = g_new(Rect*, screen_num_desktops + 2);
-    for (i = 0; i < screen_num_desktops + 1; ++i)
-        area[i] = g_new0(Rect, screen_num_monitors + 1);
-    area[i] = NULL;
-     
-    dims = g_new(gulong, 4 * screen_num_desktops);
+    dims = g_new(gulong, 4 * screen_num_desktops * screen_num_monitors);
 
-    for (i = 0; i < screen_num_desktops + 1; ++i) {
-        Strut *struts;
-        gint l, r, t, b;
+    RESET_STRUT_LIST(struts_left);
+    RESET_STRUT_LIST(struts_top);
+    RESET_STRUT_LIST(struts_right);
+    RESET_STRUT_LIST(struts_bottom);
 
-        struts = g_new0(Strut, screen_num_monitors);
-
-        /* calc the xinerama areas */
-        for (x = 0; x < screen_num_monitors; ++x) {
-            area[i][x] = monitor_area[x];
-            if (x == 0) {
-                l = monitor_area[x].x;
-                t = monitor_area[x].y;
-                r = monitor_area[x].x + monitor_area[x].width - 1;
-                b = monitor_area[x].y + monitor_area[x].height - 1;
-            } else {
-                l = MIN(l, monitor_area[x].x);
-                t = MIN(t, monitor_area[x].y);
-                r = MAX(r, monitor_area[x].x + monitor_area[x].width - 1);
-                b = MAX(b, monitor_area[x].y + monitor_area[x].height - 1);
-            }
-        }
-        RECT_SET(area[i][x], l, t, r - l + 1, b - t + 1);
-
-        /* apply the struts */
-
-        /* find the left-most xin heads, i do this in 2 loops :| */
-        o = area[i][0].x;
-        for (x = 1; x < screen_num_monitors; ++x)
-            o = MIN(o, area[i][x].x);
-
-        for (x = 0; x < screen_num_monitors; ++x) {
-            for (it = client_list; it; it = g_list_next(it)) {
-                ObClient *c = it->data;
-                screen_area_add_strut_left(&c->strut,
-                                           &monitor_area[x],
-                                           o + c->strut.left - area[i][x].x,
-                                           &struts[x]);
-            }
-            screen_area_add_strut_left(&dock_strut,
-                                       &monitor_area[x],
-                                       o + dock_strut.left - area[i][x].x,
-                                       &struts[x]);
-
-            area[i][x].x += struts[x].left;
-            area[i][x].width -= struts[x].left;
+    /* collect the struts */
+    for (it = client_list; it; it = g_list_next(it)) {
+        ObClient *c = it->data;
+        if (c->strut.left)
+            ADD_STRUT_TO_LIST(struts_left, c->desktop, &c->strut);
+        if (c->strut.top)
+            ADD_STRUT_TO_LIST(struts_top, c->desktop, &c->strut);
+        if (c->strut.right)
+            ADD_STRUT_TO_LIST(struts_right, c->desktop, &c->strut);
+        if (c->strut.bottom)
+            ADD_STRUT_TO_LIST(struts_bottom, c->desktop, &c->strut);
+    }
+    if (dock_strut.left)
+        ADD_STRUT_TO_LIST(struts_left, DESKTOP_ALL, &dock_strut);
+    if (dock_strut.top)
+        ADD_STRUT_TO_LIST(struts_top, DESKTOP_ALL, &dock_strut);
+    if (dock_strut.right)
+        ADD_STRUT_TO_LIST(struts_right, DESKTOP_ALL, &dock_strut);
+    if (dock_strut.bottom)
+        ADD_STRUT_TO_LIST(struts_bottom, DESKTOP_ALL, &dock_strut);
+
+    /* set up the work areas to be full screen */
+    for (i = 0; i < screen_num_monitors; ++i)
+        for (j = 0; j < screen_num_desktops; ++j) {
+            dims[(i * screen_num_desktops + j) * 4+0] = monitor_area[i].x;
+            dims[(i * screen_num_desktops + j) * 4+1] = monitor_area[i].y;
+            dims[(i * screen_num_desktops + j) * 4+2] = monitor_area[i].width;
+            dims[(i * screen_num_desktops + j) * 4+3] = monitor_area[i].height;
         }
 
-        /* find the top-most xin heads, i do this in 2 loops :| */
-        o = area[i][0].y;
-        for (x = 1; x < screen_num_monitors; ++x)
-            o = MIN(o, area[i][x].y);
-
-        for (x = 0; x < screen_num_monitors; ++x) {
-            for (it = client_list; it; it = g_list_next(it)) {
-                ObClient *c = it->data;
-                screen_area_add_strut_top(&c->strut,
-                                           &monitor_area[x],
-                                           o + c->strut.top - area[i][x].y,
-                                           &struts[x]);
-            }
-            screen_area_add_strut_top(&dock_strut,
-                                      &monitor_area[x],
-                                      o + dock_strut.top - area[i][x].y,
-                                      &struts[x]);
+    /* calculate the work areas from the struts */
+    for (i = 0; i < screen_num_monitors; ++i)
+        for (j = 0; j < screen_num_desktops; ++j) {
+            gint l = 0, r = 0, t = 0, b = 0;
 
-            area[i][x].y += struts[x].top;
-            area[i][x].height -= struts[x].top;
-        }
+            /* only add the strut to the area if it touches the monitor */
 
-        /* find the right-most xin heads, i do this in 2 loops :| */
-        o = area[i][0].x + area[i][0].width - 1;
-        for (x = 1; x < screen_num_monitors; ++x)
-            o = MAX(o, area[i][x].x + area[i][x].width - 1);
-
-        for (x = 0; x < screen_num_monitors; ++x) {
-            for (it = client_list; it; it = g_list_next(it)) {
-                ObClient *c = it->data;
-                screen_area_add_strut_right(&c->strut,
-                                           &monitor_area[x],
-                                           (area[i][x].x +
-                                            area[i][x].width - 1) -
-                                            (o - c->strut.right),
-                                            &struts[x]);
+            for (sit = struts_left; sit; sit = g_slist_next(sit)) {
+                ObScreenStrut *s = sit->data;
+                if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+                    STRUT_LEFT_ON_MONITOR(s->strut, i))
+                    l = MAX(l, s->strut->left);
             }
-            screen_area_add_strut_right(&dock_strut,
-                                        &monitor_area[x],
-                                        (area[i][x].x +
-                                         area[i][x].width - 1) -
-                                        (o - dock_strut.right),
-                                        &struts[x]);
-
-            area[i][x].width -= struts[x].right;
-        }
-
-        /* find the bottom-most xin heads, i do this in 2 loops :| */
-        o = area[i][0].y + area[i][0].height - 1;
-        for (x = 1; x < screen_num_monitors; ++x)
-            o = MAX(o, area[i][x].y + area[i][x].height - 1);
-
-        for (x = 0; x < screen_num_monitors; ++x) {
-            for (it = client_list; it; it = g_list_next(it)) {
-                ObClient *c = it->data;
-                screen_area_add_strut_bottom(&c->strut,
-                                             &monitor_area[x],
-                                             (area[i][x].y +
-                                              area[i][x].height - 1) - \
-                                             (o - c->strut.bottom),
-                                             &struts[x]);
+            for (sit = struts_top; sit; sit = g_slist_next(sit)) {
+                ObScreenStrut *s = sit->data;
+                if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+                    STRUT_TOP_ON_MONITOR(s->strut, i))
+                    t = MAX(t, s->strut->top);
+            }
+            for (sit = struts_right; sit; sit = g_slist_next(sit)) {
+                ObScreenStrut *s = sit->data;
+                if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+                    STRUT_RIGHT_ON_MONITOR(s->strut, i))
+                    r = MAX(r, s->strut->right);
+            }
+            for (sit = struts_bottom; sit; sit = g_slist_next(sit)) {
+                ObScreenStrut *s = sit->data;
+                if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
+                    STRUT_BOTTOM_ON_MONITOR(s->strut, i))
+                    b = MAX(b, s->strut->bottom);
             }
-            screen_area_add_strut_bottom(&dock_strut,
-                                         &monitor_area[x],
-                                         (area[i][x].y +
-                                          area[i][x].height - 1) - \
-                                         (o - dock_strut.bottom),
-                                         &struts[x]);
-
-            area[i][x].height -= struts[x].bottom;
-        }
 
-        l = RECT_LEFT(area[i][0]);
-        t = RECT_TOP(area[i][0]);
-        r = RECT_RIGHT(area[i][0]);
-        b = RECT_BOTTOM(area[i][0]);
-        for (x = 1; x < screen_num_monitors; ++x) {
-            l = MIN(l, RECT_LEFT(area[i][x]));
-            t = MIN(l, RECT_TOP(area[i][x]));
-            r = MAX(r, RECT_RIGHT(area[i][x]));
-            b = MAX(b, RECT_BOTTOM(area[i][x]));
-        }
-        RECT_SET(area[i][screen_num_monitors], l, t,
-                 r - l + 1, b - t + 1);
-
-        /* XXX optimize when this is run? */
-
-        /* the area has changed, adjust all the maximized 
-           windows */
-        for (it = client_list; it; it = g_list_next(it)) {
-            ObClient *c = it->data; 
-            if (i < screen_num_desktops) {
-                if (c->desktop == i)
-                    client_reconfigure(c);
-            } else if (c->desktop == DESKTOP_ALL)
-                client_reconfigure(c);
-        }
-        if (i < screen_num_desktops) {
-            /* don't set these for the 'all desktops' area */
-            dims[(i * 4) + 0] = area[i][screen_num_monitors].x;
-            dims[(i * 4) + 1] = area[i][screen_num_monitors].y;
-            dims[(i * 4) + 2] = area[i][screen_num_monitors].width;
-            dims[(i * 4) + 3] = area[i][screen_num_monitors].height;
+            /* based on these margins, set the work area for the
+               monitor/desktop */
+            dims[(i * screen_num_desktops + j) * 4 + 0] += l;
+            dims[(i * screen_num_desktops + j) * 4 + 1] += t;
+            dims[(i * screen_num_desktops + j) * 4 + 2] -= l + r;
+            dims[(i * screen_num_desktops + j) * 4 + 3] -= t + b;
         }
 
-        g_free(struts);
-    }
-
     PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
-                dims, 4 * screen_num_desktops);
+                dims, 4 * screen_num_desktops * screen_num_monitors);
+
+    /* the area has changed, adjust all the windows if they need it */
+    for (it = client_list; it; it = g_list_next(it))
+        client_reconfigure(it->data, FALSE);
 
     g_free(dims);
 }
 
-Rect *screen_area(guint desktop)
+#if 0
+Rect* screen_area_all_monitors(guint desktop)
 {
-    return screen_area_monitor(desktop, screen_num_monitors);
+    guint i;
+    Rect *a;
+
+    a = screen_area_monitor(desktop, 0);
+
+    /* combine all the monitors together */
+    for (i = 1; i < screen_num_monitors; ++i) {
+        Rect *m = screen_area_monitor(desktop, i);
+        gint l, r, t, b;
+
+        l = MIN(RECT_LEFT(*a), RECT_LEFT(*m));
+        t = MIN(RECT_TOP(*a), RECT_TOP(*m));
+        r = MAX(RECT_RIGHT(*a), RECT_RIGHT(*m));
+        b = MAX(RECT_BOTTOM(*a), RECT_BOTTOM(*m));
+
+        RECT_SET(*a, l, t, r - l + 1, b - t + 1);
+
+        g_free(m);
+    }
+        
+    return a;
 }
+#endif
 
-Rect *screen_area_monitor(guint desktop, guint head)
+#define STRUT_LEFT_IN_SEARCH(s, search) \
+    (RANGES_INTERSECT(search->y, search->height, \
+                      s->left_start, s->left_end - s->left_start + 1))
+#define STRUT_RIGHT_IN_SEARCH(s, search) \
+    (RANGES_INTERSECT(search->y, search->height, \
+                      s->right_start, s->right_end - s->right_start + 1))
+#define STRUT_TOP_IN_SEARCH(s, search) \
+    (RANGES_INTERSECT(search->x, search->width, \
+                      s->top_start, s->top_end - s->top_start + 1))
+#define STRUT_BOTTOM_IN_SEARCH(s, search) \
+    (RANGES_INTERSECT(search->x, search->width, \
+                      s->bottom_start, s->bottom_end - s->bottom_start + 1))
+
+#define STRUT_LEFT_IGNORE(s, us, search) \
+    (head == SCREEN_AREA_ALL_MONITORS && us && \
+     RECT_LEFT(monitor_area[i]) + s->left > RECT_LEFT(*search))
+#define STRUT_RIGHT_IGNORE(s, us, search) \
+    (head == SCREEN_AREA_ALL_MONITORS && us && \
+     RECT_RIGHT(monitor_area[i]) - s->right < RECT_RIGHT(*search))
+#define STRUT_TOP_IGNORE(s, us, search) \
+    (head == SCREEN_AREA_ALL_MONITORS && us && \
+     RECT_TOP(monitor_area[i]) + s->top > RECT_TOP(*search))
+#define STRUT_BOTTOM_IGNORE(s, us, search) \
+    (head == SCREEN_AREA_ALL_MONITORS && us && \
+     RECT_BOTTOM(monitor_area[i]) - s->bottom < RECT_BOTTOM(*search))
+
+Rect* screen_area(guint desktop, guint head, Rect *search)
 {
-    if (head > screen_num_monitors)
-        return NULL;
-    if (desktop >= screen_num_desktops) {
-        if (desktop == DESKTOP_ALL)
-            return &area[screen_num_desktops][head];
-        return NULL;
+    Rect *a;
+    GSList *it;
+    gint l, r, t, b, al, ar, at, ab;
+    guint i, d;
+    gboolean us = search != NULL; /* user provided search */
+
+    g_assert(desktop < screen_num_desktops || desktop == DESKTOP_ALL);
+    g_assert(head < screen_num_monitors || head == SCREEN_AREA_ONE_MONITOR ||
+             head == SCREEN_AREA_ALL_MONITORS);
+    g_assert(!(head == SCREEN_AREA_ONE_MONITOR && search == NULL));
+
+    /* find any struts for this monitor
+       which will be affecting the search area.
+    */
+
+    /* search everything if search is null */
+    if (!search) {
+        if (head < screen_num_monitors) search = &monitor_area[head];
+        else search = &monitor_area[screen_num_monitors];
     }
-    return &area[desktop][head];
+    if (head == SCREEN_AREA_ONE_MONITOR) head = screen_find_monitor(search);
+
+    /* al is "all left" meaning the furthest left you can get, l is our
+       "working left" meaning our current strut edge which we're calculating
+    */
+
+    /* only include monitors which the search area lines up with */
+    if (RECT_INTERSECTS_RECT(monitor_area[screen_num_monitors], *search)) {
+        al = l = RECT_RIGHT(monitor_area[screen_num_monitors]);
+        at = t = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+        ar = r = RECT_LEFT(monitor_area[screen_num_monitors]);
+        ab = b = RECT_TOP(monitor_area[screen_num_monitors]);
+        for (i = 0; i < screen_num_monitors; ++i) {
+            /* add the monitor if applicable */
+            if (RANGES_INTERSECT(search->x, search->width,
+                                 monitor_area[i].x, monitor_area[i].width))
+            {
+                at = t = MIN(t, RECT_TOP(monitor_area[i]));
+                ab = b = MAX(b, RECT_BOTTOM(monitor_area[i]));
+            }
+            if (RANGES_INTERSECT(search->y, search->height,
+                                 monitor_area[i].y, monitor_area[i].height))
+            {
+                al = l = MIN(l, RECT_LEFT(monitor_area[i]));
+                ar = r = MAX(r, RECT_RIGHT(monitor_area[i]));
+            }
+        }
+    } else {
+        al = l = RECT_LEFT(monitor_area[screen_num_monitors]);
+        at = t = RECT_TOP(monitor_area[screen_num_monitors]);
+        ar = r = RECT_RIGHT(monitor_area[screen_num_monitors]);
+        ab = b = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+    }
+
+    for (d = 0; d < screen_num_desktops; ++d) {
+        if (d != desktop && desktop != DESKTOP_ALL) continue;
+
+        for (i = 0; i < screen_num_monitors; ++i) {
+            if (head != SCREEN_AREA_ALL_MONITORS && head != i) continue;
+
+            for (it = struts_left; it; it = g_slist_next(it)) {
+                ObScreenStrut *s = it->data;
+                if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+                    STRUT_LEFT_IN_SEARCH(s->strut, search) &&
+                    !STRUT_LEFT_IGNORE(s->strut, us, search))
+                    l = MAX(l, al + s->strut->left);
+            }
+            for (it = struts_top; it; it = g_slist_next(it)) {
+                ObScreenStrut *s = it->data;
+                if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+                    STRUT_TOP_IN_SEARCH(s->strut, search) &&
+                    !STRUT_TOP_IGNORE(s->strut, us, search))
+                    t = MAX(t, at + s->strut->top);
+            }
+            for (it = struts_right; it; it = g_slist_next(it)) {
+                ObScreenStrut *s = it->data;
+                if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+                    STRUT_RIGHT_IN_SEARCH(s->strut, search) &&
+                    !STRUT_RIGHT_IGNORE(s->strut, us, search))
+                    r = MIN(r, ar - s->strut->right);
+            }
+            for (it = struts_bottom; it; it = g_slist_next(it)) {
+                ObScreenStrut *s = it->data;
+                if ((s->desktop == d || s->desktop == DESKTOP_ALL) &&
+                    STRUT_BOTTOM_IN_SEARCH(s->strut, search) &&
+                    !STRUT_BOTTOM_IGNORE(s->strut, us, search))
+                    b = MIN(b, ab - s->strut->bottom);
+            }
+
+            /* limit to this monitor */
+            if (head == i) {
+                l = MAX(l, RECT_LEFT(monitor_area[i]));
+                t = MAX(t, RECT_TOP(monitor_area[i]));
+                r = MIN(r, RECT_RIGHT(monitor_area[i]));
+                b = MIN(b, RECT_BOTTOM(monitor_area[i]));
+            }
+        }
+    }
+
+    a = g_new(Rect, 1);
+    a->x = l;
+    a->y = t;
+    a->width = r - l + 1;
+    a->height = b - t + 1;
+    return a;
 }
 
 guint screen_find_monitor(Rect *search)
@@ -1351,23 +1409,34 @@ guint screen_find_monitor(Rect *search)
                 most = i;
             }
         }
+        g_free(area);
     }
     return most;
 }
 
-Rect *screen_physical_area()
+Rect* screen_physical_area_all_monitors()
 {
     return screen_physical_area_monitor(screen_num_monitors);
 }
 
-Rect *screen_physical_area_monitor(guint head)
+Rect* screen_physical_area_monitor(guint head)
+{
+    Rect *a;
+    g_assert(head <= screen_num_monitors);
+
+    a = g_new(Rect, 1);
+    *a = monitor_area[head];
+    return a;
+}
+
+gboolean screen_physical_area_monitor_contains(guint head, Rect *search)
 {
-    if (head > screen_num_monitors)
-        return NULL;
-    return &monitor_area[head];
+    g_assert(head <= screen_num_monitors);
+    g_assert(search);
+    return RECT_INTERSECTS_RECT(monitor_area[head], *search);
 }
 
-Rect *screen_physical_area_monitor_active()
+Rect* screen_physical_area_active()
 {
     Rect *a;
     gint x, y;
index 03d6ff697982d684862e2cde5c9f28fabfbee12b..6ad181953bfe6f3e6b3edb07158f0504ce6aac71 100644 (file)
@@ -94,19 +94,29 @@ void screen_install_colormap(struct _ObClient *client, gboolean install);
 
 void screen_update_areas();
 
-Rect *screen_physical_area();
+Rect *screen_physical_area_all_monitors();
 
 Rect *screen_physical_area_monitor(guint head);
 
-Rect *screen_physical_area_monitor_active();
+Rect *screen_physical_area_active();
 
-Rect *screen_area(guint desktop);
+/* doesn't include struts which the search area is already outside of when
+   'search' is not NULL */
+#define SCREEN_AREA_ALL_MONITORS ((unsigned)-1)
+#define SCREEN_AREA_ONE_MONITOR  ((unsigned)-2)
 
-Rect *screen_area_monitor(guint desktop, guint head);
+/*! @param head is the number of the head or one of SCREEN_AREA_ALL_MONITORS,
+           SCREEN_AREA_ONE_MONITOR
+    @param search NULL or the whole monitor(s)
+ */
+Rect* screen_area(guint desktop, guint head, Rect *search);
+
+gboolean screen_physical_area_monitor_contains(guint head, Rect *search);
 
 /*! Determines which physical monitor a rectangle is on by calculating the
     area of the part of the rectable on each monitor.  The number of the
-    monitor containing the greatest area of the rectangle is returned.*/
+    monitor containing the greatest area of the rectangle is returned.
+*/
 guint screen_find_monitor(Rect *search);
 
 /*! Sets the root cursor. This function decides which cursor to use, but you
index afd890a4825dd3878f52c2b733d9b45bc284dc0c..fe3d26d35e4e63f0e5c9403fecb34bbbe5395d41 100644 (file)
@@ -169,66 +169,38 @@ static void restack_windows(ObClient *selected, gboolean raise)
     GList *modals = NULL;
     GList *trans = NULL;
 
-    if (!raise && selected->parents) {
-        GSList *top, *top_it;
-        GSList *top_reorder = NULL;
-        
-        /* if it's a transient lowering, lower its parents so that we can lower
-           this window, or it won't move */
-        top = client_search_all_top_parents_layer(selected);
-
-        /* that is, if it has any parents */
-        if (!(top->data == selected && top->next == NULL)) {
-            /* place the window being lowered on the bottom so it'll be
-               below any of its peers that it can */
-            stacking_list = g_list_remove(stacking_list, selected);
-            stacking_list = g_list_append(stacking_list, selected);
-
-            /* go thru stacking list backwards so we can use g_slist_prepend */
-            for (it = g_list_last(stacking_list); it && top;
-                 it = g_list_previous(it))
-                if ((top_it = g_slist_find(top, it->data))) {
-                    top_reorder = g_slist_prepend(top_reorder, top_it->data);
-                    top = g_slist_delete_link(top, top_it);
-                }
-            g_assert(top == NULL);
-
-            /* call restack for each of these to lower them */
-            for (top_it = top_reorder; top_it; top_it = g_slist_next(top_it))
-                restack_windows(top_it->data, raise);
-            return;
-        }
-    }
-
     /* remove first so we can't run into ourself */
     it = g_list_find(stacking_list, selected);
     g_assert(it);
     stacking_list = g_list_delete_link(stacking_list, it);
 
-    /* go from the bottom of the stacking list up */
-    for (it = g_list_last(stacking_list); it; it = next) {
-        next = g_list_previous(it);
+    /* go from the bottom of the stacking list up. don't move any other windows
+       when lowering, we call this for each window independently */
+    if (raise) {
+        for (it = g_list_last(stacking_list); it; it = next) {
+            next = g_list_previous(it);
 
-        if (WINDOW_IS_CLIENT(it->data)) {
-            ObClient *ch = it->data;
+            if (WINDOW_IS_CLIENT(it->data)) {
+                ObClient *ch = it->data;
 
-            /* only move windows in the same stacking layer */
-            if (ch->layer == selected->layer &&
-                client_search_transient(selected, ch))
-            {
-                if (client_is_direct_child(selected, ch)) {
-                    if (ch->modal)
-                        modals = g_list_prepend(modals, ch);
-                    else
-                        trans = g_list_prepend(trans, ch);
-                }
-                else {
-                    if (ch->modal)
-                        group_modals = g_list_prepend(group_modals, ch);
-                    else
-                        group_trans = g_list_prepend(group_trans, ch);
+                /* only move windows in the same stacking layer */
+                if (ch->layer == selected->layer &&
+                    client_search_transient(selected, ch))
+                {
+                    if (client_is_direct_child(selected, ch)) {
+                        if (ch->modal)
+                            modals = g_list_prepend(modals, ch);
+                        else
+                            trans = g_list_prepend(trans, ch);
+                    }
+                    else {
+                        if (ch->modal)
+                            group_modals = g_list_prepend(group_modals, ch);
+                        else
+                            group_trans = g_list_prepend(group_trans, ch);
+                    }
+                    stacking_list = g_list_delete_link(stacking_list, it);
                 }
-                stacking_list = g_list_delete_link(stacking_list, it);
             }
         }
     }
@@ -317,6 +289,27 @@ static void restack_windows(ObClient *selected, gboolean raise)
 
     do_restack(wins, below);
     g_list_free(wins);
+
+    /* lower our parents after us, so they go below us */
+    if (!raise && selected->parents) {
+        GSList *parents_copy, *sit;
+        GSList *reorder = NULL;
+
+        parents_copy = g_slist_copy(selected->parents);
+
+        /* go thru stacking list backwards so we can use g_slist_prepend */
+        for (it = g_list_last(stacking_list); it && parents_copy;
+             it = g_list_previous(it))
+            if ((sit = g_slist_find(parents_copy, it->data))) {
+                reorder = g_slist_prepend(reorder, sit->data);
+                parents_copy = g_slist_delete_link(parents_copy, sit);
+            }
+        g_assert(parents_copy == NULL);
+
+        /* call restack for each of these to lower them */
+        for (sit = reorder; sit; sit = g_slist_next(sit))
+            restack_windows(sit->data, raise);
+    }
 }
 
 void stacking_raise(ObWindow *window)
index 58792bb0b6d1bf650024deeb093da650b5ed726b..d361d7a260880fd47f7d8a4c938786b5695ca1ea 100644 (file)
@@ -21,5 +21,6 @@ bn_IN
 it
 vi
 ja
+ua
 
 #hr
diff --git a/po/ua.po b/po/ua.po
new file mode 100644 (file)
index 0000000..e0d8579
--- /dev/null
+++ b/po/ua.po
@@ -0,0 +1,340 @@
+# Ukrainian translation for Openbox.
+# Copyright (C) 2007 Dmitriy Moroz
+# This file is distributed under the same license as the openbox package.
+# Dmitriy Moroz <zux@dimaka.org.ua>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openbox 3.4.2\n"
+"Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
+"POT-Creation-Date: 2007-06-16 15:02+0200\n"
+"PO-Revision-Date: 2007-06-16 13:02+0200\n"
+"Last-Translator: Dmitriy Moroz <zux@dimaka.org.ua>\n"
+"Language-Team: Ukrainian <root@archlinux.org.ua>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: openbox/action.c:991
+#, c-format
+msgid "Invalid action '%s' requested. No such action exists."
+msgstr "Здійснено запит на некоректну дію '%s'. Нема такої дії."
+
+#: openbox/action.c:994
+#, c-format
+msgid "Invalid use of action '%s'. Action will be ignored."
+msgstr "Некоректне викристання дії '%s'. Дія буде проігнорована."
+
+#: openbox/action.c:1261 openbox/action.c:1279 openbox/action.c:1292
+#, c-format
+msgid "Failed to execute '%s': %s"
+msgstr "Невдалося виконати '%s': %s"
+
+#: openbox/action.c:1300
+#, c-format
+msgid "Failed to convert the path '%s' from utf8"
+msgstr "Не вдалося сконвертувати шлях '%s' з utf8"
+
+#: openbox/client_list_combined_menu.c:104 openbox/client_list_menu.c:105
+msgid "Go there..."
+msgstr "Перейти...."
+
+#: openbox/client_list_combined_menu.c:150
+msgid "Windows"
+msgstr "Вікна"
+
+#: openbox/client_list_menu.c:196
+msgid "Desktops"
+msgstr "Стільниці"
+
+#: openbox/client_menu.c:258
+msgid "All desktops"
+msgstr "Всі стільниці"
+
+#: openbox/client_menu.c:363
+msgid "&Layer"
+msgstr "Шар(&L)"
+
+#: openbox/client_menu.c:368
+msgid "Always on &top"
+msgstr "Зверху всіх вікон(&T)"
+
+#: openbox/client_menu.c:369
+msgid "&Normal"
+msgstr "Звичайне положення(&N)"
+
+#: openbox/client_menu.c:370
+msgid "Always on &bottom"
+msgstr "Знизу всіх вікон(&B)"
+
+#: openbox/client_menu.c:373
+msgid "&Send to desktop"
+msgstr "Відправити на стільницю(&S)"
+
+#: openbox/client_menu.c:377
+msgid "Client menu"
+msgstr "Меню клієнтів"
+
+#: openbox/client_menu.c:383
+msgid "R&estore"
+msgstr "Відновити(&E)"
+
+#: openbox/client_menu.c:391
+msgid "&Move"
+msgstr "Перемістити(&M)"
+
+#: openbox/client_menu.c:393
+msgid "Resi&ze"
+msgstr "Змінити розмір(&Z)"
+
+#: openbox/client_menu.c:395
+msgid "Ico&nify"
+msgstr "Згорнути(&N)"
+
+#: openbox/client_menu.c:403
+msgid "Ma&ximize"
+msgstr "Розгорнути(&X)"
+
+#: openbox/client_menu.c:411
+msgid "&Roll up/down"
+msgstr "Скрутити/Розкрутити(&R)"
+
+#: openbox/client_menu.c:413
+msgid "Un/&Decorate"
+msgstr "(Від)декорувати(&D)"
+
+#: openbox/client_menu.c:423
+msgid "&Close"
+msgstr "Закрити(&C)"
+
+#: openbox/config.c:719
+#, c-format
+msgid "Invalid button '%s' specified in config file"
+msgstr "Некоректна клавіша '%s' вказана у файлі конфігурації"
+
+#: openbox/keyboard.c:164
+msgid "Conflict with key binding in config file"
+msgstr "Конфлікт прив'язки клавіш у файлі конфігурації"
+
+#: openbox/menu.c:100 openbox/menu.c:108
+#, c-format
+msgid "Unable to find a valid menu file '%s'"
+msgstr "Не вдалося знайти коректний файл меню '%s'"
+
+#: openbox/menu.c:168
+#, c-format
+msgid "Failed to execute command for pipe-menu '%s': %s"
+msgstr "Не вдалося виконати команду для pipe-меню '%s': %s"
+
+#: openbox/menu.c:182
+#, c-format
+msgid "Invalid output from pipe-menu '%s'"
+msgstr "Некоректний вивід з pipe-меню '%s'"
+
+#: openbox/menu.c:195
+#, c-format
+msgid "Attempted to access menu '%s' but it does not exist"
+msgstr "Спроба доступа до меню '%s' якого не існує"
+
+#: openbox/menu.c:356 openbox/menu.c:357
+msgid "More..."
+msgstr "Більше..."
+
+#: openbox/mouse.c:338
+#, c-format
+msgid "Invalid button '%s' in mouse binding"
+msgstr "Некоректна клавіша '%s' в прив'язці клавіш мишки"
+
+#: openbox/mouse.c:344
+#, c-format
+msgid "Invalid context '%s' in mouse binding"
+msgstr "Некоректний контекст '%s' в прив'зці клавіш мишки"
+
+#: openbox/openbox.c:129
+#, c-format
+msgid "Unable to change to home directory '%s': %s"
+msgstr "Не вдалося перейти в домашню директорію '%s': %s"
+
+#: openbox/openbox.c:149
+msgid "Failed to open the display from the DISPLAY environment variable."
+msgstr "Не вдалося відкрити дисплей зі змінної середовища DISPLAY"
+
+#: openbox/openbox.c:180
+msgid "Failed to initialize the obrender library."
+msgstr "Не вдалося ініцаілізувати бібліотеку obrender"
+
+#: openbox/openbox.c:186
+msgid "X server does not support locale."
+msgstr "X-сервер не підтримує локалі"
+
+#: openbox/openbox.c:188
+msgid "Cannot set locale modifiers for the X server."
+msgstr "Не можу встановити модифікатори локалі для X-сервера"
+
+#: openbox/openbox.c:249
+msgid "Unable to find a valid config file, using some simple defaults"
+msgstr ""
+"Не вдалося знайти коректний файл конфігурації, використовую стандартні "
+"налаштування"
+
+#: openbox/openbox.c:275
+msgid "Unable to load a theme."
+msgstr "Не вдалося загрузити стиль"
+
+#: openbox/openbox.c:401
+#, c-format
+msgid "Restart failed to execute new executable '%s': %s"
+msgstr ""
+"При перезавантаженні не вдалося виконати новий виконуваний файл '%s': %s"
+
+#: openbox/openbox.c:471 openbox/openbox.c:473
+msgid "Copyright (c)"
+msgstr "Авторські права (c)"
+
+#: openbox/openbox.c:482
+msgid "Syntax: openbox [options]\n"
+msgstr "Синтакс: openbox [параметри]\n"
+
+#: openbox/openbox.c:483
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Параметри:\n"
+
+#: openbox/openbox.c:484
+msgid "  --help              Display this help and exit\n"
+msgstr "  --help              Показати цю справку і вийти\n"
+
+#: openbox/openbox.c:485
+msgid "  --version           Display the version and exit\n"
+msgstr "  --vesrion           Показати версію і вийти\n"
+
+#: openbox/openbox.c:486
+msgid "  --replace           Replace the currently running window manager\n"
+msgstr "  --replace           Замінити поточний менеджер вікон\n"
+
+#: openbox/openbox.c:487
+msgid "  --sm-disable        Disable connection to the session manager\n"
+msgstr "  --sm-disable        Не з'єднуватися з сесійним менеджером\n"
+
+#: openbox/openbox.c:488
+msgid ""
+"\n"
+"Passing messages to a running Openbox instance:\n"
+msgstr ""
+"\n"
+"Передаю повідомлення процесу Openbox що виконується\n"
+
+#: openbox/openbox.c:489
+msgid "  --reconfigure       Reload Openbox's configuration\n"
+msgstr "  --reconfigure       Перезавантажити конфігурацію Openbox'у\n"
+
+#: openbox/openbox.c:490
+msgid "  --restart           Restart Openbox\n"
+msgstr "  --restart           Перезапустити Openbox\n"
+
+#: openbox/openbox.c:491
+msgid ""
+"\n"
+"Debugging options:\n"
+msgstr ""
+"\n"
+"Налагоджувальні параметри\n"
+
+#: openbox/openbox.c:492
+msgid "  --sync              Run in synchronous mode\n"
+msgstr "  --sync              Запустити в синхронному режимі\n"
+
+#: openbox/openbox.c:493
+msgid "  --debug             Display debugging output\n"
+msgstr "  --debug             Показувати інформацію налагоджування\n"
+
+#: openbox/openbox.c:494
+msgid "  --debug-focus       Display debugging output for focus handling\n"
+msgstr ""
+"  --debug-focus       Показувати інформацію налагоджування для уравління\n"
+
+#: openbox/openbox.c:495
+msgid "  --debug-xinerama    Split the display into fake xinerama screens\n"
+msgstr "  --debug-xinerama    Розбити екран на фальшиві екрани xinerama\n"
+
+#: openbox/openbox.c:496
+#, c-format
+msgid ""
+"\n"
+"Please report bugs at %s\n"
+msgstr ""
+"\n"
+"Будь-ласка, повідомляйте про помилки на %s\n"
+
+#: openbox/openbox.c:593
+#, c-format
+msgid "Invalid command line argument '%s'\n"
+msgstr "Некоректний командний аргумент '%s'\n"
+
+#: openbox/screen.c:94 openbox/screen.c:195
+#, c-format
+msgid "A window manager is already running on screen %d"
+msgstr "На дисплеї %d вже запущений менеджер вікон"
+
+#: openbox/screen.c:131
+#, c-format
+msgid "Could not acquire window manager selection on screen %d"
+msgstr "Не можу отримати вибір менеджера вікон на дисплеї %d"
+
+#: openbox/screen.c:152
+#, c-format
+msgid "The WM on screen %d is not exiting"
+msgstr "Менеджео вікон на дисплеї %d не завершується"
+
+#: openbox/screen.c:1006
+#, c-format
+msgid "desktop %i"
+msgstr "стільниця %i"
+
+#: openbox/session.c:103
+#, c-format
+msgid "Unable to make directory '%s': %s"
+msgstr "Не вдалося створити директорію '%s': %s"
+
+#: openbox/session.c:451
+#, c-format
+msgid "Unable to save the session to '%s': %s"
+msgstr "Не вдалося зберегти сесію в '%s': %s"
+
+#: openbox/session.c:583
+#, c-format
+msgid "Error while saving the session to '%s': %s"
+msgstr "Помилка при збереженні сесії в '%s': %s"
+
+#: openbox/startupnotify.c:237
+#, c-format
+msgid "Running %s\n"
+msgstr "Виконується %s\n"
+
+#: openbox/translate.c:58
+#, c-format
+msgid "Invalid modifier key '%s' in key/mouse binding"
+msgstr "Некоректна назва модифікатору '%s' у прив'язці клавіш клавіатури/мишки"
+
+#: openbox/translate.c:135
+#, c-format
+msgid "Invalid key code '%s' in key binding"
+msgstr "Некоректний код клавіши '%s' у прив'зці клавіш"
+
+#: openbox/translate.c:142
+#, c-format
+msgid "Invalid key name '%s' in key binding"
+msgstr "Некоректна назва клавіши '%s' у прив'язці клавіш"
+
+#: openbox/translate.c:148
+#, c-format
+msgid "Requested key '%s' does not exist on the display"
+msgstr "Клавіша '%s' на яку здійснено запит - не існує на дисплеї"
+
+#: openbox/xerror.c:39
+#, c-format
+msgid "X Error: %s"
+msgstr "Помилка X-серверу: %s"
index ccfd6071d5c3f5c2e08887331ce939013e99c993..41514ac43296bac8ce059e1034cadf0aa35e4fb5 100644 (file)
@@ -421,50 +421,28 @@ static void gradient_solid(RrAppearance *l, gint w, gint h)
 
 static void gradient_splitvertical(RrAppearance *a, gint w, gint h)
 {
-    gint x, y1, y2, y3, r, g, b;
+    gint x, y1, y2, y3;
     RrSurface *sf = &a->surface;
     RrPixel32 *data = sf->pixel_data;
     RrPixel32 current;
-    RrColor *primary_light, *secondary_light;
     gint y1sz, y2sz, y3sz;
 
     VARS(y1);
     VARS(y2);
     VARS(y3);
 
-    r = sf->primary->r;
-    r += r >> 2;
-    g = sf->primary->g;
-    g += g >> 2;
-    b = sf->primary->b;
-    b += b >> 2;
-    if (r > 0xFF) r = 0xFF;
-    if (g > 0xFF) g = 0xFF;
-    if (b > 0xFF) b = 0xFF;
-    primary_light = RrColorNew(a->inst, r, g, b);
-
-    r = sf->secondary->r;
-    r += r >> 4;
-    g = sf->secondary->g;
-    g += g >> 4;
-    b = sf->secondary->b;
-    b += b >> 4;
-    if (r > 0xFF) r = 0xFF;
-    if (g > 0xFF) g = 0xFF;
-    if (b > 0xFF) b = 0xFF;
-    secondary_light = RrColorNew(a->inst, r, g, b);
 
     y1sz = MAX(h/2 - 1, 1);
     /* setup to get the colors _in between_ these other 2 */
     y2sz = (h < 3 ? 0 : (h % 2 ? 3 : 2));
     y3sz = MAX(h/2 - 1, 0);
 
-    SETUP(y1, primary_light, sf->primary, y1sz);
+    SETUP(y1, sf->split_primary, sf->primary, y1sz);
     if (y2sz) {
         SETUP(y2, sf->primary, sf->secondary, y2sz);
         NEXT(y2); /* skip the first one, its the same as the last of y1 */
     }
-    SETUP(y3, sf->secondary, secondary_light,  y3sz);
+    SETUP(y3, sf->secondary, sf->split_secondary,  y3sz);
 
     for (y1 = y1sz; y1 > 0; --y1) {
         current = COLOR(y1);
@@ -489,9 +467,6 @@ static void gradient_splitvertical(RrAppearance *a, gint w, gint h)
 
         NEXT(y3);
     }
-
-    RrColorFree(primary_light);
-    RrColorFree(secondary_light);
 }
 
 static void gradient_horizontal(RrSurface *sf, gint w, gint h)
index 63c1e7245c53b9ef0591122d30dd1fdd3f7ed781..97ec7b520e149a784caceacdeaff4e585239723c 100644 (file)
@@ -241,6 +241,20 @@ RrAppearance *RrAppearanceCopy(RrAppearance *orig)
                                       spo->bevel_light->b);
     else spc->bevel_light = NULL;
 
+    if (spo->split_primary != NULL)
+        spc->split_primary = RrColorNew(copy->inst,
+                                        spo->split_primary->r,
+                                        spo->split_primary->g,
+                                        spo->split_primary->b);
+    else spc->split_primary = NULL;
+
+    if (spo->split_secondary != NULL)
+        spc->split_secondary = RrColorNew(copy->inst,
+                                        spo->split_secondary->r,
+                                        spo->split_secondary->g,
+                                        spo->split_secondary->b);
+    else spc->split_secondary = NULL;
+
     spc->interlaced = spo->interlaced;
     spc->bevel_light_adjust = spo->bevel_light_adjust;
     spc->bevel_dark_adjust = spo->bevel_dark_adjust;
@@ -284,6 +298,8 @@ void RrAppearanceFree(RrAppearance *a)
         RrColorFree(p->interlace_color);
         RrColorFree(p->bevel_dark);
         RrColorFree(p->bevel_light);
+        RrColorFree(p->split_primary);
+        RrColorFree(p->split_secondary);
         g_free(p->pixel_data);
         p->pixel_data = NULL;
         g_free(a);
index cf0f7eddbf45eaba28c56063bf3dd919bc92bbb0..33c9c0e9a8fc0b88fdefd6049858fd5e938747c4 100644 (file)
@@ -125,6 +125,8 @@ struct _RrSurface {
     RrPixel32 *pixel_data;
     gint bevel_dark_adjust;  /* 0-255, default is 64 */
     gint bevel_light_adjust; /* 0-255, default is 128 */
+    RrColor *split_primary;
+    RrColor *split_secondary;
 };
 
 struct _RrTextureText {
index 709449443697aa5052652d42a52592ee70ed47d7..265378539fd08fd779023526c0879c831ef5df57 100644 (file)
@@ -1761,6 +1761,7 @@ static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
     gboolean ret = FALSE;
     gchar *rclass = create_class_name(rname);
     gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
+    gchar *csplitname, *ctosplitname;
     gchar *rettype;
     XrmValue retvalue;
     gint i;
@@ -1771,6 +1772,8 @@ static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
     icname = g_strconcat(rname, ".interlace.color", NULL);
     hname = g_strconcat(rname, ".highlight", NULL);
     sname = g_strconcat(rname, ".shadow", NULL);
+    csplitname = g_strconcat(rname, ".color.splitTo", NULL);
+    ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
 
     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
         retvalue.addr != NULL) {
@@ -1797,9 +1800,46 @@ static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
             value->surface.bevel_light_adjust = i;
         if (read_int(db, sname, &i) && i >= 0 && i <= 256)
             value->surface.bevel_dark_adjust = i;
+
+        if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
+            gint r, g, b;
+
+            if (!read_color(db, inst, csplitname,
+                            &value->surface.split_primary))
+            {
+                r = value->surface.primary->r;
+                r += r >> 2;
+                g = value->surface.primary->g;
+                g += g >> 2;
+                b = value->surface.primary->b;
+                b += b >> 2;
+                if (r > 0xFF) r = 0xFF;
+                if (g > 0xFF) g = 0xFF;
+                if (b > 0xFF) b = 0xFF;
+                value->surface.split_primary = RrColorNew(inst, r, g, b);
+            }
+
+            if (!read_color(db, inst, ctosplitname,
+                            &value->surface.split_secondary))
+            {
+                r = value->surface.secondary->r;
+                r += r >> 4;
+                g = value->surface.secondary->g;
+                g += g >> 4;
+                b = value->surface.secondary->b;
+                b += b >> 4;
+                if (r > 0xFF) r = 0xFF;
+                if (g > 0xFF) g = 0xFF;
+                if (b > 0xFF) b = 0xFF;
+                value->surface.split_secondary = RrColorNew(inst, r, g, b);
+            }
+        }
+
         ret = TRUE;
     }
 
+    g_free(ctosplitname);
+    g_free(csplitname);
     g_free(sname);
     g_free(hname);
     g_free(icname);
index be5006b0048d4467536cafefa8727820d9f944e2..a849342a1aba4d566392280a2c484d18c1323e29 100644 (file)
@@ -59,7 +59,9 @@ window.inactive.button.*.pressed.image.color: #fdceb7
 window.inactive.button.*.pressed.bg.border.color: #f0832c
 
 window.active.button.*.image.color: #e0e0e0
-window.inactive.button.*.image.color: #606060
+window.active.button.disabled.image.color: #707070
+window.inactive.button.*.image.color: #747474
+window.inactive.button.disabled.image.color: #c0c0c0
 
 !! Borders
 window.active.border.color: #181818
index 8a4769ea036bee005f3a7735ac52d5da1cbdcc78..8de9d064522006db5700ccfefc430a0fb4f4d7d6 100644 (file)
@@ -59,7 +59,9 @@ window.inactive.button.*.pressed.image.color: #b7fdef
 window.inactive.button.*.pressed.bg.border.color: #38b3d6
 
 window.active.button.*.image.color: #e0e0e0
+window.active.button.disabled.image.color: #707070
 window.inactive.button.*.image.color: #747474
+window.inactive.button.disabled.image.color: #c0c0c0
 
 !! Borders
 window.active.border.color: #181818