X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=9cbbaf6191260ec723b4061ef92ca241066e1aa0;hb=b41c3395313a97741f2f76b9133dc3b0b8eb5bbc;hp=d65ce4a193c0711cb8c4ce49f49b294ad9c4c24f;hpb=29c4cf4a15bc5fa97ba746b03a5e334f989c645e;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index d65ce4a1..9cbbaf61 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -933,7 +933,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, frame_rect_to_frame(self->frame, &desired); /* get where the frame would be */ - frame_client_gravity(self->frame, x, y, w, h); + frame_client_gravity(self->frame, x, y); /* get the requested size of the window with decorations */ fw = self->frame->size.left + w + self->frame->size.right; @@ -1021,7 +1021,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, } /* get where the client should be */ - frame_frame_gravity(self->frame, x, y, w, h); + frame_frame_gravity(self->frame, x, y); return ox != *x || oy != *y; } @@ -2613,11 +2613,18 @@ static void client_apply_startup_state(ObClient *self, 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); @@ -2702,7 +2709,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, frame_adjust_area(self->frame, FALSE, TRUE, TRUE); /* gets the frame's position */ - frame_client_gravity(self->frame, x, y, *w, *h); + frame_client_gravity(self->frame, x, y); /* these positions are frame positions, not client positions */ @@ -2749,7 +2756,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, } /* gets the client's position */ - frame_frame_gravity(self->frame, x, y, *w, *h); + frame_frame_gravity(self->frame, x, y); /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { @@ -3029,6 +3036,9 @@ void client_fullscreen(ObClient *self, gboolean fs) 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); @@ -3873,179 +3883,161 @@ ObClient *client_search_transient(ObClient *self, ObClient *search) 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_move_directional(ObClient *self, ObDirection dir, + gint *x, gint *y) { - gint dest, monitor_dest; - gint my_edge_start, my_edge_end, my_offset; + gint dest, edge, my_edge_start, my_edge_size, my_pos; GList *it; Rect *a, *mon; - if(!client_list) - return -1; + *x = self->frame->area.x; + *y = self->frame->area.y; - 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; + case OB_DIRECTION_SOUTH: + my_edge_start = RECT_LEFT(self->frame->area); + my_edge_size = self->frame->area.width; + my_pos = RECT_TOP(self->frame->area); + break; + case OB_DIRECTION_EAST: + case OB_DIRECTION_WEST: + my_edge_start = RECT_TOP(self->frame->area); + my_edge_size = self->frame->area.height; + my_pos = RECT_LEFT(self->frame->area); + break; + default: + g_assert_not_reached(); + } - HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) - } + switch(dir) { + case OB_DIRECTION_NORTH: + if (RECT_TOP(self->frame->area) > RECT_TOP(*mon)) + edge = RECT_TOP(*mon); + else + edge = RECT_TOP(*a); 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 (RECT_BOTTOM(self->frame->area) < RECT_BOTTOM(*mon)) + edge = RECT_BOTTOM(*mon) - self->frame->area.height; + else + edge = RECT_BOTTOM(*a) - self->frame->area.height; + break; + case OB_DIRECTION_EAST: + if (RECT_RIGHT(self->frame->area) < RECT_RIGHT(*mon)) + edge = RECT_RIGHT(*mon) - self->frame->area.width; + else + edge = RECT_RIGHT(*a) - self->frame->area.width; + break; + case OB_DIRECTION_WEST: + if (RECT_LEFT(self->frame->area) > RECT_LEFT(*mon)) + edge = RECT_LEFT(*mon); + else + edge = RECT_LEFT(*a); + break; + default: + g_assert_not_reached(); + } + /* default to the far edge, then narrow it down */ + dest = edge; - 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 && dest != my_pos; 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) + WANT_EDGE(cur, self); /* skip windows to not bump into */ - 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); + 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(); + } + /* do we collide with this window? */ + if (!RANGES_INTERSECT(my_edge_start, my_edge_size, + edge_start, edge_size)) + continue; - if(his_offset - 1 < my_offset) - continue; - - if(his_offset > dest) - continue; + switch(dir) { + case OB_DIRECTION_NORTH: + case OB_DIRECTION_SOUTH: + head = RECT_TOP(cur->frame->area) - self->frame->area.height; + tail = RECT_BOTTOM(cur->frame->area) + 1; + break; + case OB_DIRECTION_EAST: + case OB_DIRECTION_WEST: + head = RECT_LEFT(cur->frame->area) - self->frame->area.width; + tail = RECT_RIGHT(cur->frame->area) + 1; + break; + default: + g_assert_not_reached(); + } - HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) + switch(dir) { + case OB_DIRECTION_NORTH: + case OB_DIRECTION_WEST: + if (my_pos <= head) + skip_head = TRUE; + if (my_pos <= tail) + skip_tail = TRUE; + if (head < edge) + skip_head = TRUE; + if (tail < edge) + skip_tail = TRUE; + break; + case OB_DIRECTION_SOUTH: + case OB_DIRECTION_EAST: + if (my_pos >= head) + skip_head = TRUE; + if (my_pos >= tail) + skip_tail = TRUE; + if (head > edge) + skip_head = TRUE; + if (tail > edge) + skip_tail = TRUE; + 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; - - 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 ? 0 : cur->frame->area.width); - - if(his_offset + 1 > my_offset) - continue; - if(his_offset < dest) - continue; + if (!skip_head) + dest = head; + else if (!skip_tail) + dest = tail; + } - HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) - } - break; + switch(dir) { + case OB_DIRECTION_NORTH: + case OB_DIRECTION_SOUTH: + *y = dest; + break; + case OB_DIRECTION_WEST: 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) - } + *x = dest; 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; + + frame_frame_gravity(self->frame, x, y); } ObClient* client_under_pointer()