rewrote the movetoedge code so it works with both types of edges (to edge and from edge)

This commit is contained in:
Dana Jansens 2007-06-28 05:18:01 +00:00
parent d9699d1470
commit 01a35904fe
5 changed files with 189 additions and 227 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
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;
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 ? cur->frame->area.height : 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)
}
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_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;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
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)
}
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();
}
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:
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 && 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, self); /* skip windows to not bump into */
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;
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();
}
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();
}
if (!skip_head)
dest = head;
else if (!skip_tail)
dest = tail;
}
switch(dir) {
case OB_DIRECTION_NORTH:
case OB_DIRECTION_SOUTH:
*y = dest;
break;
case OB_DIRECTION_WEST:
case OB_DIRECTION_EAST:
*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()

View file

@ -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.<br />
= 0 indicates the client should be placed with other clients.<br />

View file

@ -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 <glib.h>
/* 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;
gint dist = KEY_DIST;
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;
/* 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;