gboolean oldgtran, gboolean newgtran,
ObClient* oldparent,
ObClient *newparent);
-static void client_present(ObClient *self, gboolean here, gboolean raise);
+static void client_present(ObClient *self, gboolean here, gboolean raise,
+ gboolean unshade);
static GSList *client_search_all_top_parents_internal(ObClient *self,
gboolean bylayer,
ObStackingLayer layer);
if (activate) {
gboolean stacked = client_restore_session_stacking(self);
- client_present(self, FALSE, !stacked);
+ client_present(self, FALSE, !stacked, TRUE);
}
/* add to client list/map */
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;
}
/* 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;
}
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 */
}
/* 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)) {
oldw = self->area.width;
oldh = self->area.height;
RECT_SET(self->area, x, y, w, h);
- ob_debug("Client area %s set to %d %d %d %d\n",
- self->title, self->area.x, self->area.y,
- self->area.width, self->area.height);
/* for app-requested resizes, always resize if 'resized' is true.
for user-requested ones, only resize if final is true, or when
"Focusing client \"%s\" (0x%x) at time %u\n",
self->title, self->window, event_curtime);
+ /* if using focus_delay, stop the timer now so that focus doesn't
+ go moving on us */
+ event_halt_focus_delay();
+
/* if there is a grab going on, then we need to cancel it. if we move
focus during the grab, applications will get NotifyWhileGrabbed events
and ignore them !
return !xerror_occured;
}
-/*! Present the client to the user.
- @param raise If the client should be raised or not. You should only set
- raise to false if you don't care if the window is completely
- hidden.
-*/
-static void client_present(ObClient *self, gboolean here, gboolean raise)
+static void client_present(ObClient *self, gboolean here, gboolean raise,
+ gboolean unshade)
{
- /* if using focus_delay, stop the timer now so that focus doesn't
- go moving on us */
- event_halt_focus_delay();
-
if (client_normal(self) && screen_showing_desktop)
screen_show_desktop(FALSE, self);
if (self->iconic)
/* if its not visible for other reasons, then don't mess
with it */
return;
- if (self->shaded)
+ if (self->shaded && unshade)
client_shade(self, FALSE);
if (raise)
stacking_raise(CLIENT_AS_WINDOW(self));
client_focus(self);
}
-void client_activate(ObClient *self, gboolean here, gboolean user)
+void client_activate(ObClient *self, gboolean here, gboolean raise,
+ gboolean unshade, gboolean user)
{
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
gboolean allow = FALSE;
(user ? "user" : "application"), allow);
if (allow)
- client_present(self, here, TRUE);
+ client_present(self, here, raise, unshade);
else
/* don't focus it but tell the user it wants attention */
client_hilite(self, TRUE);
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)
-{
- gint dest, monitor_dest;
- gint my_edge_start, my_edge_end, my_offset;
+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)
+{
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)
+ 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)
+ 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;
+ 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) * (grow ? 1 : -1);
+ 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) * (grow ? 1 : -1);
+ 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) * (grow ? 1 : -1);
+ 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) * (grow ? 1 : -1);
+ 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;
+ ob_debug("head %d dir %d\n", head, dir);
+ client_find_edge_directional(self, dir, head, 1,
+ e_start, e_size, &e, &near);
+ ob_debug("edge %d\n", e);
+ *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 (grow == near) --e;
+ delta = e - RECT_RIGHT(self->frame->area);
+ *w += delta;
+ break;
+ case OB_DIRECTION_WEST:
+ if (grow == near) ++e;
+ delta = RECT_LEFT(self->frame->area) - e;
+ *x -= delta;
+ *w += delta;
+ break;
+ case OB_DIRECTION_NORTH:
+ if (grow == near) ++e;
+ delta = RECT_TOP(self->frame->area) - e;
+ *y -= delta;
+ *h += delta;
+ break;
+ case OB_DIRECTION_SOUTH:
+ if (grow == 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()
#include "openbox.h"
#include "resist.h"
#include "mainloop.h"
+#include "modkeys.h"
#include "popup.h"
#include "moveresize.h"
#include "config.h"
#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;
static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
-static gint cur_x, cur_y;
+static gint cur_x, cur_y, cur_w, cur_h;
static guint button;
static guint32 corner;
static ObCorner lockcorner;
static ObDirection edge_warp_dir = -1;
+static ObDirection key_resize_edge = -1;
#ifdef SYNC
static gboolean waiting_for_sync;
#endif
static void do_edge_warp(gint x, gint y);
static void cancel_edge_warp();
+#ifdef SYNC
+static gboolean sync_timeout_func(gpointer data);
+#endif
static void client_dest(ObClient *client, gpointer data)
{
popup = NULL;
}
-static void get_resize_position(gint *x, gint *y, gboolean cancel)
-{
- gint dw, dh;
- gint w, h, lw, lh;
-
- *x = moveresize_client->frame->area.x;
- *y = moveresize_client->frame->area.y;
-
- if (cancel) {
- w = start_cw;
- h = start_ch;
- } else {
- w = cur_x;
- h = cur_y;
- }
-
- /* see how much it is actually going to resize */
- {
- gint cx = *x, cy = *y;
- frame_frame_gravity(moveresize_client->frame, &cx, &cy, w, h);
- client_try_configure(moveresize_client, &cx, &cy, &w, &h,
- &lw, &lh, TRUE);
- }
- dw = w - moveresize_client->area.width;
- dh = h - moveresize_client->area.height;
-
- switch (lockcorner) {
- case OB_CORNER_TOPLEFT:
- break;
- case OB_CORNER_TOPRIGHT:
- *x -= dw;
- break;
- case OB_CORNER_BOTTOMLEFT:
- *y -= dh;
- break;
- case OB_CORNER_BOTTOMRIGHT:
- *x -= dw;
- *y -= dh;
- break;
- }
-
- frame_frame_gravity(moveresize_client->frame, x, y, w, h);
-}
-
static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
{
gchar *text;
moveresize_client = c;
start_cx = c->area.x;
start_cy = c->area.y;
+ start_cw = c->area.width;
+ start_ch = c->area.height;
/* these adjustments for the size_inc make resizing a terminal more
friendly. you essentially start the resize in the middle of the
increment instead of at 0, so you have to move half an increment
- either way instead of a full increment one and 1 px the other. and this
- is one large mother fucking comment. */
- start_cw = c->area.width + c->size_inc.width / 2;
- start_ch = c->area.height + c->size_inc.height / 2;
- start_x = x;
- start_y = y;
+ either way instead of a full increment one and 1 px the other. */
+ start_x = x - c->size_inc.width / 2;
+ start_y = y - c->size_inc.height / 2;
corner = cnr;
button = b;
+ key_resize_edge = -1;
/*
have to change start_cx and start_cy if going to do this..
c->area.width / 2, c->area.height / 2);
*/
- if (moving) {
- cur_x = start_cx;
- cur_y = start_cy;
- } else {
- cur_x = start_cw;
- cur_y = start_ch;
- }
+ cur_x = start_cx;
+ cur_y = start_cy;
+ cur_w = start_cw;
+ cur_h = start_ch;
moveresize_in_progress = TRUE;
#ifdef SYNC
- if (config_resize_redraw && !moving && extensions_shape &&
+ if (config_resize_redraw && !moving && extensions_sync &&
moveresize_client->sync_request && moveresize_client->sync_counter)
{
/* Initialize values for the resize syncing, and create an alarm for
void moveresize_end(gboolean cancel)
{
- gint x, y;
-
ungrab_keyboard();
ungrab_pointer();
XSyncDestroyAlarm(ob_display, moveresize_alarm);
moveresize_alarm = None;
}
+
+ ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
#endif
- get_resize_position(&x, &y, cancel);
- client_configure(moveresize_client, x, y,
- (cancel ? start_cw : cur_x),
- (cancel ? start_ch : cur_y),
+ client_configure(moveresize_client,
+ (cancel ? start_cx : cur_x),
+ (cancel ? start_cy : cur_y),
+ (cancel ? start_cw : cur_w),
+ (cancel ? start_ch : cur_h),
TRUE, TRUE, FALSE);
}
moveresize_client = NULL;
}
-static void do_move(gboolean keyboard)
+static void do_move(gboolean keyboard, gint keydist)
{
gint resist;
- if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+ if (keyboard) resist = keydist - 1; /* resist for one key press */
else resist = config_resist_win;
resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
if (!keyboard) resist = config_resist_edge;
resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
- client_configure(moveresize_client, cur_x, cur_y,
- moveresize_client->area.width,
- moveresize_client->area.height,
+ client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
TRUE, FALSE, FALSE);
if (config_resize_popup_show == 2) /* == "Always" */
popup_coords(moveresize_client, "%d x %d",
moveresize_client->frame->area.y);
}
+
static void do_resize()
{
gint x, y, w, h, lw, lh;
/* see if it is actually going to resize */
x = 0;
y = 0;
- w = cur_x;
- h = cur_y;
+ w = cur_w;
+ h = cur_h;
client_try_configure(moveresize_client, &x, &y, &w, &h,
&lw, &lh, TRUE);
if (w == moveresize_client->area.width &&
NoEventMask, &ce);
waiting_for_sync = TRUE;
+
+ ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
+ ob_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
+ sync_timeout_func,
+ NULL, NULL, NULL);
}
#endif
- get_resize_position(&x, &y, FALSE);
- client_configure(moveresize_client, x, y, cur_x, cur_y, TRUE, FALSE, FALSE);
+ client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
+ TRUE, FALSE, FALSE);
/* this would be better with a fixed width font ... XXX can do it better
if there are 2 text boxes */
moveresize_client->logical_size.height);
}
-static void calc_resize(gboolean keyboard)
+#ifdef SYNC
+static gboolean sync_timeout_func(gpointer data)
+{
+ waiting_for_sync = FALSE; /* we timed out waiting for our sync... */
+ do_resize(); /* ...so let any pending resizes through */
+
+ return FALSE; /* don't repeat */
+}
+#endif
+
+static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh,
+ ObCorner cor)
{
- gint resist;
+ gint resist, x, y, lw, lh, ow, oh, nw, nh;
+ ow = cur_w;
+ oh = cur_h;
/* resist_size_* needs the frame size */
- cur_x += moveresize_client->frame->size.left +
+ nw = ow + *dw +
+ moveresize_client->frame->size.left +
moveresize_client->frame->size.right;
- cur_y += moveresize_client->frame->size.top +
+ nh = oh + *dh +
+ moveresize_client->frame->size.top +
moveresize_client->frame->size.bottom;
- if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+ if (keyboard) resist = keydist - 1; /* resist for one key press */
else resist = config_resist_win;
- resist_size_windows(moveresize_client, resist, &cur_x, &cur_y, lockcorner);
+ resist_size_windows(moveresize_client, resist, &nw, &nh, cor);
if (!keyboard) resist = config_resist_edge;
- resist_size_monitors(moveresize_client, resist, &cur_x, &cur_y,lockcorner);
+ resist_size_monitors(moveresize_client, resist, &nw, &nh, cor);
- cur_x -= moveresize_client->frame->size.left +
+ nw -= moveresize_client->frame->size.left +
moveresize_client->frame->size.right;
- cur_y -= moveresize_client->frame->size.top +
+ nh -= moveresize_client->frame->size.top +
moveresize_client->frame->size.bottom;
+
+ /* see its actual size */
+ x = 0;
+ y = 0;
+ client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
+
+
+ *dw = nw - ow;
+ *dh = nh - oh;
}
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;
ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
}
+static void move_with_keys(gint keycode, gint state)
+{
+ gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
+ gint opx, px, opy, py;
+ gint dist = 0;
+
+ /* shift means jump to edge */
+ if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+ gint x, y;
+ ObDirection dir;
+
+ if (keycode == ob_keycode(OB_KEY_RIGHT))
+ dir = OB_DIRECTION_EAST;
+ else if (keycode == ob_keycode(OB_KEY_LEFT))
+ dir = OB_DIRECTION_WEST;
+ else if (keycode == ob_keycode(OB_KEY_DOWN))
+ dir = OB_DIRECTION_SOUTH;
+ else /* if (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 (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+ dist = 1;
+ else
+ dist = KEY_DIST;
+
+ if (keycode == ob_keycode(OB_KEY_RIGHT))
+ dx = dist;
+ else if (keycode == ob_keycode(OB_KEY_LEFT))
+ dx = -dist;
+ else if (keycode == ob_keycode(OB_KEY_DOWN))
+ dy = dist;
+ else /* if (keycode == ob_keycode(OB_KEY_UP)) */
+ dy = -dist;
+ }
+
+ screen_pointer_pos(&opx, &opy);
+ XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
+ /* steal the motion events this causes */
+ XSync(ob_display, FALSE);
+ {
+ XEvent ce;
+ while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+ }
+ screen_pointer_pos(&px, &py);
+
+ cur_x += dx;
+ cur_y += dy;
+ do_move(TRUE, dist);
+
+ /* because the cursor moves even though the window does
+ not nessesarily (resistance), this adjusts where the curor
+ thinks it started so that it keeps up with where the window
+ actually is */
+ start_x += (px - opx) - (cur_x - ox);
+ start_y += (py - opy) - (cur_y - oy);
+}
+
+static void resize_with_keys(gint keycode, gint state)
+{
+ gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
+ gint dist = 0;
+ ObDirection dir;
+ ObCorner cor;
+
+ /* pick the edge if it needs to move */
+ if (keycode == ob_keycode(OB_KEY_RIGHT)) {
+ dir = OB_DIRECTION_EAST;
+ if (key_resize_edge != OB_DIRECTION_WEST &&
+ key_resize_edge != OB_DIRECTION_EAST)
+ {
+ key_resize_edge = OB_DIRECTION_EAST;
+ return;
+ }
+ }
+ if (keycode == ob_keycode(OB_KEY_LEFT)) {
+ dir = OB_DIRECTION_WEST;
+ if (key_resize_edge != OB_DIRECTION_WEST &&
+ key_resize_edge != OB_DIRECTION_EAST)
+ {
+ key_resize_edge = OB_DIRECTION_WEST;
+ return;
+ }
+ }
+ if (keycode == ob_keycode(OB_KEY_UP)) {
+ dir = OB_DIRECTION_NORTH;
+ if (key_resize_edge != OB_DIRECTION_NORTH &&
+ key_resize_edge != OB_DIRECTION_SOUTH)
+ {
+ key_resize_edge = OB_DIRECTION_NORTH;
+ return;
+ }
+ }
+ if (keycode == ob_keycode(OB_KEY_DOWN)) {
+ dir = OB_DIRECTION_SOUTH;
+ if (key_resize_edge != OB_DIRECTION_NORTH &&
+ key_resize_edge != OB_DIRECTION_SOUTH)
+ {
+ key_resize_edge = OB_DIRECTION_SOUTH;
+ return;
+ }
+ }
+
+ /* shift means jump to edge */
+ if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+ gint x, y, w, h;
+
+ if (keycode == ob_keycode(OB_KEY_RIGHT))
+ dir = OB_DIRECTION_EAST;
+ else if (keycode == ob_keycode(OB_KEY_LEFT))
+ dir = OB_DIRECTION_WEST;
+ else if (keycode == ob_keycode(OB_KEY_DOWN))
+ dir = OB_DIRECTION_SOUTH;
+ else /* if (keycode == ob_keycode(OB_KEY_UP)) */
+ dir = OB_DIRECTION_NORTH;
+
+ client_find_resize_directional(moveresize_client, key_resize_edge,
+ key_resize_edge == dir,
+ &x, &y, &w, &h);
+ dw = w - moveresize_client->area.width;
+ dh = h - moveresize_client->area.height;
+ } else {
+ gint distw, disth;
+
+ /* control means fine grained */
+ if (moveresize_client->size_inc.width > 1)
+ distw = moveresize_client->size_inc.width;
+ else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+ distw = 1;
+ else
+ distw = KEY_DIST;
+ if (moveresize_client->size_inc.height > 1)
+ disth = moveresize_client->size_inc.height;
+ else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+ disth = 1;
+ else
+ disth = KEY_DIST;
+
+ if (key_resize_edge == OB_DIRECTION_WEST) {
+ if (dir == OB_DIRECTION_WEST)
+ dw = (dist = distw);
+ else
+ dw = -(dist = distw);
+ }
+ else if (key_resize_edge == OB_DIRECTION_EAST) {
+ if (dir == OB_DIRECTION_EAST)
+ dw = (dist = distw);
+ else
+ dw = -(dist = distw);
+ }
+ else if (key_resize_edge == OB_DIRECTION_NORTH) {
+ if (dir == OB_DIRECTION_NORTH)
+ dh = (dist = disth);
+ else
+ dh = -(dist = disth);
+ }
+ else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
+ if (dir == OB_DIRECTION_SOUTH)
+ dh = (dist = disth);
+ else
+ dh = -(dist = disth);
+ }
+ }
+
+ /* which corner is locked, for resistance */
+ if (key_resize_edge == OB_DIRECTION_WEST)
+ cor = OB_CORNER_TOPRIGHT;
+ else if (key_resize_edge == OB_DIRECTION_EAST)
+ cor = OB_CORNER_TOPLEFT;
+ else if (key_resize_edge == OB_DIRECTION_NORTH)
+ cor = OB_CORNER_BOTTOMLEFT;
+ else if (key_resize_edge == OB_DIRECTION_SOUTH)
+ cor = OB_CORNER_TOPLEFT;
+
+ calc_resize(TRUE, dist, &dw, &dh, cor);
+ if (key_resize_edge == OB_DIRECTION_WEST)
+ cur_x -= dw;
+ else if (key_resize_edge == OB_DIRECTION_NORTH)
+ cur_y -= dh;
+ cur_w += dw;
+ cur_h += dh;
+
+ /* how to move the pointer to keep up with the change */
+ if (key_resize_edge == OB_DIRECTION_WEST)
+ pdx = -dw;
+ else if (key_resize_edge == OB_DIRECTION_EAST)
+ pdx = dw;
+ else if (key_resize_edge == OB_DIRECTION_NORTH)
+ pdy = -dh;
+ else if (key_resize_edge == OB_DIRECTION_SOUTH)
+ pdy = dh;
+
+ screen_pointer_pos(&opx, &opy);
+ XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
+ /* steal the motion events this causes */
+ XSync(ob_display, FALSE);
+ {
+ XEvent ce;
+ while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+ }
+ screen_pointer_pos(&px, &py);
+
+ do_resize();
+
+ /* because the cursor moves even though the window does
+ not nessesarily (resistance), this adjusts where the cursor
+ thinks it started so that it keeps up with where the window
+ actually is */
+ start_x += (px - opx) - dw;
+ start_y += (py - opy) - dh;
+
+}
+
gboolean moveresize_event(XEvent *e)
{
gboolean used = FALSE;
- g_assert(moveresize_in_progress);
+ if (!moveresize_in_progress) return FALSE;
if (e->type == ButtonPress) {
if (!button) {
if (moving) {
cur_x = start_cx + e->xmotion.x_root - start_x;
cur_y = start_cy + e->xmotion.y_root - start_y;
- do_move(FALSE);
+ do_move(FALSE, 0);
do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
} else {
+ gint dw, dh;
+
if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
- cur_x = start_cw - (e->xmotion.x_root - start_x);
- cur_y = start_ch - (e->xmotion.y_root - start_y);
+ dw = -(e->xmotion.x_root - start_x);
+ dh = -(e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_BOTTOMRIGHT;
} else if (corner == prop_atoms.net_wm_moveresize_size_top) {
- cur_x = start_cw;
- cur_y = start_ch - (e->xmotion.y_root - start_y);
+ dw = 0;
+ dh = -(e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_BOTTOMRIGHT;
} else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
- cur_x = start_cw + (e->xmotion.x_root - start_x);
- cur_y = start_ch - (e->xmotion.y_root - start_y);
+ dw = (e->xmotion.x_root - start_x);
+ dh = -(e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_BOTTOMLEFT;
} else if (corner == prop_atoms.net_wm_moveresize_size_right) {
- cur_x = start_cw + (e->xmotion.x_root - start_x);
- cur_y = start_ch;
+ dw = (e->xmotion.x_root - start_x);
+ dh = 0;
lockcorner = OB_CORNER_BOTTOMLEFT;
} else if (corner ==
prop_atoms.net_wm_moveresize_size_bottomright) {
- cur_x = start_cw + (e->xmotion.x_root - start_x);
- cur_y = start_ch + (e->xmotion.y_root - start_y);
+ dw = (e->xmotion.x_root - start_x);
+ dh = (e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_TOPLEFT;
} else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
- cur_x = start_cw;
- cur_y = start_ch + (e->xmotion.y_root - start_y);
+ dw = 0;
+ dh = (e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_TOPLEFT;
} else if (corner ==
prop_atoms.net_wm_moveresize_size_bottomleft) {
- cur_x = start_cw - (e->xmotion.x_root - start_x);
- cur_y = start_ch + (e->xmotion.y_root - start_y);
+ dw = -(e->xmotion.x_root - start_x);
+ dh = (e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_TOPRIGHT;
} else if (corner == prop_atoms.net_wm_moveresize_size_left) {
- cur_x = start_cw - (e->xmotion.x_root - start_x);
- cur_y = start_ch;
+ dw = -(e->xmotion.x_root - start_x);
+ dh = 0;
lockcorner = OB_CORNER_TOPRIGHT;
} else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
- cur_x = start_cw + (e->xmotion.x_root - start_x);
- cur_y = start_ch + (e->xmotion.y_root - start_y);
+ dw = (e->xmotion.x_root - start_x);
+ dh = (e->xmotion.y_root - start_y);
lockcorner = OB_CORNER_TOPLEFT;
} else
g_assert_not_reached();
- calc_resize(FALSE);
+ dw -= cur_w - start_cw;
+ dh -= cur_h - start_ch;
+
+ calc_resize(FALSE, 0, &dw, &dh, lockcorner);
+ cur_w += dw;
+ cur_h += dh;
+
+ if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
+ corner == prop_atoms.net_wm_moveresize_size_left ||
+ corner == prop_atoms.net_wm_moveresize_size_bottomleft)
+ {
+ cur_x -= dw;
+ }
+ if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
+ corner == prop_atoms.net_wm_moveresize_size_top ||
+ corner == prop_atoms.net_wm_moveresize_size_topright)
+ {
+ cur_y -= dh;
+ }
+
do_resize();
}
used = TRUE;
e->xkey.keycode == ob_keycode(OB_KEY_UP))
{
if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
- gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
-
- if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
- dx = MAX(KEY_DIST, moveresize_client->size_inc.width);
- else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
- dx = -MAX(KEY_DIST, moveresize_client->size_inc.width);
- else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
- dy = MAX(KEY_DIST, moveresize_client->size_inc.height);
- else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */
- dy = -MAX(KEY_DIST, moveresize_client->size_inc.height);
-
- cur_x += dx;
- cur_y += dy;
- XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
- /* steal the motion events this causes */
- XSync(ob_display, FALSE);
- {
- XEvent ce;
- while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
- }
-
- calc_resize(TRUE);
- do_resize();
-
- /* because the cursor moves even though the window does
- not nessesarily (resistance), this adjusts where the curor
- thinks it started so that it keeps up with where the window
- actually is */
- start_x += dx - (cur_x - ox);
- start_y += dy - (cur_y - oy);
-
+ resize_with_keys(e->xkey.keycode, e->xkey.state);
used = TRUE;
} 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;
-
- cur_x += dx;
- cur_y += dy;
- screen_pointer_pos(&opx, &opy);
- XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
- /* steal the motion events this causes */
- XSync(ob_display, FALSE);
- {
- XEvent ce;
- while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
- }
- screen_pointer_pos(&px, &py);
-
- do_move(TRUE);
-
- /* because the cursor moves even though the window does
- not nessesarily (resistance), this adjusts where the curor
- thinks it started so that it keeps up with where the window
- actually is */
- start_x += (px - opx) - (cur_x - ox);
- start_y += (py - opy) - (cur_y - oy);
-
+ move_with_keys(e->xkey.keycode, e->xkey.state);
used = TRUE;
}
}