<placement>
<policy>Smart</policy>
<!-- 'Smart' or 'UnderMouse' -->
+ <center>yes</center>
+ <!-- whether to place windows in the center of the free area found or
+ the top left corner -->
</placement>
<theme>
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
- <mousebind button="Left" action="Click">
- <action name="Unshade"/>
- </mousebind>
<mousebind button="Left" action="Drag">
<action name="Move"/>
</mousebind>
<action name="Shade"/>
<action name="FocusToBottom"/>
<action name="Unfocus"/>
+ <action name="Lower"/>
</mousebind>
<mousebind button="Down" action="Click">
<action name="Unshade"/>
+ <action name="Raise"/>
</mousebind>
<mousebind button="Right" action="Press">
<xsd:documentation>defines how new windows are placed</xsd:documentation>
</xsd:annotation>
<xsd:element name="policy" type="ob:placementpolicy"/>
+ <xsd:element name="center" type="ob:bool"/>
</xsd:complexType>
<xsd:complexType name="theme">
<xsd:element minOccurs="0" name="name" type="xsd:string"/>
}
}
+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;
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,
{
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)
{
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)
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);
}
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);
}
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)
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 */
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)
/* 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);
+}
gchar *name;
};
+struct AddRemoveDesktop {
+ struct AnyAction any;
+ gboolean current;
+};
+
struct CycleWindows {
struct InteractiveAction inter;
gboolean linear;
struct CycleWindows cycle;
struct Layer layer;
struct Stacking stacking;
+ struct AddRemoveDesktop addremovedesktop;
};
struct _ObAction {
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
/* 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;
}
*/
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);
}
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);
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;
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);
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)
}
}
-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;
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],
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);
}
/* 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;
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;
*/
(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;
}
/* 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 */
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
Rect *a;
guint i;
- i = screen_find_monitor(&desired_area);
+ i = screen_find_monitor(&desired);
a = screen_physical_area_monitor(i);
*x = a->x;
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) {
user = FALSE; /* ignore if the client can't be moved/resized when it
is maximizing */
+
+ g_free(a);
}
/* gets the client's position */
/* 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;
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;
}
/* 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;
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);
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)
void client_set_desktop_recursive(ObClient *self,
guint target,
- gboolean donthide)
+ gboolean donthide,
+ gboolean dontraise)
{
guint old;
GSList *it;
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)
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)
if (iconic && self->iconic)
client_iconify(self, FALSE, TRUE, FALSE);
else
- client_set_desktop(self, desktop, FALSE);
+ client_set_desktop(self, desktop, FALSE, FALSE);
}
}
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:
/* 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)
/* 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) */
/* 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)
/* 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) */
g_assert_not_reached();
dest = 0; /* suppress warning */
}
+
+ g_free(a);
+ g_free(mon);
return dest;
}
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.
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
/*! 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);
{
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();
gboolean config_focus_under_mouse;
ObPlacePolicy config_place_policy;
+gboolean config_place_center;
gchar *config_theme;
gboolean config_theme_keepborder;
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,
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);
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 */
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));
}
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;
}
}
- 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;
}
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) {
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) {
}
}
- 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;
dock->h += ob_rr_theme->obwidth * 2;
screen_update_areas();
+
+ g_free(a);
}
void dock_app_configure(ObDockApp *app, gint w, gint h)
}
}
}
+
+void dock_get_area(Rect *a)
+{
+ RECT_SET(*a, dock->x, dock->y, dock->w, dock->h);
+}
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
{
gint lw,lh;
- gulong ignore_start;
client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
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;
}
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;
moveresize_end(TRUE);
} else if (msgtype == prop_atoms.net_moveresize_window) {
gint ograv, x, y, w, h;
- gulong ignore_start;
ograv = client->gravity;
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) {
/* 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 "
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) {
#include "grab.h"
#include "client.h"
#include "config.h"
+#include "group.h"
#include "focus_cycle.h"
#include "screen.h"
#include "prop.h"
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))
{
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))
{
}
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;
+}
+
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
#include "screen.h"
#include "openbox.h"
#include "debug.h"
-#include "group.h"
#include <X11/Xlib.h>
#include <glib.h>
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)
{
/* 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,
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 */
/* 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
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;
}
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
#include "client.h"
#include "screen.h"
#include "focus.h"
-#include "focus_cycle.h"
#include "openbox.h"
#include "window.h"
#include "event.h"
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);
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);
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,
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);
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);
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);
{
if (!self->visible) {
self->visible = TRUE;
+ framerender_frame(self);
XMapWindow(ob_display, self->client->window);
XMapWindow(ob_display, self->window);
}
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))
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
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,
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);
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);
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,
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);
{
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);
ob_rr_theme->handle_height);
XMoveResizeWindow(ob_display, self->lgriptop,
- self->bwidth,
+ sidebwidth,
FRAME_HANDLE_Y(self),
ob_rr_theme->grip_width +
self->bwidth,
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,
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);
self->size.left, self->size.top);
if (resized) {
+ self->need_render = TRUE;
framerender_frame(self);
frame_adjust_shape(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);
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);
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);
}
(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;
}
}
+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;
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;
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 ! */
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;
gboolean iconify_hover;
gboolean focused;
+ gboolean need_render;
gboolean flashing;
gboolean flash_on;
*/
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);
{
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;
(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
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);
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);
}
*dx = MAX(*dx, a->x - x);
*dy = MAX(*dy, a->y - y);
}
+
+ g_free(a);
}
static void menu_entry_frame_render(ObMenuEntryFrame *self)
}
}
+ g_free(a);
+
menu_frame_render(self);
}
/* 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;
}
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;
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,
#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 */
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);
}
}
#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;
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;
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;
}
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;
}
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)
gboolean ret;
gint maxsize;
GSList *spaces = NULL, *sit, *maxit;
+ guint i;
areas = pick_head(c);
ret = FALSE;
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 */
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;
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;
}
}
}
+ for (i = 0; i < screen_num_monitors; ++i)
+ g_free(areas[i]);
g_free(areas);
return ret;
}
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)
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;
}
(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);
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
popup_show_timeout(self);
}
}
+
+ g_free(area);
}
void popup_hide(ObPopup *self)
/* 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;
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;
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);
*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);
/* 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);
gint pl, pt, pr, pb; /* physical screen boundaries */
gint incw, inch;
guint i;
+ Rect desired_area;
if (!resist) return;
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);
*h = b - pt + 1;
break;
}
+
+ g_free(area);
+ g_free(parea);
}
}
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;
void screen_shutdown(gboolean reconfig)
{
- Rect **r;
-
pager_popup_free(desktop_cycle_popup);
if (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()
{
guint old;
gulong *viewport;
- GList *it;
+ GList *it, *stacking_copy;
g_assert(num > 0);
/* 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) */
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 */
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
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,
}
}
-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)
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;
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
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);
}
}
}
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)
--- /dev/null
+# Ukrainian translation for Openbox.
+# Copyright (C) 2007 Dmitriy Moroz
+# This file is distributed under the same license as the openbox package.
+# Dmitriy Moroz <zux@dimaka.org.ua>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openbox 3.4.2\n"
+"Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
+"POT-Creation-Date: 2007-06-16 15:02+0200\n"
+"PO-Revision-Date: 2007-06-16 13:02+0200\n"
+"Last-Translator: Dmitriy Moroz <zux@dimaka.org.ua>\n"
+"Language-Team: Ukrainian <root@archlinux.org.ua>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: openbox/action.c:991
+#, c-format
+msgid "Invalid action '%s' requested. No such action exists."
+msgstr "Здійснено запит на некоректну дію '%s'. Нема такої дії."
+
+#: openbox/action.c:994
+#, c-format
+msgid "Invalid use of action '%s'. Action will be ignored."
+msgstr "Некоректне викристання дії '%s'. Дія буде проігнорована."
+
+#: openbox/action.c:1261 openbox/action.c:1279 openbox/action.c:1292
+#, c-format
+msgid "Failed to execute '%s': %s"
+msgstr "Невдалося виконати '%s': %s"
+
+#: openbox/action.c:1300
+#, c-format
+msgid "Failed to convert the path '%s' from utf8"
+msgstr "Не вдалося сконвертувати шлях '%s' з utf8"
+
+#: openbox/client_list_combined_menu.c:104 openbox/client_list_menu.c:105
+msgid "Go there..."
+msgstr "Перейти...."
+
+#: openbox/client_list_combined_menu.c:150
+msgid "Windows"
+msgstr "Вікна"
+
+#: openbox/client_list_menu.c:196
+msgid "Desktops"
+msgstr "Стільниці"
+
+#: openbox/client_menu.c:258
+msgid "All desktops"
+msgstr "Всі стільниці"
+
+#: openbox/client_menu.c:363
+msgid "&Layer"
+msgstr "Шар(&L)"
+
+#: openbox/client_menu.c:368
+msgid "Always on &top"
+msgstr "Зверху всіх вікон(&T)"
+
+#: openbox/client_menu.c:369
+msgid "&Normal"
+msgstr "Звичайне положення(&N)"
+
+#: openbox/client_menu.c:370
+msgid "Always on &bottom"
+msgstr "Знизу всіх вікон(&B)"
+
+#: openbox/client_menu.c:373
+msgid "&Send to desktop"
+msgstr "Відправити на стільницю(&S)"
+
+#: openbox/client_menu.c:377
+msgid "Client menu"
+msgstr "Меню клієнтів"
+
+#: openbox/client_menu.c:383
+msgid "R&estore"
+msgstr "Відновити(&E)"
+
+#: openbox/client_menu.c:391
+msgid "&Move"
+msgstr "Перемістити(&M)"
+
+#: openbox/client_menu.c:393
+msgid "Resi&ze"
+msgstr "Змінити розмір(&Z)"
+
+#: openbox/client_menu.c:395
+msgid "Ico&nify"
+msgstr "Згорнути(&N)"
+
+#: openbox/client_menu.c:403
+msgid "Ma&ximize"
+msgstr "Розгорнути(&X)"
+
+#: openbox/client_menu.c:411
+msgid "&Roll up/down"
+msgstr "Скрутити/Розкрутити(&R)"
+
+#: openbox/client_menu.c:413
+msgid "Un/&Decorate"
+msgstr "(Від)декорувати(&D)"
+
+#: openbox/client_menu.c:423
+msgid "&Close"
+msgstr "Закрити(&C)"
+
+#: openbox/config.c:719
+#, c-format
+msgid "Invalid button '%s' specified in config file"
+msgstr "Некоректна клавіша '%s' вказана у файлі конфігурації"
+
+#: openbox/keyboard.c:164
+msgid "Conflict with key binding in config file"
+msgstr "Конфлікт прив'язки клавіш у файлі конфігурації"
+
+#: openbox/menu.c:100 openbox/menu.c:108
+#, c-format
+msgid "Unable to find a valid menu file '%s'"
+msgstr "Не вдалося знайти коректний файл меню '%s'"
+
+#: openbox/menu.c:168
+#, c-format
+msgid "Failed to execute command for pipe-menu '%s': %s"
+msgstr "Не вдалося виконати команду для pipe-меню '%s': %s"
+
+#: openbox/menu.c:182
+#, c-format
+msgid "Invalid output from pipe-menu '%s'"
+msgstr "Некоректний вивід з pipe-меню '%s'"
+
+#: openbox/menu.c:195
+#, c-format
+msgid "Attempted to access menu '%s' but it does not exist"
+msgstr "Спроба доступа до меню '%s' якого не існує"
+
+#: openbox/menu.c:356 openbox/menu.c:357
+msgid "More..."
+msgstr "Більше..."
+
+#: openbox/mouse.c:338
+#, c-format
+msgid "Invalid button '%s' in mouse binding"
+msgstr "Некоректна клавіша '%s' в прив'язці клавіш мишки"
+
+#: openbox/mouse.c:344
+#, c-format
+msgid "Invalid context '%s' in mouse binding"
+msgstr "Некоректний контекст '%s' в прив'зці клавіш мишки"
+
+#: openbox/openbox.c:129
+#, c-format
+msgid "Unable to change to home directory '%s': %s"
+msgstr "Не вдалося перейти в домашню директорію '%s': %s"
+
+#: openbox/openbox.c:149
+msgid "Failed to open the display from the DISPLAY environment variable."
+msgstr "Не вдалося відкрити дисплей зі змінної середовища DISPLAY"
+
+#: openbox/openbox.c:180
+msgid "Failed to initialize the obrender library."
+msgstr "Не вдалося ініцаілізувати бібліотеку obrender"
+
+#: openbox/openbox.c:186
+msgid "X server does not support locale."
+msgstr "X-сервер не підтримує локалі"
+
+#: openbox/openbox.c:188
+msgid "Cannot set locale modifiers for the X server."
+msgstr "Не можу встановити модифікатори локалі для X-сервера"
+
+#: openbox/openbox.c:249
+msgid "Unable to find a valid config file, using some simple defaults"
+msgstr ""
+"Не вдалося знайти коректний файл конфігурації, використовую стандартні "
+"налаштування"
+
+#: openbox/openbox.c:275
+msgid "Unable to load a theme."
+msgstr "Не вдалося загрузити стиль"
+
+#: openbox/openbox.c:401
+#, c-format
+msgid "Restart failed to execute new executable '%s': %s"
+msgstr ""
+"При перезавантаженні не вдалося виконати новий виконуваний файл '%s': %s"
+
+#: openbox/openbox.c:471 openbox/openbox.c:473
+msgid "Copyright (c)"
+msgstr "Авторські права (c)"
+
+#: openbox/openbox.c:482
+msgid "Syntax: openbox [options]\n"
+msgstr "Синтакс: openbox [параметри]\n"
+
+#: openbox/openbox.c:483
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Параметри:\n"
+
+#: openbox/openbox.c:484
+msgid " --help Display this help and exit\n"
+msgstr " --help Показати цю справку і вийти\n"
+
+#: openbox/openbox.c:485
+msgid " --version Display the version and exit\n"
+msgstr " --vesrion Показати версію і вийти\n"
+
+#: openbox/openbox.c:486
+msgid " --replace Replace the currently running window manager\n"
+msgstr " --replace Замінити поточний менеджер вікон\n"
+
+#: openbox/openbox.c:487
+msgid " --sm-disable Disable connection to the session manager\n"
+msgstr " --sm-disable Не з'єднуватися з сесійним менеджером\n"
+
+#: openbox/openbox.c:488
+msgid ""
+"\n"
+"Passing messages to a running Openbox instance:\n"
+msgstr ""
+"\n"
+"Передаю повідомлення процесу Openbox що виконується\n"
+
+#: openbox/openbox.c:489
+msgid " --reconfigure Reload Openbox's configuration\n"
+msgstr " --reconfigure Перезавантажити конфігурацію Openbox'у\n"
+
+#: openbox/openbox.c:490
+msgid " --restart Restart Openbox\n"
+msgstr " --restart Перезапустити Openbox\n"
+
+#: openbox/openbox.c:491
+msgid ""
+"\n"
+"Debugging options:\n"
+msgstr ""
+"\n"
+"Налагоджувальні параметри\n"
+
+#: openbox/openbox.c:492
+msgid " --sync Run in synchronous mode\n"
+msgstr " --sync Запустити в синхронному режимі\n"
+
+#: openbox/openbox.c:493
+msgid " --debug Display debugging output\n"
+msgstr " --debug Показувати інформацію налагоджування\n"
+
+#: openbox/openbox.c:494
+msgid " --debug-focus Display debugging output for focus handling\n"
+msgstr ""
+" --debug-focus Показувати інформацію налагоджування для уравління\n"
+
+#: openbox/openbox.c:495
+msgid " --debug-xinerama Split the display into fake xinerama screens\n"
+msgstr " --debug-xinerama Розбити екран на фальшиві екрани xinerama\n"
+
+#: openbox/openbox.c:496
+#, c-format
+msgid ""
+"\n"
+"Please report bugs at %s\n"
+msgstr ""
+"\n"
+"Будь-ласка, повідомляйте про помилки на %s\n"
+
+#: openbox/openbox.c:593
+#, c-format
+msgid "Invalid command line argument '%s'\n"
+msgstr "Некоректний командний аргумент '%s'\n"
+
+#: openbox/screen.c:94 openbox/screen.c:195
+#, c-format
+msgid "A window manager is already running on screen %d"
+msgstr "На дисплеї %d вже запущений менеджер вікон"
+
+#: openbox/screen.c:131
+#, c-format
+msgid "Could not acquire window manager selection on screen %d"
+msgstr "Не можу отримати вибір менеджера вікон на дисплеї %d"
+
+#: openbox/screen.c:152
+#, c-format
+msgid "The WM on screen %d is not exiting"
+msgstr "Менеджео вікон на дисплеї %d не завершується"
+
+#: openbox/screen.c:1006
+#, c-format
+msgid "desktop %i"
+msgstr "стільниця %i"
+
+#: openbox/session.c:103
+#, c-format
+msgid "Unable to make directory '%s': %s"
+msgstr "Не вдалося створити директорію '%s': %s"
+
+#: openbox/session.c:451
+#, c-format
+msgid "Unable to save the session to '%s': %s"
+msgstr "Не вдалося зберегти сесію в '%s': %s"
+
+#: openbox/session.c:583
+#, c-format
+msgid "Error while saving the session to '%s': %s"
+msgstr "Помилка при збереженні сесії в '%s': %s"
+
+#: openbox/startupnotify.c:237
+#, c-format
+msgid "Running %s\n"
+msgstr "Виконується %s\n"
+
+#: openbox/translate.c:58
+#, c-format
+msgid "Invalid modifier key '%s' in key/mouse binding"
+msgstr "Некоректна назва модифікатору '%s' у прив'язці клавіш клавіатури/мишки"
+
+#: openbox/translate.c:135
+#, c-format
+msgid "Invalid key code '%s' in key binding"
+msgstr "Некоректний код клавіши '%s' у прив'зці клавіш"
+
+#: openbox/translate.c:142
+#, c-format
+msgid "Invalid key name '%s' in key binding"
+msgstr "Некоректна назва клавіши '%s' у прив'язці клавіш"
+
+#: openbox/translate.c:148
+#, c-format
+msgid "Requested key '%s' does not exist on the display"
+msgstr "Клавіша '%s' на яку здійснено запит - не існує на дисплеї"
+
+#: openbox/xerror.c:39
+#, c-format
+msgid "X Error: %s"
+msgstr "Помилка X-серверу: %s"
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);
NEXT(y3);
}
-
- RrColorFree(primary_light);
- RrColorFree(secondary_light);
}
static void gradient_horizontal(RrSurface *sf, gint w, gint h)
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;
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);
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 {
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;
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) {
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);
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
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