/* non-zero defaults */
self->wmstate = WithdrawnState; /* make sure it gets updated first time */
+ self->gravity = NorthWestGravity;
self->desktop = screen_num_desktops; /* always an invalid value */
self->user_time = focus_client ? focus_client->user_time : CurrentTime;
+ /* get all the stuff off the window */
client_get_all(self, TRUE);
- /* per-app settings override stuff, and return the settings for other
- uses too */
- settings = client_get_settings_state(self);
- /* the session should get the last say */
- client_restore_session_state(self);
-
- client_setup_decor_and_functions(self);
-
- {
- Time t = sn_app_started(self->startup_id, self->class);
- if (t) self->user_time = t;
- }
- /* update the focus lists, do this before the call to change_state or
- it can end up in the list twice! */
- focus_order_add_new(self);
-
- /* remove the client's border (and adjust re gravity) */
- client_toggle_border(self, FALSE);
-
/* specify that if we exit, the window should not be destroyed and
should be reparented back to root automatically */
XChangeSaveSet(ob_display, window, SetModeInsert);
frame_grab_client(self->frame);
+ /* we've grabbed everything and set everything that we need to at mapping
+ time now */
+ grab_server(FALSE);
+
+ /* per-app settings override stuff from client_get_all, and return the
+ settings for other uses too */
+ settings = client_get_settings_state(self);
+ /* the session should get the last say thought */
+ client_restore_session_state(self);
+
+ /* now we have all of the window's information so we can set this up */
+ client_setup_decor_and_functions(self);
+
+ /* remove the client's border (and adjust re gravity) */
+ client_toggle_border(self, FALSE);
+
+ {
+ Time t = sn_app_started(self->startup_id, self->class);
+ if (t) self->user_time = t;
+ }
+
/* do this after we have a frame.. it uses the frame to help determine the
WM_STATE to apply. */
client_change_state(self);
- grab_server(FALSE);
+ /* add ourselves to the focus order */
+ focus_order_add_new(self);
/* do this to add ourselves to the stacking list in a non-intrusive way */
client_calc_layer(self);
stacking_raise(CLIENT_AS_WINDOW(self));
}
+ /* adjust the frame to the client's size before showing the window */
+ frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+
/* this has to happen before we try focus the window, but we want it to
happen after the client's stacking has been determined or it looks bad
*/
/* restore the window's original geometry so it is not lost */
{
- Rect a = self->area;
+ Rect a;
+
+ /* give the client its border back */
+ client_toggle_border(self, TRUE);
+
+ a = self->area;
if (self->fullscreen)
a = self->pre_fullscreen_area;
}
}
- /* give the client its border back */
- client_toggle_border(self, TRUE);
-
self->fullscreen = self->max_horz = self->max_vert = FALSE;
self->decorations = 0; /* unmanaged windows have no decor */
if (!real)
return;
+ /* get this early so we have it for debugging */
+ client_update_title(self);
+
client_update_protocols(self);
client_update_wmhints(self);
#endif
client_get_colormap(self);
- client_update_title(self);
client_update_strut(self);
client_update_icons(self);
client_update_user_time_window(self);
GSList *it, *next;
ObClient *c;
+ /* * *
+ Group transient windows are not allowed to have other group
+ transient windows as their children.
+ * * */
+
+
/* No change has occured */
if (oldgroup == newgroup && oldparent == newparent) return;
/** Remove the client from the transient tree wherever it has changed **/
/* If the window is becoming a direct transient for a window in its group
- then that window can't be a child of this window anymore */
+ then any group transients which were our children and are now becoming
+ our parents need to stop being our children.
+
+ Group transients can't be children of group transients already, but
+ we could have any number of direct parents above up, any of which could
+ be transient for the group, and we need to remove it from our children.
+ */
if (oldparent != newparent &&
newparent != NULL && newparent != OB_TRAN_GROUP &&
- newparent->transient_for == OB_TRAN_GROUP &&
newgroup != NULL && newgroup == oldgroup)
{
- self->transients = g_slist_remove(self->transients, newparent);
+ ObClient *look = newparent;
+ do {
+ self->transients = g_slist_remove(self->transients, look);
+ look = look->transient_for;
+ } while (look != NULL && look != OB_TRAN_GROUP);
}
WARNING: Cyclical transient-ness is possible. For e.g. if:
A is transient for the group
- B is a member of the group and transient for A
+ B is transient for A
+ C is transient for B
+ A can't be transient for C or we have a cycle
*/
if (oldgroup != newgroup && newgroup != NULL &&
newparent != OB_TRAN_GROUP)
if (!(self->functions & OB_CLIENT_FUNC_ICONIFY))
self->decorations &= ~OB_FRAME_DECOR_ICONIFY;
if (!(self->functions & OB_CLIENT_FUNC_RESIZE))
- self->decorations &= ~OB_FRAME_DECOR_GRIPS;
+ self->decorations &= ~(OB_FRAME_DECOR_GRIPS | OB_FRAME_DECOR_HANDLE);
/* can't maximize without moving/resizing */
if (!((self->functions & OB_CLIENT_FUNC_MAXIMIZE) &&
void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
- gboolean user, gboolean final,
- gboolean force_reply)
+ gboolean user, gboolean final)
{
- gint oldw, oldh, oldrx, oldry;
+ gint oldw, oldh;
gboolean send_resize_client;
- gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
+ gboolean moved = FALSE, resized = FALSE;
guint fdecor = self->frame->decorations;
gboolean fhorz = self->frame->max_horz;
gint logicalw, logicalh;
if (moved || resized)
frame_adjust_area(self->frame, moved, resized, FALSE);
- /* find the client's position relative to the root window */
- oldrx = self->root_pos.x;
- oldry = self->root_pos.y;
- rootmoved = (oldrx != (signed)(self->frame->area.x +
- self->frame->size.left -
- self->border_width) ||
- oldry != (signed)(self->frame->area.y +
- self->frame->size.top -
- self->border_width));
-
- if (force_reply || ((!user || (user && final)) && rootmoved))
+ if ((!user || (user && final)) && !resized)
{
XEvent event;
event.xconfigure.event = self->window;
event.xconfigure.window = self->window;
+ ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d\n",
+ self->title, self->root_pos.x, self->root_pos.y, w, h);
+
/* root window real coords */
event.xconfigure.x = self->root_pos.x;
event.xconfigure.y = self->root_pos.y;
static ObClientIcon* client_icon_recursive(ObClient *self, gint w, gint h)
{
guint i;
- /* si is the smallest image >= req */
- /* li is the largest image < req */
- gulong size, smallest = 0xffffffff, largest = 0, si = 0, li = 0;
+ gulong min_diff, min_i;
if (!self->nicons) {
ObClientIcon *parent = NULL;
return parent;
}
- for (i = 0; i < self->nicons; ++i) {
- size = self->icons[i].width * self->icons[i].height;
- if (size < smallest && size >= (unsigned)(w * h)) {
- smallest = size;
- si = i;
- }
- if (size > largest && size <= (unsigned)(w * h)) {
- largest = size;
- li = i;
+ /* some kind of crappy approximation to find the icon closest in size to
+ what we requested, but icons are generally all the same ratio as
+ eachother so it's good enough. */
+
+ min_diff = ABS(self->icons[0].width - w) + ABS(self->icons[0].height - h);
+ min_i = 0;
+
+ for (i = 1; i < self->nicons; ++i) {
+ gulong diff;
+
+ diff = ABS(self->icons[0].width - w) + ABS(self->icons[0].height - h);
+ if (diff < min_diff) {
+ min_diff = diff;
+ min_i = i;
}
}
- if (largest == 0) /* didnt find one smaller than the requested size */
- return &self->icons[si];
- return &self->icons[li];
+ return &self->icons[min_i];
}
const ObClientIcon* client_icon(ObClient *self, gint w, gint h)
continue; \
if(cur->iconic) \
continue; \
- if(cur->layer < c->layer && !config_resist_layers_below) \
+ if(cur->layer == c->layer) \
continue;
#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \