#include "prop.h"
#include "extensions.h"
#include "frame.h"
-#include "engine.h"
#include "event.h"
#include "grab.h"
#include "focus.h"
#include "stacking.h"
#include "dispatch.h"
#include "group.h"
+#include "config.h"
#include <glib.h>
#include <X11/Xutil.h>
client_startup_stack_order = NULL;
client_startup_stack_size = 0;
- if (focus_new)
+ if (config_focus_new)
focus_fallback(Fallback_NoFocus);
}
XChangeSaveSet(ob_display, window, SetModeInsert);
/* create the decoration frame for the client window */
- self->frame = engine_frame_new();
+ self->frame = frame_new();
- engine_frame_grab_client(self->frame, self);
+ frame_grab_client(self->frame, self);
client_apply_startup_state(self);
dispatch_client(Event_Client_Mapped, self, 0, 0);
- if (ob_state != State_Starting && focus_new)
- client_focus(self);
+ /* focus the new window? */
+ if (ob_state != State_Starting && client_normal(self)) {
+ if (config_focus_new)
+ client_focus(self);
+ else if (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {/* transient of a window */
+ if (focus_client == self->transient_for)
+ client_focus(self);
+ } else { /* transient of a group */
+ GSList *it;
+
+ for (it = self->group->members; it; it = it->next)
+ if (focus_client == it->data) {
+ client_focus(self);
+ break;
+ }
+ }
+ }
+ }
/* update the list hints */
client_set_list();
/* we dont want events no more */
XSelectInput(ob_display, self->window, NoEventMask);
- engine_frame_hide(self->frame);
+ frame_hide(self->frame);
client_list = g_list_remove(client_list, self);
stacking_list = g_list_remove(stacking_list, self);
client_toggle_border(self, TRUE);
/* reparent the window out of the frame, and free the frame */
- engine_frame_release_client(self->frame, self);
+ frame_release_client(self->frame, self);
self->frame = NULL;
if (ob_state != State_Exiting) {
break;
case Type_Dialog:
- /* dialogs cannot be maximized */
+ case Type_Utility:
+ /* these windows cannot be maximized */
self->decorations &= ~Decor_Maximize;
self->functions &= ~Func_Maximize;
break;
case Type_Menu:
case Type_Toolbar:
- case Type_Utility:
/* these windows get less functionality */
self->decorations &= ~(Decor_Iconify | Decor_Handle);
self->functions &= ~(Func_Iconify | Func_Resize);
if (!(self->decorations & Decor_Titlebar))
self->functions &= ~Func_Shade;
+ /* now we need to check against rules for the client's current state */
+ if (self->fullscreen) {
+ self->functions &= (Func_Close | Func_Fullscreen | Func_Iconify);
+ self->decorations = 0;
+ }
+
client_change_allowed_actions(self);
if (self->frame) {
/* change the decors on the frame, and with more/less decorations,
we may also need to be repositioned */
- engine_frame_adjust_area(self->frame, TRUE, TRUE);
+ frame_adjust_area(self->frame, TRUE, TRUE);
/* with new decor, the window's maximized size may change */
client_remaximize(self);
}
self->pixmap_icon_mask = None;
if (self->frame)
- engine_frame_adjust_icon(self->frame);
+ frame_adjust_icon(self->frame);
}
}
self->title = data;
if (self->frame)
- engine_frame_adjust_title(self->frame);
+ frame_adjust_title(self->frame);
}
void client_update_icon_title(Client *self)
}
if (self->frame)
- engine_frame_adjust_icon(self->frame);
+ frame_adjust_icon(self->frame);
}
void client_update_kwm_icon(Client *self)
self->pixmap_icon = self->pixmap_icon_mask = None;
}
if (self->frame)
- engine_frame_adjust_icon(self->frame);
+ frame_adjust_icon(self->frame);
}
static void client_change_state(Client *self)
client_calc_layer(self);
if (self->frame)
- engine_frame_adjust_state(self->frame);
+ frame_adjust_state(self->frame);
}
static Client *search_focus_tree(Client *node, Client *skip)
return NULL;
}
+static void calc_recursive(Client *self, StackLayer l, gboolean raised)
+{
+ StackLayer old;
+ GSList *it;
+
+ old = self->layer;
+ self->layer = l;
+
+ for (it = self->transients; it; it = it->next)
+ calc_recursive(it->data, l, raised ? raised : l != old);
+
+ if (!raised && l != old)
+ if (self->frame)
+ stacking_raise(self);
+}
+
void client_calc_layer(Client *self)
{
StackLayer l;
- gboolean fs;
- Client *c;
-
- /* are we fullscreen, or do we have a fullscreen transient parent? */
- c = self;
- fs = FALSE;
- while (c && c != TRAN_GROUP) { /* XXX do smthng with the TRAN_GROUP case?*/
- if (c->fullscreen) {
- fs = TRUE;
- break;
- }
- c = c->transient_for;
- }
- if (!fs && self->fullscreen) {
- /* is one of our transients focused? */
- c = search_focus_tree(self, self);
- if (c != NULL) fs = TRUE;
+ gboolean f;
+
+ /* 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 != TRAN_GROUP) {
+ self = self->transient_for;
+ break;
+ }
+ }
}
-
+
+ /* is us or one of our transients focused? */
+ if (client_focused(self))
+ f = TRUE;
+ else if (search_focus_tree(self, self))
+ f = TRUE;
+ else
+ f = FALSE;
+
if (self->iconic) l = Layer_Icon;
- else if (fs) l = Layer_Fullscreen;
+ /* fullscreen windows are only in the fullscreen layer while focused */
+ else if (self->fullscreen && f) l = Layer_Fullscreen;
else if (self->type == Type_Desktop) l = Layer_Desktop;
else if (self->type == Type_Dock) {
- if (!self->below) l = Layer_Top;
- else l = Layer_Normal;
+ if (!self->below) l = Layer_Top;
+ else l = Layer_Normal;
}
else if (self->above) l = Layer_Above;
else if (self->below) l = Layer_Below;
else l = Layer_Normal;
-
- if (l != self->layer) {
- self->layer = l;
- if (self->frame)
- stacking_raise(self);
- }
+
+ calc_recursive(self, l, FALSE);
}
gboolean client_should_show(Client *self)
{
if (client_should_show(self))
- engine_frame_show(self->frame);
+ frame_show(self->frame);
else
- engine_frame_hide(self->frame);
+ frame_hide(self->frame);
}
gboolean client_normal(Client *self) {
y = 0;
w = screen_physical_size.width;
h = screen_physical_size.height;
+ user = FALSE; /* ignore that increment etc shit when in fullscreen */
} else {
/* set the size and position if maximized */
if (self->max_horz) {
/* move/resize the frame to match the request */
if (self->frame) {
if (moved || resized)
- engine_frame_adjust_area(self->frame, moved, resized);
+ frame_adjust_area(self->frame, moved, resized);
if (!user || final) {
XEvent event;
self->fullscreen == fs) return; /* already done */
self->fullscreen = fs;
- client_change_state(self); /* change the state hints on the client */
+ client_change_state(self); /* change the state hints on the client,
+ and adjust out layer/stacking */
if (fs) {
- /* save the functions and remove them */
- self->pre_fs_func = self->functions;
- self->functions &= (Func_Close | Func_Fullscreen |
- Func_Iconify);
- /* save the decorations and remove them */
- self->pre_fs_decor = self->decorations;
- self->decorations = 0;
if (savearea) {
long dimensions[4];
dimensions[0] = self->area.x;
} else {
long *dimensions;
- self->functions = self->pre_fs_func;
- self->decorations = self->pre_fs_decor;
-
if (PROP_GET32A(self->window, openbox_premax, cardinal,
dimensions, 4)) {
x = dimensions[0];
}
}
- client_change_allowed_actions(self); /* based on the new _functions */
-
- /* when fullscreening, don't obey things like increments, fill the
- screen */
- client_configure(self, Corner_TopLeft, x, y, w, h, !fs, TRUE);
+ client_setup_decor_and_functions(self);
- /* raise (back) into our stacking layer */
- stacking_raise(self);
+ client_configure(self, 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)
{
+ GSList *it;
+
+ /* move up the transient chain as far as possible first if deiconifying */
+ if (!iconic)
+ while (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {
+ if (self->transient_for->iconic == iconic)
+ break;
+ self = self->transient_for;
+ } else {
+ GSList *it;
+
+ /* the check for TRAN_GROUP is to prevent an infinate loop with
+ 2 transients of the same group at the head of the group's
+ members list */
+ for (it = self->group->members; it; it = it->next) {
+ Client *c = it->data;
+
+ if (c != self && c->transient_for->iconic != iconic &&
+ c->transient_for != TRAN_GROUP) {
+ self = it->data;
+ break;
+ }
+ }
+ if (it == NULL) break;
+ }
+ }
+
if (self->iconic == iconic) return; /* nothing to do */
g_message("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
self, 0, 0);
/* iconify all transients */
- if (self->transients) {
- GSList *it;
-
- for (it = self->transients; it != NULL; it = it->next)
- if (it->data != self) client_iconify(it->data, iconic, curdesk);
- }
+ for (it = self->transients; it != NULL; it = it->next)
+ if (it->data != self) client_iconify(it->data, iconic, curdesk);
}
void client_maximize(Client *self, gboolean max, int dir, gboolean savearea)
self->shaded = shade;
client_change_state(self);
/* resize the frame to just the titlebar */
- engine_frame_adjust_area(self->frame, FALSE, FALSE);
+ frame_adjust_area(self->frame, FALSE, FALSE);
}
void client_close(Client *self)
self->desktop = target;
PROP_SET32(self->window, net_wm_desktop, cardinal, target);
/* the frame can display the current desktop state */
- engine_frame_adjust_state(self->frame);
+ frame_adjust_state(self->frame);
/* 'move' the window to the new desktop */
if (!donthide)
client_showhide(self);
focus_order[old] = g_list_remove(focus_order[old], self);
if (target == DESKTOP_ALL) {
for (i = 0; i < screen_num_desktops; ++i) {
- if (focus_new)
+ if (config_focus_new)
focus_order[i] = g_list_prepend(focus_order[i], self);
else
focus_order[i] = g_list_append(focus_order[i], self);
}
} else {
- if (focus_new)
+ if (config_focus_new)
focus_order[target] = g_list_prepend(focus_order[target], self);
else
focus_order[target] = g_list_append(focus_order[target], self);
void client_unfocus(Client *self)
{
g_assert(focus_client == self);
+#ifdef DEBUG_FOCUS
g_message("client_unfocus");
+#endif
focus_fallback(Fallback_Unfocusing);
}