From 01a35904fec67a7f92a0eb7f19457e79ca3d0988 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 28 Jun 2007 05:18:01 +0000 Subject: [PATCH] rewrote the movetoedge code so it works with both types of edges (to edge and from edge) --- openbox/actions/growtoedge.c | 8 +- openbox/actions/movetofromedge.c | 61 +------ openbox/client.c | 272 +++++++++++++++---------------- openbox/client.h | 8 +- openbox/moveresize.c | 49 ++++-- 5 files changed, 180 insertions(+), 218 deletions(-) diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index 5d4647f7..a5b24e37 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -74,11 +74,13 @@ static gboolean run_func(ObActionsData *data, gpointer options) width = c->area.width + c->frame->size.left + c->frame->size.right; height = c->area.height + c->frame->size.top + c->frame->size.bottom; +#if 0 + dest = client_directional_edge_search(c, o->dir); + switch(o->dir) { case OB_DIRECTION_NORTH: if (c->shaded) break; /* don't allow vertical resize if shaded */ - dest = client_directional_edge_search(c, o->dir, FALSE); if (a->y == y) height = height / 2; else { @@ -87,7 +89,6 @@ static gboolean run_func(ObActionsData *data, gpointer options) } break; case OB_DIRECTION_WEST: - dest = client_directional_edge_search(c, o->dir, FALSE); if (a->x == x) width = width / 2; else { @@ -98,7 +99,6 @@ static gboolean run_func(ObActionsData *data, gpointer options) case OB_DIRECTION_SOUTH: if (c->shaded) break; /* don't allow vertical resize if shaded */ - dest = client_directional_edge_search(c, o->dir, FALSE); if (a->y + a->height == y + c->frame->area.height) { height = c->frame->area.height / 2; y = a->y + a->height - height; @@ -108,7 +108,6 @@ static gboolean run_func(ObActionsData *data, gpointer options) height -= (height - c->frame->area.height) % c->size_inc.height; break; case OB_DIRECTION_EAST: - dest = client_directional_edge_search(c, o->dir, FALSE); if (a->x + a->width == x + c->frame->area.width) { width = c->frame->area.width / 2; x = a->x + a->width - width; @@ -129,6 +128,7 @@ static gboolean run_func(ObActionsData *data, gpointer options) client_move_resize(c, x, y, width, height); actions_client_move(data, TRUE); +#endif g_free(a); } diff --git a/openbox/actions/movetofromedge.c b/openbox/actions/movetofromedge.c index 72a89c1c..8db45097 100644 --- a/openbox/actions/movetofromedge.c +++ b/openbox/actions/movetofromedge.c @@ -6,24 +6,16 @@ typedef struct { ObDirection dir; - gboolean hang; } Options; static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); -static gpointer setup_to_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); -static gpointer setup_from_func(ObParseInst *i,xmlDocPtr doc, xmlNodePtr node); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); void action_movetofromedge_startup() { actions_register("MoveToEdge", - setup_to_func, - free_func, - run_func, - NULL, NULL); - actions_register("MoveFromEdge", - setup_from_func, + setup_func, free_func, run_func, NULL, NULL); @@ -57,20 +49,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) return o; } -static gpointer setup_to_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) -{ - Options *o = setup_func(i, doc, node); - o->hang = FALSE; - return o; -} - -static gpointer setup_from_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) -{ - Options *o = setup_func(i, doc, node); - o->hang = TRUE; - return o; -} - static void free_func(gpointer options) { Options *o = options; @@ -85,40 +63,13 @@ static gboolean run_func(ObActionsData *data, gpointer options) if (data->client) { gint x, y; - ObClient *c = data->client; - x = c->frame->area.x; - y = c->frame->area.y; - - switch(o->dir) { - case OB_DIRECTION_NORTH: - y = client_directional_edge_search(c, OB_DIRECTION_NORTH, - o->hang) - - (o->hang ? c->frame->area.height : 0); - break; - case OB_DIRECTION_WEST: - x = client_directional_edge_search(c, OB_DIRECTION_WEST, - o->hang) - - (o->hang ? c->frame->area.width : 0); - break; - case OB_DIRECTION_SOUTH: - y = client_directional_edge_search(c, OB_DIRECTION_SOUTH, - o->hang) - - (o->hang ? 0 : c->frame->area.height); - break; - case OB_DIRECTION_EAST: - x = client_directional_edge_search(c, OB_DIRECTION_EAST, - o->hang) - - (o->hang ? 0 : c->frame->area.width); - break; - default: - g_assert_not_reached(); + client_find_move_directional(data->client, o->dir, &x, &y); + if (x != data->client->area.x || y != data->client->area.y) { + actions_client_move(data, FALSE); + client_move(data->client, x, y); + actions_client_move(data, TRUE); } - frame_frame_gravity(c->frame, &x, &y); - - actions_client_move(data, FALSE); - client_move(c, x, y); - actions_client_move(data, TRUE); } return FALSE; diff --git a/openbox/client.c b/openbox/client.c index e58cc753..9cbbaf61 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -3883,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() diff --git a/openbox/client.h b/openbox/client.h index bb783458..fcfb28b8 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -455,6 +455,11 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, */ void client_move_onscreen(ObClient *self, gboolean rude); +/*! dir is either North, South, East or West. It can't be, for example, + Northwest */ +void client_find_move_directional(ObClient *self, ObDirection dir, + gint *x, gint *y); + /*! Fullscreen's or unfullscreen's the client window @param fs true if the window should be made fullscreen; false if it should be returned to normal state. @@ -684,9 +689,6 @@ ObClient *client_search_parent(ObClient *self, ObClient *search); NULL is returned if the given search is not a transient of the client. */ ObClient *client_search_transient(ObClient *self, ObClient *search); -/*! Return the closest edge in the given direction */ -gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang); - /*! Set a client window to be above/below other clients. @layer < 0 indicates the client should be placed below other clients.
= 0 indicates the client should be placed with other clients.
diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 05c5f596..19bed579 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -26,6 +26,7 @@ #include "openbox.h" #include "resist.h" #include "mainloop.h" +#include "modkeys.h" #include "popup.h" #include "moveresize.h" #include "config.h" @@ -39,7 +40,7 @@ #include /* how far windows move and resize with the keyboard arrows */ -#define KEY_DIST 4 +#define KEY_DIST 8 gboolean moveresize_in_progress = FALSE; ObClient *moveresize_client = NULL; @@ -434,7 +435,7 @@ static gboolean edge_warp_delay_func(gpointer data) static void do_edge_warp(gint x, gint y) { - guint i, d; + guint i; ObDirection dir; if (!config_mouse_screenedgetime) return; @@ -597,15 +598,41 @@ gboolean moveresize_event(XEvent *e) } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) { gint dx = 0, dy = 0, ox = cur_x, oy = cur_y; gint opx, px, opy, py; - - if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) - dx = KEY_DIST; - else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) - dx = -KEY_DIST; - else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) - dy = KEY_DIST; - else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */ - dy = -KEY_DIST; + gint dist = KEY_DIST; + + /* shift means jump to edge */ + if (e->xkey.state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) { + gint x, y; + ObDirection dir; + + if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) + dir = OB_DIRECTION_EAST; + else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) + dir = OB_DIRECTION_WEST; + else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) + dir = OB_DIRECTION_SOUTH; + else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */ + dir = OB_DIRECTION_NORTH; + + client_find_move_directional(moveresize_client, dir, + &x, &y); + dx = x - moveresize_client->area.x; + dy = y - moveresize_client->area.y; + } else { + /* control means fine grained */ + if (e->xkey.state & + modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL)) + dist = 1; + + if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) + dx = dist; + else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) + dx = -dist; + else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) + dy = dist; + else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */ + dy = -dist; + } cur_x += dx; cur_y += dy; -- 2.45.2