/* 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))
{
activate = TRUE;
}
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_monitor(self->desktop, client_monitor(self),
+ &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);
}
/* 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
*/
- client_show(self);
+ {
+ gulong ignore_start;
+ if (!config_focus_under_mouse)
+ ignore_start = event_start_ignore_all_enters();
+
+ client_show(self);
+
+ if (!config_focus_under_mouse)
+ event_end_ignore_all_enters(ignore_start);
+ }
if (activate) {
gboolean stacked = client_restore_session_stacking(self);
XSelectInput(ob_display, self->window, NoEventMask);
/* ignore enter events from the unmap so it doesnt mess with the focus */
- if (!client_focused(self) || !config_focus_under_mouse)
+ if (!config_focus_under_mouse)
ignore_start = event_start_ignore_all_enters();
frame_hide(self->frame);
/* flush to send the hide to the server quickly */
XFlush(ob_display);
- if (!client_focused(self) || !config_focus_under_mouse)
+ if (!config_focus_under_mouse)
event_end_ignore_all_enters(ignore_start);
mouse_grab_for_client(self, FALSE);
Rect desired;
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);
+
+ all_a = screen_area(self->desktop, &desired);
+ mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired),
+ &desired);
/* get where the frame would be */
frame_client_gravity(self->frame, x, y, w, h);
/* get where the client should be */
frame_frame_gravity(self->frame, x, y, w, h);
+ g_free(all_a);
+ g_free(mon_a);
+
return ox != *x || oy != *y;
}
if (size.flags & PResizeInc && size.width_inc && size.height_inc)
SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
+
+ ob_debug("Normal hints: min size (%d %d) max size (%d %d)\n "
+ "size inc (%d %d) base size (%d %d)\n",
+ self->min_size.width, self->min_size.height,
+ self->max_size.width, self->max_size.height,
+ self->size_inc.width, self->size_inc.height,
+ self->base_size.width, self->base_size.height);
}
+ else
+ ob_debug("Normal hints: not set\n");
}
void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
/* 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) {
- if (config_theme_keepborder)
- self->decorations &= OB_FRAME_DECOR_BORDER;
- else
- self->decorations = 0;
- }
+ if (self->undecorated)
+ self->decorations = 0;
/* if we don't have a titlebar, then we cannot shade! */
if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
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);
}
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;
}
event_cancel_all_key_grabs();
}
+ /* We don't need to ignore enter events here.
+ The window can hide/iconify in 3 different ways:
+ 1 - through an x message. in this case we ignore all enter events
+ caused by responding to the x message (unless underMouse)
+ 2 - by a keyboard action. in this case we ignore all enter events
+ caused by the action
+ 3 - by a mouse action. in this case they are doing stuff with the
+ mouse and focus _should_ move.
+
+ Also in action_end, we simulate an enter event that can't be ignored
+ so trying to ignore them is futile in case 3 anyways
+ */
+
frame_hide(self->frame);
hide = TRUE;
*/
client_try_configure(self, &x, &y, &w, &h, &l, &l, FALSE);
ob_debug("placed window 0x%x at %d, %d with size %d x %d\n",
- self->window, self->area.x, self->area.y,
- self->area.width, self->area.height);
- oldarea = self->area; /* save the area */
- RECT_SET(self->area, x, y, w, h); /* put where it should be for the premax stuff */
+ self->window, x, y, w, h);
+ /* save the area, and make it where it should be for the premax stuff */
+ oldarea = self->area;
+ RECT_SET(self->area, x, y, w, h);
/* apply the states. these are in a carefully crafted order.. */
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
the updated frame dimensions. */
frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
+ /* gets the frame's position */
+ frame_client_gravity(self->frame, x, y, *w, *h);
+
+ /* these positions are frame positions, not client positions */
+
+ /* set the size and position if fullscreen */
+ if (self->fullscreen) {
+ Rect *a;
+ guint i;
+
+ i = screen_find_monitor(&desired);
+ a = screen_physical_area_monitor(i);
+
+ *x = a->x;
+ *y = a->y;
+ *w = a->width;
+ *h = a->height;
+
+ 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);
+ a = screen_area_monitor(self->desktop, i, &desired);
+
+ /* set the size and position if maximized */
+ if (self->max_horz) {
+ *x = a->x;
+ *w = a->width - self->frame->size.left - self->frame->size.right;
+ }
+ if (self->max_vert) {
+ *y = a->y;
+ *h = a->height - self->frame->size.top - self->frame->size.bottom;
+ }
+
+ user = FALSE; /* ignore if the client can't be moved/resized when it
+ is maximizing */
+
+ g_free(a);
+ }
+
+ /* gets the client's position */
+ frame_frame_gravity(self->frame, x, y, *w, *h);
+
/* 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;
+ 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;
+ minratio = self->fullscreen || (self->max_horz && self->max_vert) ?
+ 0 : self->min_ratio;
+ maxratio = self->fullscreen || (self->max_horz && self->max_vert) ?
+ 0 : self->max_ratio;
/* base size is substituted with min size if not specified */
if (self->base_size.width || self->base_size.height) {
*h -= baseh;
/* keep to the increments */
- *w /= self->size_inc.width;
- *h /= self->size_inc.height;
+ *w /= incw;
+ *h /= inch;
/* you cannot resize to nothing */
if (basew + *w < 1) *w = 1 - basew;
if (baseh + *h < 1) *h = 1 - baseh;
/* save the logical size */
- *logicalw = self->size_inc.width > 1 ? *w : *w + basew;
- *logicalh = self->size_inc.height > 1 ? *h : *h + baseh;
+ *logicalw = incw > 1 ? *w : *w + basew;
+ *logicalh = inch > 1 ? *h : *h + baseh;
- *w *= self->size_inc.width;
- *h *= self->size_inc.height;
+ *w *= incw;
+ *h *= inch;
*w += basew;
*h += baseh;
*w -= self->base_size.width;
*h -= self->base_size.height;
- if (!self->fullscreen) {
- if (self->min_ratio)
- if (*h * self->min_ratio > *w) {
- *h = (gint)(*w / self->min_ratio);
+ if (minratio)
+ if (*h * minratio > *w) {
+ *h = (gint)(*w / minratio);
- /* you cannot resize to nothing */
- if (*h < 1) {
- *h = 1;
- *w = (gint)(*h * self->min_ratio);
- }
+ /* you cannot resize to nothing */
+ if (*h < 1) {
+ *h = 1;
+ *w = (gint)(*h * minratio);
}
- if (self->max_ratio)
- if (*h * self->max_ratio < *w) {
- *h = (gint)(*w / self->max_ratio);
-
- /* you cannot resize to nothing */
- if (*h < 1) {
- *h = 1;
- *w = (gint)(*h * self->min_ratio);
- }
+ }
+ if (maxratio)
+ if (*h * maxratio < *w) {
+ *h = (gint)(*w / maxratio);
+
+ /* you cannot resize to nothing */
+ if (*h < 1) {
+ *h = 1;
+ *w = (gint)(*h * minratio);
}
- }
+ }
*w += self->base_size.width;
*h += self->base_size.height;
}
- /* gets the frame's position */
- frame_client_gravity(self->frame, x, y, *w, *h);
-
- /* these positions are frame positions, not client positions */
-
- /* set the size and position if fullscreen */
- if (self->fullscreen) {
- Rect *a;
- guint i;
-
- i = screen_find_monitor(&desired_area);
- a = screen_physical_area_monitor(i);
-
- *x = a->x;
- *y = a->y;
- *w = a->width;
- *h = a->height;
-
- user = FALSE; /* ignore if the client can't be moved/resized when it
- is fullscreening */
- } 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);
-
- /* set the size and position if maximized */
- if (self->max_horz) {
- *x = a->x;
- *w = a->width - self->frame->size.left - self->frame->size.right;
- }
- if (self->max_vert) {
- *y = a->y;
- *h = a->height - self->frame->size.top - self->frame->size.bottom;
- }
-
- user = FALSE; /* ignore if the client can't be moved/resized when it
- is maximizing */
- }
-
- /* gets the client's position */
- frame_frame_gravity(self->frame, x, y, *w, *h);
-
/* these override the above states! if you cant move you can't move! */
if (user) {
if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
/* raise if it was not already on the desktop */
if (old != DESKTOP_ALL)
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();
}
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
gboolean allow = FALSE;
- /* if the request came from the user, or if nothing is focused, then grant
- the request.
- if the currently focused app doesn't set a user_time, then it can't
+ /* if the currently focused app doesn't set a user_time, then it can't
benefit from any focus stealing prevention.
+
+ if the timestamp is missing in the request then let it go through
+ even if it is source=app, because EVERY APPLICATION DOES THIS because
+ GTK IS VERY BUGGY AND HARDCODES source=application... WHY!?
*/
- if (user || !focus_client || !last_time)
+ if (!last_time || !event_curtime)
allow = TRUE;
/* otherwise, if they didn't give a time stamp or if it is too old, they
don't get focus */
else
- allow = event_curtime && event_time_after(event_curtime, last_time);
+ allow = event_time_after(event_curtime, last_time);
ob_debug_type(OB_DEBUG_FOCUS,
"Want to activate window 0x%x with time %u (last time %u), "
if(!client_list)
return -1;
- a = screen_area(c->desktop);
- monitor = screen_area_monitor(c->desktop, client_monitor(c));
+ a = screen_area(c->desktop, &c->frame->area);
+ monitor = screen_area_monitor(c->desktop, client_monitor(c),
+ &c->frame->area);
switch(dir) {
case OB_DIRECTION_NORTH:
g_assert_not_reached();
dest = 0; /* suppress warning */
}
+
+ g_free(a);
+ g_free(monitor);
return dest;
}
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
if (c->frame->visible &&
+ /* check the desktop, this is done during desktop
+ switching and windows are shown/hidden status is not
+ reliable */
+ (c->desktop == screen_desktop ||
+ c->desktop == DESKTOP_ALL) &&
/* ignore all animating windows */
!frame_iconify_animating(c->frame) &&
RECT_CONTAINS(c->frame->area, x, y))