From 5afa66e8762772719ed6f09cfa462bccf83bf0ec Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 19 Jun 2007 21:26:21 +0000 Subject: [PATCH] merge r7519-7571 from trunk --- data/rc.xml | 8 +- data/rc.xsd | 1 + openbox/action.c | 122 +++++- openbox/action.h | 10 + openbox/client.c | 256 +++++++------ openbox/client.h | 24 +- openbox/client_menu.c | 2 +- openbox/config.c | 4 + openbox/config.h | 2 + openbox/dock.c | 40 +- openbox/dock.h | 2 + openbox/event.c | 33 +- openbox/focus.c | 94 ++++- openbox/focus.h | 6 + openbox/focus_cycle.c | 135 ++----- openbox/focus_cycle.h | 6 - openbox/focus_cycle_popup.c | 18 +- openbox/frame.c | 150 +++++--- openbox/frame.h | 6 + openbox/framerender.c | 5 + openbox/geom.h | 3 + openbox/grab.c | 2 +- openbox/keyboard.c | 3 +- openbox/menuframe.c | 8 +- openbox/moveresize.c | 6 +- openbox/openbox.c | 2 +- openbox/place.c | 103 +++-- openbox/popup.c | 7 +- openbox/resist.c | 32 +- openbox/screen.c | 539 +++++++++++++++------------ openbox/screen.h | 20 +- openbox/stacking.c | 97 +++-- po/LINGUAS | 1 + po/ua.po | 340 +++++++++++++++++ render/gradient.c | 31 +- render/render.c | 16 + render/render.h | 2 + render/theme.c | 40 ++ themes/Onyx-Citrus/openbox-3/themerc | 4 +- themes/Onyx/openbox-3/themerc | 2 + 40 files changed, 1456 insertions(+), 726 deletions(-) create mode 100644 po/ua.po diff --git a/data/rc.xml b/data/rc.xml index d16ae5a2..1a4230c7 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -32,6 +32,9 @@ Smart +
yes
+
@@ -282,9 +285,6 @@ - - - @@ -302,9 +302,11 @@ + + diff --git a/data/rc.xsd b/data/rc.xsd index e256e448..0357deed 100644 --- a/data/rc.xsd +++ b/data/rc.xsd @@ -53,6 +53,7 @@ defines how new windows are placed + diff --git a/openbox/action.c b/openbox/action.c index 6248d143..7bc8ab65 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -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); +} diff --git a/openbox/action.h b/openbox/action.h index 38452e44..17e35766 100644 --- a/openbox/action.h +++ b/openbox/action.h @@ -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 diff --git a/openbox/client.c b/openbox/client.c index 29b27d1d..cf6965ae 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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; } diff --git a/openbox/client.h b/openbox/client.h index 98f9e6e4..ed677926 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -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); diff --git a/openbox/client_menu.c b/openbox/client_menu.c index ce29db10..cc67a461 100644 --- a/openbox/client_menu.c +++ b/openbox/client_menu.c @@ -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(); diff --git a/openbox/config.c b/openbox/config.c index 10a60fb4..2eb8e13c 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -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); diff --git a/openbox/config.h b/openbox/config.h index f45196e2..e8c70eb2 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -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 */ diff --git a/openbox/dock.c b/openbox/dock.c index ff5b74cf..c128e470 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -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); +} diff --git a/openbox/dock.h b/openbox/dock.h index 051747c3..48d6af49 100644 --- a/openbox/dock.h +++ b/openbox/dock.h @@ -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 diff --git a/openbox/event.c b/openbox/event.c index 12ecdac0..8089792c 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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) { diff --git a/openbox/focus.c b/openbox/focus.c index 6d66382a..f34021a4 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -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; +} + diff --git a/openbox/focus.h b/openbox/focus.h index f54da05c..f5033aee 100644 --- a/openbox/focus.h +++ b/openbox/focus.h @@ -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 diff --git a/openbox/focus_cycle.c b/openbox/focus_cycle.c index bd8a0846..a5ac4e68 100644 --- a/openbox/focus_cycle.c +++ b/openbox/focus_cycle.c @@ -26,7 +26,6 @@ #include "screen.h" #include "openbox.h" #include "debug.h" -#include "group.h" #include #include @@ -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; } diff --git a/openbox/focus_cycle.h b/openbox/focus_cycle.h index afdbdc79..2e32805f 100644 --- a/openbox/focus_cycle.h +++ b/openbox/focus_cycle.h @@ -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 diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index 3ec14a5c..477619f5 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -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); diff --git a/openbox/frame.c b/openbox/frame.c index 746bc610..096b7839 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -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 ! */ diff --git a/openbox/frame.h b/openbox/frame.h index eb868dcb..cf840bdf 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -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); diff --git a/openbox/framerender.c b/openbox/framerender.c index a02567bd..fe789d96 100644 --- a/openbox/framerender.c +++ b/openbox/framerender.c @@ -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; diff --git a/openbox/geom.h b/openbox/geom.h index 67a82cde..43eb8ea3 100644 --- a/openbox/geom.h +++ b/openbox/geom.h @@ -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 diff --git a/openbox/grab.c b/openbox/grab.c index 85027d5d..3fa45b7c 100644 --- a/openbox/grab.c +++ b/openbox/grab.c @@ -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); diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 9fd38def..7fdd1870 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -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); } diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 6b3e729b..fdb24afb 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -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; } diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 232cc9b9..534cd011 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -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 */ diff --git a/openbox/openbox.c b/openbox/openbox.c index e8d5ae4d..1e1e3bf0 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -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); } } diff --git a/openbox/place.c b/openbox/place.c index c30a27f9..845becdb 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -23,8 +23,11 @@ #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); diff --git a/openbox/popup.c b/openbox/popup.c index 77f751fc..f5072748 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -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) diff --git a/openbox/resist.c b/openbox/resist.c index ab71d132..211a012c 100644 --- a/openbox/resist.c +++ b/openbox/resist.c @@ -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); } } diff --git a/openbox/screen.c b/openbox/screen.c index 7e2d8645..f9b1eb6c 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -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; diff --git a/openbox/screen.h b/openbox/screen.h index 03d6ff69..6ad18195 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -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 diff --git a/openbox/stacking.c b/openbox/stacking.c index afd890a4..fe3d26d3 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -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) diff --git a/po/LINGUAS b/po/LINGUAS index 58792bb0..d361d7a2 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -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 index 00000000..e0d8579c --- /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 , 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 \n" +"Language-Team: Ukrainian \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" diff --git a/render/gradient.c b/render/gradient.c index ccfd6071..41514ac4 100644 --- a/render/gradient.c +++ b/render/gradient.c @@ -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) diff --git a/render/render.c b/render/render.c index 63c1e724..97ec7b52 100644 --- a/render/render.c +++ b/render/render.c @@ -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); diff --git a/render/render.h b/render/render.h index cf0f7edd..33c9c0e9 100644 --- a/render/render.h +++ b/render/render.h @@ -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 { diff --git a/render/theme.c b/render/theme.c index 70944944..26537853 100644 --- a/render/theme.c +++ b/render/theme.c @@ -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); diff --git a/themes/Onyx-Citrus/openbox-3/themerc b/themes/Onyx-Citrus/openbox-3/themerc index be5006b0..a849342a 100644 --- a/themes/Onyx-Citrus/openbox-3/themerc +++ b/themes/Onyx-Citrus/openbox-3/themerc @@ -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 diff --git a/themes/Onyx/openbox-3/themerc b/themes/Onyx/openbox-3/themerc index 8a4769ea..8de9d064 100644 --- a/themes/Onyx/openbox-3/themerc +++ b/themes/Onyx/openbox-3/themerc @@ -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 -- 2.34.1