GList *client_list = NULL;
static GSList *client_destroy_notifies = NULL;
-static GSList *client_hide_notifies = NULL;
static void client_get_all(ObClient *self, gboolean real);
static void client_toggle_border(ObClient *self, gboolean show);
}
}
-void client_add_hide_notify(ObClientCallback func, gpointer data)
-{
- ClientCallback *d = g_new(ClientCallback, 1);
- d->func = func;
- d->data = data;
- client_hide_notifies = g_slist_prepend(client_hide_notifies, d);
-}
-
-void client_remove_hide_notify(ObClientCallback func)
-{
- GSList *it;
-
- for (it = client_hide_notifies; it; it = g_slist_next(it)) {
- ClientCallback *d = it->data;
- if (d->func == func) {
- g_free(d);
- client_hide_notifies =
- g_slist_delete_link(client_hide_notifies, it);
- break;
- }
- }
-}
-
void client_set_list()
{
Window *windows, *win_it;
do this after adjusting the frame. otherwise it gets all weird and
clients don't work right */
- client_configure_full(self, self->area.x, self->area.y,
- self->area.width, self->area.height,
- FALSE, TRUE);
+ client_configure(self, self->area.x, self->area.y,
+ self->area.width, self->area.height,
+ FALSE, TRUE);
/* do this after the window is placed, so the premax/prefullscreen numbers
won't be all wacko!!
OB_CLIENT_FUNC_SHADE |
OB_CLIENT_FUNC_CLOSE |
OB_CLIENT_FUNC_BELOW |
- OB_CLIENT_FUNC_ABOVE);
+ OB_CLIENT_FUNC_ABOVE |
+ OB_CLIENT_FUNC_UNDECORATE);
if (!(self->min_size.width < self->max_size.width ||
self->min_size.height < self->max_size.height))
if (self->max_vert && self->max_horz)
self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS);
+ /* If there are no decorations to remove, don't allow the user to try
+ toggle the state */
+ if (self->decorations == 0)
+ self->functions &= ~OB_CLIENT_FUNC_UNDECORATE;
+
/* finally, the user can have requested no decorations, which overrides
everything (but doesnt give it a border if it doesnt have one) */
if (self->undecorated) {
else l = OB_STACKING_LAYER_ABOVE;
}
else if ((self->fullscreen ||
- /* no decorations and fills the monitor = oldskool fullscreen */
- (self->frame != NULL &&
- (self->frame->size.right == 0 && self->frame->size.left == 0 &&
- self->frame->size.bottom == 0 && self->frame->size.top == 0 &&
- RECT_EQUAL(self->area,
- *screen_physical_area_monitor
- (client_monitor(self))))))) {
- if (client_focused(self) || client_search_focus_tree(self))
- l = OB_STACKING_LAYER_FULLSCREEN;
- else
- l = OB_STACKING_LAYER_FULLSCREEN_BELOW;
- }
+ /* No decorations and fills the monitor = oldskool fullscreen.
+ But not for undecorated windows, because the user can do that
+ */
+ (self->decorations == 0 &&
+ !self->undecorated &&
+ RECT_EQUAL(self->area,
+ *screen_physical_area_monitor
+ (client_monitor(self))))) &&
+ (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;
return FALSE;
}
-void client_show(ObClient *self)
+gboolean client_show(ObClient *self)
{
+ gboolean show = FALSE;
if (client_should_show(self)) {
frame_show(self->frame);
+ show = TRUE;
}
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
desktop!
*/
client_change_wm_state(self);
+ return show;
}
-void client_hide(ObClient *self)
+gboolean client_hide(ObClient *self)
{
+ gboolean hide = FALSE;
+
if (!client_should_show(self)) {
- frame_hide(self->frame);
+ if (self == focus_client) {
+ /* if there is a grab going on, then we need to cancel it. if we
+ move focus during the grab, applications will get
+ NotifyWhileGrabbed events and ignore them !
+
+ actions should not rely on being able to move focus during an
+ interactive grab.
+ */
+ if (keyboard_interactively_grabbed())
+ keyboard_interactive_cancel();
+ }
- client_call_notifies(self, client_hide_notifies);
+ frame_hide(self->frame);
+ hide = TRUE;
}
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
desktop!
*/
client_change_wm_state(self);
+ return hide;
}
void client_showhide(ObClient *self)
{
-
- if (client_should_show(self)) {
- frame_show(self->frame);
- }
- else {
- frame_hide(self->frame);
-
- client_call_notifies(self, client_hide_notifies);
- }
+ if (!client_show(self))
+ client_hide(self);
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
needs to be in IconicState. This includes when it is on another
}
-void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
- gboolean user, gboolean final)
+void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
+ gboolean user, gboolean final)
{
gint oldw, oldh;
gboolean send_resize_client;
gboolean moved = FALSE, resized = FALSE;
+ gboolean fmoved, fresized;
guint fdecor = self->frame->decorations;
gboolean fhorz = self->frame->max_horz;
gint logicalw, logicalh;
}
/* find the frame's dimensions and move/resize it */
+ fmoved = moved;
+ fresized = resized;
if (self->decorations != fdecor || self->max_horz != fhorz)
- moved = resized = TRUE;
- if (moved || resized)
- frame_adjust_area(self->frame, moved, resized, FALSE);
+ fmoved = fresized = TRUE;
+ if (fmoved || fresized)
+ frame_adjust_area(self->frame, fmoved, fresized, FALSE);
if ((!user || (user && final)) && !resized)
{
}
}
}
+
if (max_horz != self->max_horz || max_vert != self->max_vert) {
if (max_horz != self->max_horz && max_vert != self->max_vert) {
/* toggling both */
client_shade(self, shaded);
if (undecorated != self->undecorated)
client_set_undecorated(self, undecorated);
+ if (above != self->above || below != self->below) {
+ self->above = above;
+ self->below = below;
+ client_calc_layer(self);
+ }
+
if (modal != self->modal) {
self->modal = modal;
/* when a window changes modality, then its stacking order with its
transients needs to change */
stacking_raise(CLIENT_AS_WINDOW(self));
+
+ /* it also may get focused. if something is focused that shouldn't
+ be focused anymore, then move the focus */
+ if (focus_client && client_focus_target(focus_client) != focus_client)
+ client_focus(focus_client);
}
+
if (iconic != self->iconic)
client_iconify(self, iconic, FALSE, FALSE);
if (demands_attention != self->demands_attention)
client_hilite(self, demands_attention);
- if (above != self->above || below != self->below) {
- self->above = above;
- self->below = below;
- client_calc_layer(self);
- }
-
client_change_state(self); /* change the hint to reflect these changes */
}
gboolean client_focus(ObClient *self)
{
- gboolean error;
-
/* choose the correct target */
self = client_focus_target(self);
if (keyboard_interactively_grabbed())
keyboard_interactive_cancel();
- error = FALSE;
xerror_set_ignore(TRUE);
+ xerror_occured = FALSE;
if (self->can_focus) {
/* This can cause a BadMatch error with CurrentTime, or if an app
XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
}
- /* This calls XSync, which will cause the FocusIn to come back to us.
- That's important for desktop switches, since otherwise we'll have no
- FocusIn on the queue and end up falling back again. */
xerror_set_ignore(FALSE);
- if (!xerror_occured) error = TRUE;
- return !error;
+ return !xerror_occured;
}
/*! Present the client to the user.
void client_set_undecorated(ObClient *self, gboolean undecorated)
{
- if (self->undecorated != undecorated) {
+ if (self->undecorated != undecorated &&
+ /* don't let it undecorate if the function is missing, but let
+ it redecorate */
+ (self->functions & OB_CLIENT_FUNC_UNDECORATE || !undecorated))
+ {
self->undecorated = undecorated;
client_setup_decor_and_functions(self);
- /* Make sure the client knows it might have moved. Maybe there is a
- * better way of doing this so only one client_configure is sent, but
- * since 125 of these are sent per second when moving the window (with
- * user = FALSE) i doubt it matters much.
- */
- client_configure(self, self->area.x, self->area.y,
- self->area.width, self->area.height, TRUE, TRUE);
client_change_state(self); /* reflect this in the state hints */
}
}