/* get all the stuff off the window */
client_get_all(self, TRUE);
+ ob_debug("Window type: %d\n", self->type);
+ ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
+
/* specify that if we exit, the window should not be destroyed and
should be reparented back to root automatically */
XChangeSaveSet(ob_display, window, SetModeInsert);
client_search_focus_tree_full(self)) &&
/* this checks for focus=false for the window */
(!settings || settings->focus != 0) &&
- focus_valid_target(self, FALSE, TRUE, FALSE, FALSE))
+ focus_valid_target(self, FALSE, FALSE, TRUE, FALSE, FALSE))
{
activate = TRUE;
}
else if (max_horz)
client_maximize(self, TRUE, 1);
- /* if the window hasn't been configured yet, then do so now */
- if (!fullscreen && !max_vert && !max_horz) {
- self->area = oldarea;
- client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
- }
+ /* if the window hasn't been configured yet, then do so now, in fact the
+ x,y,w,h may _not_ be the same as the area rect, which can end up
+ meaning that the client isn't properly moved/resized by the fullscreen
+ function
+ pho can cause this because it maps at size of the screen but not 0,0
+ so openbox moves it on screen to 0,0 (thus x,y=0,0 and area.x,y don't).
+ then fullscreen'ing makes it go to 0,0 which it thinks it already is at
+ cuz thats where the pre-fullscreen will be. however the actual area is
+ not, so this needs to be called even if we have fullscreened/maxed
+ */
+ self->area = oldarea;
+ client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
/* set the desktop hint, to make sure that it always exists */
PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
}
+ ob_debug("Window %s going fullscreen (%d)\n",
+ self->title, self->fullscreen);
+
client_setup_decor_and_functions(self, FALSE);
client_move_resize(self, x, y, w, h);
return NULL;
}
-#define WANT_EDGE(cur, c) \
- if (cur == c) \
- continue; \
- if (c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL && \
- cur->desktop != screen_desktop) \
- continue; \
- if (cur->iconic) \
- continue;
-
-#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
- if ((his_edge_start >= my_edge_start && \
- his_edge_start <= my_edge_end) || \
- (my_edge_start >= his_edge_start && \
- my_edge_start <= his_edge_end)) \
- dest = his_offset;
-
-/* finds the nearest edge in the given direction from the current client
- * note to self: the edge is the -frame- edge (the actual one), not the
- * client edge.
- */
-gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
+void client_find_edge_directional(ObClient *self, ObDirection dir,
+ gint my_head, gint my_size,
+ gint my_edge_start, gint my_edge_size,
+ gint *dest, gboolean *near_edge)
{
- gint dest, monitor_dest;
- gint my_edge_start, my_edge_end, my_offset;
GList *it;
Rect *a, *mon;
-
- if(!client_list)
- return -1;
+ gint edge;
- a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
- mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area);
+ a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS,
+ &self->frame->area);
+ mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR,
+ &self->frame->area);
switch(dir) {
case OB_DIRECTION_NORTH:
- my_edge_start = c->frame->area.x;
- my_edge_end = c->frame->area.x + c->frame->area.width;
- my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
-
- /* default: top of screen */
- dest = a->y + (hang ? c->frame->area.height : 0);
- monitor_dest = mon->y + (hang ? c->frame->area.height : 0);
- /* if the monitor edge comes before the screen edge, */
- /* use that as the destination instead. (For xinerama) */
- if (monitor_dest != dest && my_offset > monitor_dest)
- dest = monitor_dest;
-
- for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
- gint his_edge_start, his_edge_end, his_offset;
- ObClient *cur = it->data;
-
- WANT_EDGE(cur, c)
-
- his_edge_start = cur->frame->area.x;
- his_edge_end = cur->frame->area.x + cur->frame->area.width;
- his_offset = cur->frame->area.y +
- (hang ? 0 : cur->frame->area.height);
-
- if(his_offset + 1 > my_offset)
- continue;
-
- if(his_offset < dest)
- continue;
-
- HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
- }
+ if (my_head >= RECT_TOP(*mon))
+ edge = RECT_TOP(*mon) - 1;
+ else
+ edge = RECT_TOP(*a) - 1;
break;
case OB_DIRECTION_SOUTH:
- my_edge_start = c->frame->area.x;
- my_edge_end = c->frame->area.x + c->frame->area.width;
- my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
-
- /* default: bottom of screen */
- dest = a->y + a->height - (hang ? c->frame->area.height : 0);
- monitor_dest = mon->y + mon->height -
- (hang ? c->frame->area.height : 0);
- /* if the monitor edge comes before the screen edge, */
- /* use that as the destination instead. (For xinerama) */
- if (monitor_dest != dest && my_offset < monitor_dest)
- dest = monitor_dest;
+ if (my_head <= RECT_BOTTOM(*mon))
+ edge = RECT_BOTTOM(*mon) + 1;
+ else
+ edge = RECT_BOTTOM(*a) + 1;
+ break;
+ case OB_DIRECTION_EAST:
+ if (my_head <= RECT_RIGHT(*mon))
+ edge = RECT_RIGHT(*mon) + 1;
+ else
+ edge = RECT_RIGHT(*a) + 1;
+ break;
+ case OB_DIRECTION_WEST:
+ if (my_head >= RECT_LEFT(*mon))
+ edge = RECT_LEFT(*mon) - 1;
+ else
+ edge = RECT_LEFT(*a) - 1;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ /* default to the far edge, then narrow it down */
+ *dest = edge;
+ *near_edge = TRUE;
- for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
- gint his_edge_start, his_edge_end, his_offset;
- ObClient *cur = it->data;
+ for(it = client_list; it; it = g_list_next(it)) {
+ ObClient *cur = it->data;
+ gint edge_start, edge_size, head, tail;
+ gboolean skip_head = FALSE, skip_tail = FALSE;
- WANT_EDGE(cur, c)
+ /* skip windows to not bump into */
+ if (cur == self)
+ continue;
+ if (cur->iconic)
+ continue;
+ if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&
+ cur->desktop != screen_desktop)
+ continue;
- his_edge_start = cur->frame->area.x;
- his_edge_end = cur->frame->area.x + cur->frame->area.width;
- his_offset = cur->frame->area.y +
- (hang ? cur->frame->area.height : 0);
+ ob_debug("trying window %s\n", cur->title);
+ switch(dir) {
+ case OB_DIRECTION_NORTH:
+ case OB_DIRECTION_SOUTH:
+ edge_start = cur->frame->area.x;
+ edge_size = cur->frame->area.width;
+ break;
+ case OB_DIRECTION_EAST:
+ case OB_DIRECTION_WEST:
+ edge_start = cur->frame->area.y;
+ edge_size = cur->frame->area.height;
+ break;
+ default:
+ g_assert_not_reached();
+ }
- if(his_offset - 1 < my_offset)
- continue;
-
- if(his_offset > dest)
- continue;
+ /* do we collide with this window? */
+ if (!RANGES_INTERSECT(my_edge_start, my_edge_size,
+ edge_start, edge_size))
+ continue;
- HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
+ switch(dir) {
+ case OB_DIRECTION_NORTH:
+ head = RECT_BOTTOM(cur->frame->area);
+ tail = RECT_TOP(cur->frame->area);
+ break;
+ case OB_DIRECTION_SOUTH:
+ head = RECT_TOP(cur->frame->area);
+ tail = RECT_BOTTOM(cur->frame->area);
+ break;
+ case OB_DIRECTION_EAST:
+ head = RECT_LEFT(cur->frame->area);
+ tail = RECT_RIGHT(cur->frame->area);
+ break;
+ case OB_DIRECTION_WEST:
+ head = RECT_RIGHT(cur->frame->area);
+ tail = RECT_LEFT(cur->frame->area);
+ break;
+ default:
+ g_assert_not_reached();
}
- break;
- case OB_DIRECTION_WEST:
- my_edge_start = c->frame->area.y;
- my_edge_end = c->frame->area.y + c->frame->area.height;
- my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
- /* default: leftmost egde of screen */
- dest = a->x + (hang ? c->frame->area.width : 0);
- monitor_dest = mon->x + (hang ? c->frame->area.width : 0);
- /* if the monitor edge comes before the screen edge, */
- /* use that as the destination instead. (For xinerama) */
- if (monitor_dest != dest && my_offset > monitor_dest)
- dest = monitor_dest;
+ switch(dir) {
+ case OB_DIRECTION_NORTH:
+ case OB_DIRECTION_WEST:
+ if (my_head <= head + 1)
+ skip_head = TRUE;
+ if (my_head + my_size - 1 <= tail + 1)
+ skip_tail = TRUE;
+ if (head < *dest)
+ skip_head = TRUE;
+ if (tail - my_size < *dest)
+ skip_tail = TRUE;
+ break;
+ case OB_DIRECTION_SOUTH:
+ case OB_DIRECTION_EAST:
+ if (my_head >= head - 1)
+ skip_head = TRUE;
+ if (my_head - my_size + 1 >= tail - 1)
+ skip_tail = TRUE;
+ if (head > *dest)
+ skip_head = TRUE;
+ if (tail + my_size > *dest)
+ skip_tail = TRUE;
+ break;
+ default:
+ g_assert_not_reached();
+ }
- for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
- gint his_edge_start, his_edge_end, his_offset;
- ObClient *cur = it->data;
+ ob_debug("my head %d size %d\n", my_head, my_size);
+ ob_debug("head %d tail %d deest %d\n", head, tail, *dest);
+ if (!skip_head) {
+ ob_debug("using near edge %d\n", head);
+ *dest = head;
+ *near_edge = TRUE;
+ }
+ else if (!skip_tail) {
+ ob_debug("using far edge %d\n", tail);
+ *dest = tail;
+ *near_edge = FALSE;
+ }
+ }
+}
- WANT_EDGE(cur, c)
+void client_find_move_directional(ObClient *self, ObDirection dir,
+ gint *x, gint *y)
+{
+ gint head, size;
+ gint e, e_start, e_size;
+ gboolean near;
- his_edge_start = cur->frame->area.y;
- his_edge_end = cur->frame->area.y + cur->frame->area.height;
- his_offset = cur->frame->area.x +
- (hang ? 0 : cur->frame->area.width);
+ switch (dir) {
+ case OB_DIRECTION_EAST:
+ head = RECT_RIGHT(self->frame->area);
+ size = self->frame->area.width;
+ e_start = RECT_TOP(self->frame->area);
+ e_size = self->frame->area.height;
+ break;
+ case OB_DIRECTION_WEST:
+ head = RECT_LEFT(self->frame->area);
+ size = self->frame->area.width;
+ e_start = RECT_TOP(self->frame->area);
+ e_size = self->frame->area.height;
+ break;
+ case OB_DIRECTION_NORTH:
+ head = RECT_TOP(self->frame->area);
+ size = self->frame->area.height;
+ e_start = RECT_LEFT(self->frame->area);
+ e_size = self->frame->area.width;
+ break;
+ case OB_DIRECTION_SOUTH:
+ head = RECT_BOTTOM(self->frame->area);
+ size = self->frame->area.height;
+ e_start = RECT_LEFT(self->frame->area);
+ e_size = self->frame->area.width;
+ break;
+ default:
+ g_assert_not_reached();
+ }
- if(his_offset + 1 > my_offset)
- continue;
+ client_find_edge_directional(self, dir, head, size,
+ e_start, e_size, &e, &near);
+ *x = self->frame->area.x;
+ *y = self->frame->area.y;
+ switch (dir) {
+ case OB_DIRECTION_EAST:
+ if (near) e -= self->frame->area.width;
+ else e++;
+ *x = e;
+ break;
+ case OB_DIRECTION_WEST:
+ if (near) e++;
+ else e -= self->frame->area.width;
+ *x = e;
+ break;
+ case OB_DIRECTION_NORTH:
+ if (near) e++;
+ else e -= self->frame->area.height;
+ *y = e;
+ break;
+ case OB_DIRECTION_SOUTH:
+ if (near) e -= self->frame->area.height;
+ else e++;
+ *y = e;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ frame_frame_gravity(self->frame, x, y);
+}
- if(his_offset < dest)
- continue;
+void client_find_resize_directional(ObClient *self, ObDirection side,
+ gboolean grow,
+ gint *x, gint *y, gint *w, gint *h)
+{
+ gint head, size;
+ gint e, e_start, e_size, delta;
+ gboolean near;
+ ObDirection dir;
- HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
- }
- break;
+ switch (side) {
case OB_DIRECTION_EAST:
- my_edge_start = c->frame->area.y;
- my_edge_end = c->frame->area.y + c->frame->area.height;
- my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
-
- /* default: rightmost edge of screen */
- dest = a->x + a->width - (hang ? c->frame->area.width : 0);
- monitor_dest = mon->x + mon->width -
- (hang ? c->frame->area.width : 0);
- /* if the monitor edge comes before the screen edge, */
- /* use that as the destination instead. (For xinerama) */
- if (monitor_dest != dest && my_offset < monitor_dest)
- dest = monitor_dest;
-
- for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
- gint his_edge_start, his_edge_end, his_offset;
- ObClient *cur = it->data;
-
- WANT_EDGE(cur, c)
-
- his_edge_start = cur->frame->area.y;
- his_edge_end = cur->frame->area.y + cur->frame->area.height;
- his_offset = cur->frame->area.x +
- (hang ? cur->frame->area.width : 0);
-
- if(his_offset - 1 < my_offset)
- continue;
-
- if(his_offset > dest)
- continue;
-
- HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
- }
+ head = RECT_RIGHT(self->frame->area) + (self->size_inc.width - 1);
+ size = self->frame->area.width;
+ e_start = RECT_TOP(self->frame->area);
+ e_size = self->frame->area.height;
+ dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
+ break;
+ case OB_DIRECTION_WEST:
+ head = RECT_LEFT(self->frame->area) - (self->size_inc.width - 1);
+ size = self->frame->area.width;
+ e_start = RECT_TOP(self->frame->area);
+ e_size = self->frame->area.height;
+ dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
+ break;
+ case OB_DIRECTION_NORTH:
+ head = RECT_TOP(self->frame->area) - (self->size_inc.height - 1);
+ size = self->frame->area.height;
+ e_start = RECT_LEFT(self->frame->area);
+ e_size = self->frame->area.width;
+ dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
+ break;
+ case OB_DIRECTION_SOUTH:
+ head = RECT_BOTTOM(self->frame->area) + (self->size_inc.height - 1);
+ size = self->frame->area.height;
+ e_start = RECT_LEFT(self->frame->area);
+ e_size = self->frame->area.width;
+ dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
break;
- case OB_DIRECTION_NORTHEAST:
- case OB_DIRECTION_SOUTHEAST:
- case OB_DIRECTION_NORTHWEST:
- case OB_DIRECTION_SOUTHWEST:
- /* not implemented */
default:
g_assert_not_reached();
- dest = 0; /* suppress warning */
}
- g_free(a);
- g_free(mon);
- return dest;
+ client_find_edge_directional(self, dir, head, size,
+ e_start, e_size, &e, &near);
+ *x = self->frame->area.x;
+ *y = self->frame->area.y;
+ *w = self->frame->area.width;
+ *h = self->frame->area.height;
+ switch (side) {
+ case OB_DIRECTION_EAST:
+ if (near) --e;
+ delta = e - RECT_RIGHT(self->frame->area);
+ *w += delta;
+ break;
+ case OB_DIRECTION_WEST:
+ if (near) ++e;
+ delta = RECT_LEFT(self->frame->area) - e;
+ *x -= delta;
+ *w += delta;
+ break;
+ case OB_DIRECTION_NORTH:
+ if (near) ++e;
+ delta = RECT_TOP(self->frame->area) - e;
+ *y -= delta;
+ *h += delta;
+ break;
+ case OB_DIRECTION_SOUTH:
+ if (near) --e;
+ delta = e - RECT_BOTTOM(self->frame->area);
+ *h += delta;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ frame_frame_gravity(self->frame, x, y);
+ *w -= self->frame->size.left + self->frame->size.right;
+ *h -= self->frame->size.top + self->frame->size.bottom;
}
ObClient* client_under_pointer()