focus_order_add_new(self);
/* focus the new window? */
- if (ob_state != State_Starting && config_focus_new &&
+ if (ob_state != OB_STATE_STARTING && config_focus_new &&
(self->type == Type_Normal || self->type == Type_Dialog)) {
gboolean group_foc = FALSE;
stacking_add(CLIENT_AS_WINDOW(self));
}
- screen_update_struts();
+ dispatch_client(Event_Client_New, self, 0, 0);
/* make sure the window is visible */
client_move_onscreen(self);
- dispatch_client(Event_Client_New, self, 0, 0);
+ screen_update_areas();
client_showhide(self);
/* once the client is out of the list, update the struts to remove it's
influence */
- screen_update_struts();
+ screen_update_areas();
/* tell our parent(s) that we're gone */
if (self->transient_for == TRAN_GROUP) { /* transient of group */
frame_release_client(self->frame, self);
self->frame = NULL;
- if (ob_state != State_Exiting) {
+ if (ob_state != OB_STATE_EXITING) {
/* these values should not be persisted across a window
unmapping/mapping */
prop_erase(self->window, prop_atoms.net_wm_desktop);
Rect *a;
int x = self->frame->area.x, y = self->frame->area.y;
+ /* XXX watch for xinerama dead areas */
a = screen_area(self->desktop);
if (x >= a->x + a->width - 1)
x = a->x + a->width - self->frame->area.width;
frame_frame_gravity(self->frame, &x, &y); /* get where the client
should be */
- client_configure(self , Corner_TopLeft, x, y,
+ client_configure(self, OB_CORNER_TOPLEFT, x, y,
self->area.width, self->area.height,
TRUE, TRUE);
}
static void client_get_desktop(Client *self)
{
- guint32 d;
+ guint32 d = screen_num_desktops; /* an always-invalid value */
if (PROP_GET32(self->window, net_wm_desktop, cardinal, &d)) {
if (d >= screen_num_desktops && d != DESKTOP_ALL)
- d = screen_num_desktops - 1;
- self->desktop = d;
- } else {
+ self->desktop = screen_num_desktops - 1;
+ else
+ self->desktop = d;
+ } else {
gboolean trdesk = FALSE;
if (self->transient_for) {
/* defaults to the current desktop */
self->desktop = screen_desktop;
+ }
+ if (self->desktop != d) {
/* set the desktop hint, to make sure that it always exists */
PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
}
if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL)
client_set_desktop(self, DESKTOP_ALL, FALSE);
- /* change the decors on the frame, and with more/less decorations,
- we may also need to be repositioned */
- frame_adjust_area(self->frame, TRUE, TRUE);
- /* with new decor, the window's maximized size may change */
+ /* adjust the client's decorations, etc. */
client_reconfigure(self);
} else {
/* this makes sure that these windows appear on all desktops */
void client_reconfigure(Client *self)
{
- client_configure(self, Corner_TopLeft, self->area.x, self->area.y,
- self->area.width, self->area.height, TRUE, TRUE);
+ /* by making this pass FALSE for user, we avoid the emacs event storm where
+ every configurenotify causes an update in its normal hints, i think this
+ is generally what we want anyways... */
+ client_configure(self, OB_CORNER_TOPLEFT, self->area.x, self->area.y,
+ self->area.width, self->area.height, FALSE, TRUE);
}
void client_update_wmhints(Client *self)
/* only do this when first managing the window *AND* when we aren't
starting up! */
- if (ob_state != State_Starting && self->frame == NULL)
+ if (ob_state != OB_STATE_STARTING && self->frame == NULL)
if (hints->flags & StateHint)
self->iconic = hints->initial_state == IconicState;
/* updating here is pointless while we're being mapped cuz we're not in
the client list yet */
if (self->frame)
- screen_update_struts();
+ screen_update_areas();
}
void client_update_icons(Client *self)
++y;
}
self->icons[j].data[t] =
- (((data[i] >> 24) & 0xff) << default_alpha_offset) +
- (((data[i] >> 16) & 0xff) << default_red_offset) +
- (((data[i] >> 8) & 0xff) << default_green_offset) +
- (((data[i] >> 0) & 0xff) << default_blue_offset);
+ (((data[i] >> 24) & 0xff) << RrDefaultAlphaOffset) +
+ (((data[i] >> 16) & 0xff) << RrDefaultRedOffset) +
+ (((data[i] >> 8) & 0xff) << RrDefaultGreenOffset) +
+ (((data[i] >> 0) & 0xff) << RrDefaultBlueOffset);
}
g_assert(i <= num);
}
return l;
}
-static void calc_recursive(Client *self, Client *orig, StackLayer l,
- gboolean raised)
+static void client_calc_layer_recursive(Client *self, Client *orig,
+ StackLayer l, gboolean raised)
{
StackLayer old, own;
GSList *it;
self->layer = l > own ? l : own;
for (it = self->transients; it; it = it->next)
- calc_recursive(it->data, orig, l, raised ? raised : l != old);
+ client_calc_layer_recursive(it->data, orig,
+ l, raised ? raised : l != old);
if (!raised && l != old)
- if (orig->frame) /* only restack if the original window is managed */
- stacking_raise(CLIENT_AS_WINDOW(self));
+ if (orig->frame) { /* only restack if the original window is managed */
+ /* XXX add_non_intrusive ever? */
+ stacking_remove(CLIENT_AS_WINDOW(self));
+ stacking_add(CLIENT_AS_WINDOW(self));
+ }
}
void client_calc_layer(Client *self)
orig = self;
/* transients take on the layer of their parents */
- if (self->transient_for) {
- if (self->transient_for != TRAN_GROUP) {
- self = self->transient_for;
- } else {
- GSList *it;
-
- for (it = self->group->members; it; it = it->next)
- if (it->data != self &&
- !((Client*)it->data)->transient_for) {
- self = it->data;
- break;
- }
- }
- }
+ self = client_search_top_transient(self);
l = calc_layer(self);
- calc_recursive(self, orig, l, FALSE);
+ client_calc_layer_recursive(self, orig, l, FALSE);
}
gboolean client_should_show(Client *self)
*/
}
-void client_configure(Client *self, Corner anchor, int x, int y, int w, int h,
+void client_configure(Client *self, ObCorner anchor,
+ int x, int y, int w, int h,
gboolean user, gboolean final)
{
gboolean moved = FALSE, resized = FALSE;
#ifdef VIDMODE
int dot;
XF86VidModeModeLine mode;
+#endif
+ Rect *a;
+ guint i;
- if (XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) {
+ i = client_monitor(self);
+ a = screen_physical_area_monitor(i);
+
+#ifdef VIDMODE
+ if (i == 0 && /* primary head */
+ extensions_vidmode &&
+ XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y) &&
+ /* get the mode last so the mode.privsize isnt freed incorrectly */
+ XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) {
+ x += a->x;
+ y += a->y;
w = mode.hdisplay;
h = mode.vdisplay;
if (mode.privsize) XFree(mode.private);
- } else {
-#else
- w = screen_physical_size.width;
- h = screen_physical_size.height;
-#endif
-#ifdef VIDMODE
- }
- if (!XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y)) {
- x = y = 0;
+ } else
#endif
+ {
+ x = a->x;
+ y = a->y;
+ w = a->width;
+ h = a->height;
}
+
user = FALSE; /* ignore that increment etc shit when in fullscreen */
} else {
+ Rect *a;
+
+ a = screen_area_monitor(self->desktop, client_monitor(self));
+
/* set the size and position if maximized */
if (self->max_horz) {
- x = screen_area(self->desktop)->x - self->frame->size.left;
- w = screen_area(self->desktop)->width;
+ x = a->x - self->frame->size.left;
+ w = a->width;
}
if (self->max_vert) {
- y = screen_area(self->desktop)->y;
- h = screen_area(self->desktop)->height -
- self->frame->size.top - self->frame->size.bottom;
+ y = a->y;
+ h = a->height - self->frame->size.top - self->frame->size.bottom;
}
}
}
switch (anchor) {
- case Corner_TopLeft:
+ case OB_CORNER_TOPLEFT:
break;
- case Corner_TopRight:
+ case OB_CORNER_TOPRIGHT:
x -= w - self->area.width;
break;
- case Corner_BottomLeft:
+ case OB_CORNER_BOTTOMLEFT:
y -= h - self->area.height;
break;
- case Corner_BottomRight:
+ case OB_CORNER_BOTTOMRIGHT:
x -= w - self->area.width;
y -= h - self->area.height;
break;
/* move/resize the frame to match the request */
if (self->frame) {
+ if (self->decorations != self->frame->decorations)
+ moved = resized = TRUE;
+
if (moved || resized)
frame_adjust_area(self->frame, moved, resized);
clients (emacs) freaking out, cuz they send back a configure every
time they receive this event, which resends them this event... etc.
*/
- if ((moved || resized) && (!user || final)) {
+ if ((!user && moved) || (user && final)) {
XEvent event;
event.type = ConfigureNotify;
event.xconfigure.display = ob_display;
} else {
guint num;
gint32 *dimensions;
+ Rect *a;
/* pick some fallbacks... */
- x = screen_area(self->desktop)->x +
- screen_area(self->desktop)->width / 4;
- y = screen_area(self->desktop)->y +
- screen_area(self->desktop)->height / 4;
- w = screen_area(self->desktop)->width / 2;
- h = screen_area(self->desktop)->height / 2;
+ a = screen_area_monitor(self->desktop, 0);
+ x = a->x + a->width / 4;
+ y = a->y + a->height / 4;
+ w = a->width / 2;
+ h = a->height / 2;
if (PROP_GETA32(self->window, openbox_premax, cardinal,
(guint32**)&dimensions, &num)) {
client_setup_decor_and_functions(self);
- client_configure(self, Corner_TopLeft, x, y, w, h, TRUE, TRUE);
+ client_configure(self, OB_CORNER_TOPLEFT, x, y, w, h, TRUE, TRUE);
/* try focus us when we go into fullscreen mode */
client_focus(self);
}
-void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
+static void client_iconify_recursive(Client *self,
+ gboolean iconic, gboolean curdesk)
{
GSList *it;
+ gboolean changed = FALSE;
- /* move up the transient chain as far as possible first */
- if (self->transient_for) {
- if (self->transient_for != TRAN_GROUP) {
- if (self->transient_for->iconic != iconic) {
- client_iconify(self->transient_for, iconic, curdesk);
- return;
- }
- } else {
- GSList *it;
-
- for (it = self->group->members; it; it = it->next) {
- Client *c = it->data;
- if (c != self && c->iconic != iconic &&
- !c->transient_for) {
- client_iconify(it->data, iconic, curdesk);
- break;
- }
- }
- if (it != NULL) return;
- }
- }
- if (self->iconic == iconic) return; /* nothing to do */
+ if (self->iconic != iconic) {
+ g_message("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
+ self->window);
- g_message("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
- self->window);
+ self->iconic = iconic;
- self->iconic = iconic;
+ if (iconic) {
+ if (self->functions & Func_Iconify) {
+ self->wmstate = IconicState;
+ self->ignore_unmaps++;
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(ob_display, self->window);
- if (iconic) {
- self->wmstate = IconicState;
- self->ignore_unmaps++;
- /* we unmap the client itself so that we can get MapRequest events,
- and because the ICCCM tells us to! */
- XUnmapWindow(ob_display, self->window);
+ /* update the focus lists.. iconic windows go to the bottom of
+ the list, put the new iconic window at the 'top of the
+ bottom'. */
+ focus_order_to_top(self);
- /* update the focus lists.. iconic windows go to the bottom of the
- list, put the new iconic window at the 'top of the bottom'. */
- focus_order_to_top(self);
- } else {
- if (curdesk)
- client_set_desktop(self, screen_desktop, FALSE);
- self->wmstate = self->shaded ? IconicState : NormalState;
- XMapWindow(ob_display, self->window);
+ changed = TRUE;
+ }
+ } else {
+ if (curdesk)
+ client_set_desktop(self, screen_desktop, FALSE);
+ self->wmstate = self->shaded ? IconicState : NormalState;
+ XMapWindow(ob_display, self->window);
+
+ /* this puts it after the current focused window */
+ focus_order_remove(self);
+ focus_order_add_new(self);
+
+ /* this is here cuz with the VIDMODE extension, the viewport can
+ change while a fullscreen window is iconic, and when it
+ uniconifies, it would be nice if it did so to the new position
+ of the viewport */
+ client_reconfigure(self);
+
+ changed = TRUE;
+ }
+ }
- /* this puts it after the current focused window */
- focus_order_remove(self);
- focus_order_add_new(self);
+ if (changed) {
+ client_change_state(self);
+ client_showhide(self);
+ screen_update_areas();
- /* this is here cuz with the VIDMODE extension, the viewport can change
- while a fullscreen window is iconic, and when it uniconifies, it
- would be nice if it did so to the new position of the viewport */
- client_reconfigure(self);
+ dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
+ self, 0, 0);
}
- client_change_state(self);
- client_showhide(self);
- screen_update_struts();
-
- dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
- self, 0, 0);
/* iconify all transients */
for (it = self->transients; it != NULL; it = it->next)
- if (it->data != self) client_iconify(it->data, iconic, curdesk);
+ if (it->data != self) client_iconify_recursive(it->data,
+ iconic, curdesk);
+}
+
+void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
+{
+ /* move up the transient chain as far as possible first */
+ self = client_search_top_transient(self);
+
+ client_iconify_recursive(client_search_top_transient(self),
+ iconic, curdesk);
}
void client_maximize(Client *self, gboolean max, int dir, gboolean savearea)
} else {
guint num;
gint32 *dimensions;
+ Rect *a;
/* pick some fallbacks... */
+ a = screen_area_monitor(self->desktop, 0);
if (dir == 0 || dir == 1) { /* horz */
- x = screen_area(self->desktop)->x +
- screen_area(self->desktop)->width / 4;
- w = screen_area(self->desktop)->width / 2;
+ x = a->x + a->width / 4;
+ w = a->width / 2;
}
if (dir == 0 || dir == 2) { /* vert */
- y = screen_area(self->desktop)->y +
- screen_area(self->desktop)->height / 4;
- h = screen_area(self->desktop)->height / 2;
+ y = a->y + a->height / 4;
+ h = a->height / 2;
}
if (PROP_GETA32(self->window, openbox_premax, cardinal,
/* figure out where the client should be going */
frame_frame_gravity(self->frame, &x, &y);
- client_configure(self, Corner_TopLeft, x, y, w, h, TRUE, TRUE);
+ client_configure(self, OB_CORNER_TOPLEFT, x, y, w, h, TRUE, TRUE);
}
void client_shade(Client *self, gboolean shade)
XKillClient(ob_display, self->window);
}
-void client_set_desktop(Client *self, guint target, gboolean donthide)
+void client_set_desktop_recursive(Client *self,
+ guint target, gboolean donthide)
{
guint old;
+ GSList *it;
- if (target == self->desktop) return;
-
- g_message("Setting desktop %u", target+1);
+ if (target != self->desktop) {
- g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
+ g_message("Setting desktop %u", target+1);
- /* remove from the old desktop(s) */
- focus_order_remove(self);
+ g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
- old = self->desktop;
- self->desktop = target;
- PROP_SET32(self->window, net_wm_desktop, cardinal, target);
- /* the frame can display the current desktop state */
- frame_adjust_state(self->frame);
- /* 'move' the window to the new desktop */
- if (!donthide)
- client_showhide(self);
- /* raise if it was not already on the desktop */
- if (old != DESKTOP_ALL)
- stacking_raise(CLIENT_AS_WINDOW(self));
- screen_update_struts();
-
- /* add to the new desktop(s) */
- if (config_focus_new)
- focus_order_to_top(self);
- else
- focus_order_to_bottom(self);
+ /* remove from the old desktop(s) */
+ focus_order_remove(self);
+
+ old = self->desktop;
+ self->desktop = target;
+ PROP_SET32(self->window, net_wm_desktop, cardinal, target);
+ /* the frame can display the current desktop state */
+ frame_adjust_state(self->frame);
+ /* 'move' the window to the new desktop */
+ if (!donthide)
+ client_showhide(self);
+ /* raise if it was not already on the desktop */
+ if (old != DESKTOP_ALL)
+ stacking_raise(CLIENT_AS_WINDOW(self));
+ screen_update_areas();
+
+ /* add to the new desktop(s) */
+ if (config_focus_new)
+ focus_order_to_top(self);
+ else
+ focus_order_to_bottom(self);
- dispatch_client(Event_Client_Desktop, self, target, old);
+ dispatch_client(Event_Client_Desktop, self, target, old);
+ }
+
+ /* move all transients */
+ for (it = self->transients; it != NULL; it = it->next)
+ if (it->data != self) client_set_desktop_recursive(it->data,
+ target, donthide);
+}
+
+void client_set_desktop(Client *self, guint target, gboolean donthide)
+{
+ client_set_desktop_recursive(client_search_top_transient(self),
+ target, donthide);
}
Client *client_search_modal_child(Client *self)
}
/* this be mostly ripped from fvwm */
-Client *client_find_directional(Client *c, Direction dir)
+Client *client_find_directional(Client *c, ObDirection dir)
{
int my_cx, my_cy, his_cx, his_cy;
int offset = 0;
}
switch(dir) {
- case Direction_North :
- case Direction_South :
- case Direction_NorthEast :
- case Direction_SouthWest :
+ case OB_DIRECTION_NORTH:
+ case OB_DIRECTION_SOUTH:
+ case OB_DIRECTION_NORTHEAST:
+ case OB_DIRECTION_SOUTHWEST:
offset = (his_cx < 0) ? -his_cx : his_cx;
- distance = (dir == Direction_North || dir == Direction_NorthEast) ?
- -his_cy : his_cy;
+ distance = ((dir == OB_DIRECTION_NORTH ||
+ dir == OB_DIRECTION_NORTHEAST) ?
+ -his_cy : his_cy);
break;
- case Direction_East :
- case Direction_West :
- case Direction_SouthEast :
- case Direction_NorthWest :
+ case OB_DIRECTION_EAST:
+ case OB_DIRECTION_WEST:
+ case OB_DIRECTION_SOUTHEAST:
+ case OB_DIRECTION_NORTHWEST:
offset = (his_cy < 0) ? -his_cy : his_cy;
- distance = (dir == Direction_West || dir == Direction_NorthWest) ?
- -his_cx : his_cx;
+ distance = ((dir == OB_DIRECTION_WEST ||
+ dir == OB_DIRECTION_NORTHWEST) ?
+ -his_cx : his_cx);
break;
}
client_calc_layer(self);
client_change_state(self); /* reflect this in the state hints */
}
+
+guint client_monitor(Client *self)
+{
+ guint i;
+
+ for (i = 0; i < screen_num_monitors; ++i) {
+ Rect *area = screen_physical_area_monitor(i);
+ if (RECT_INTERSECTS_RECT(*area, self->frame->area))
+ break;
+ }
+ if (i == screen_num_monitors) i = 0;
+ g_assert(i < screen_num_monitors);
+ return i;
+}
+
+Client *client_search_top_transient(Client *self)
+{
+ /* move up the transient chain as far as possible */
+ if (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {
+ return client_search_top_transient(self->transient_for);
+ } else {
+ GSList *it;
+
+ for (it = self->group->members; it; it = it->next) {
+ Client *c = it->data;
+
+ /* checking transient_for prevents infinate loops! */
+ if (c != self && !c->transient_for)
+ break;
+ }
+ if (it)
+ return it->data;
+ }
+ }
+
+ return self;
+}