X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmoveresize.c;h=19bed579d234d2a9124c86a0ef1ac67d5860e977;hb=04b570de01abc9661f9cf30dba306e66307957f3;hp=39fdd45daefaba48a5f67692be79c3bb5764305c;hpb=ad852b6b56e43bdd7dda1389f54051cf92c0fad9;p=chaz%2Fopenbox diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 39fdd45d..19bed579 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -25,6 +25,8 @@ #include "frame.h" #include "openbox.h" #include "resist.h" +#include "mainloop.h" +#include "modkeys.h" #include "popup.h" #include "moveresize.h" #include "config.h" @@ -37,6 +39,9 @@ #include #include +/* how far windows move and resize with the keyboard arrows */ +#define KEY_DIST 8 + gboolean moveresize_in_progress = FALSE; ObClient *moveresize_client = NULL; #ifdef SYNC @@ -50,12 +55,16 @@ static gint cur_x, cur_y; static guint button; static guint32 corner; static ObCorner lockcorner; +static ObDirection edge_warp_dir = -1; #ifdef SYNC static gboolean waiting_for_sync; #endif static ObPopup *popup = NULL; +static void do_edge_warp(gint x, gint y); +static void cancel_edge_warp(); + static void client_dest(ObClient *client, gpointer data) { if (moveresize_client == client) @@ -65,9 +74,10 @@ static void client_dest(ObClient *client, gpointer data) void moveresize_startup(gboolean reconfig) { popup = popup_new(FALSE); + popup_set_text_align(popup, RR_JUSTIFY_CENTER); if (!reconfig) - client_add_destructor(client_dest, NULL); + client_add_destroy_notify(client_dest, NULL); } void moveresize_shutdown(gboolean reconfig) @@ -75,13 +85,57 @@ void moveresize_shutdown(gboolean reconfig) if (!reconfig) { if (moveresize_in_progress) moveresize_end(FALSE); - client_remove_destructor(client_dest); + client_remove_destroy_notify(client_dest); } popup_free(popup); 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); + 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); +} + static void popup_coords(ObClient *c, const gchar *format, gint a, gint b) { gchar *text; @@ -105,19 +159,54 @@ static void popup_coords(ObClient *c, const gchar *format, gint a, gint b) void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) { ObCursor cur; - - moving = (cnr == prop_atoms.net_wm_moveresize_move || - cnr == prop_atoms.net_wm_moveresize_move_keyboard); + gboolean mv = (cnr == prop_atoms.net_wm_moveresize_move || + cnr == prop_atoms.net_wm_moveresize_move_keyboard); if (moveresize_in_progress || !c->frame->visible || - !(moving ? + !(mv ? (c->functions & OB_CLIENT_FUNC_MOVE) : (c->functions & OB_CLIENT_FUNC_RESIZE))) return; + if (cnr == prop_atoms.net_wm_moveresize_size_topleft) + cur = OB_CURSOR_NORTHWEST; + else if (cnr == prop_atoms.net_wm_moveresize_size_top) + cur = OB_CURSOR_NORTH; + else if (cnr == prop_atoms.net_wm_moveresize_size_topright) + cur = OB_CURSOR_NORTHEAST; + else if (cnr == prop_atoms.net_wm_moveresize_size_right) + cur = OB_CURSOR_EAST; + else if (cnr == prop_atoms.net_wm_moveresize_size_bottomright) + cur = OB_CURSOR_SOUTHEAST; + else if (cnr == prop_atoms.net_wm_moveresize_size_bottom) + cur = OB_CURSOR_SOUTH; + else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft) + cur = OB_CURSOR_SOUTHWEST; + else if (cnr == prop_atoms.net_wm_moveresize_size_left) + cur = OB_CURSOR_WEST; + else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard) + cur = OB_CURSOR_SOUTHEAST; + else if (cnr == prop_atoms.net_wm_moveresize_move) + cur = OB_CURSOR_MOVE; + else if (cnr == prop_atoms.net_wm_moveresize_move_keyboard) + cur = OB_CURSOR_MOVE; + else + g_assert_not_reached(); + + /* keep the pointer bounded to the screen for move/resize */ + if (!grab_pointer(FALSE, TRUE, cur)) + return; + if (!grab_keyboard()) { + ungrab_pointer(); + return; + } + + frame_end_iconify_animation(c->frame); + + moving = mv; moveresize_client = c; - start_cx = c->frame->area.x; - start_cy = c->frame->area.y; + start_cx = c->area.x; + start_cy = c->area.y; /* 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 @@ -148,34 +237,9 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) moveresize_in_progress = TRUE; - if (corner == prop_atoms.net_wm_moveresize_size_topleft) - cur = OB_CURSOR_NORTHWEST; - else if (corner == prop_atoms.net_wm_moveresize_size_top) - cur = OB_CURSOR_NORTH; - else if (corner == prop_atoms.net_wm_moveresize_size_topright) - cur = OB_CURSOR_NORTHEAST; - else if (corner == prop_atoms.net_wm_moveresize_size_right) - cur = OB_CURSOR_EAST; - else if (corner == prop_atoms.net_wm_moveresize_size_bottomright) - cur = OB_CURSOR_SOUTHEAST; - else if (corner == prop_atoms.net_wm_moveresize_size_bottom) - cur = OB_CURSOR_SOUTH; - else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft) - cur = OB_CURSOR_SOUTHWEST; - else if (corner == prop_atoms.net_wm_moveresize_size_left) - cur = OB_CURSOR_WEST; - else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) - cur = OB_CURSOR_SOUTHEAST; - else if (corner == prop_atoms.net_wm_moveresize_move) - cur = OB_CURSOR_MOVE; - else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) - cur = OB_CURSOR_MOVE; - else - g_assert_not_reached(); - #ifdef SYNC - if (!moving && extensions_shape && moveresize_client->sync_request && - moveresize_client->sync_counter) + if (config_resize_redraw && !moving && extensions_shape && + moveresize_client->sync_request && moveresize_client->sync_counter) { /* Initialize values for the resize syncing, and create an alarm for the client's xsync counter */ @@ -213,15 +277,14 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) waiting_for_sync = FALSE; } #endif - - grab_pointer(TRUE, FALSE, cur); - grab_keyboard(TRUE); } void moveresize_end(gboolean cancel) { - grab_keyboard(FALSE); - grab_pointer(FALSE, FALSE, OB_CURSOR_NONE); + gint x, y; + + ungrab_keyboard(); + ungrab_pointer(); popup_hide(popup); @@ -238,46 +301,50 @@ void moveresize_end(gboolean cancel) } #endif - client_configure(moveresize_client, lockcorner, - moveresize_client->area.x, - moveresize_client->area.y, + get_resize_position(&x, &y, cancel); + client_configure(moveresize_client, x, y, (cancel ? start_cw : cur_x), - (cancel ? start_ch : cur_y), TRUE, TRUE); + (cancel ? start_ch : cur_y), + TRUE, TRUE, FALSE); } + /* dont edge warp after its ended */ + cancel_edge_warp(); + moveresize_in_progress = FALSE; moveresize_client = NULL; } -static void do_move(gboolean resist) +static void do_move(gboolean keyboard) { - if (resist) { - resist_move_windows(moveresize_client, &cur_x, &cur_y); - resist_move_monitors(moveresize_client, &cur_x, &cur_y); - } + gint resist; - /* get where the client should be */ - frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y); - client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y, + if (keyboard) resist = KEY_DIST - 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, TRUE, FALSE); + moveresize_client->area.height, + TRUE, FALSE, FALSE); if (config_resize_popup_show == 2) /* == "Always" */ popup_coords(moveresize_client, "%d x %d", - moveresize_client->frame->area.x, - moveresize_client->frame->area.y); + moveresize_client->frame->area.x, + moveresize_client->frame->area.y); } static void do_resize() { -#ifdef SYNC gint x, y, w, h, lw, lh; /* see if it is actually going to resize */ - x = moveresize_client->area.x; - y = moveresize_client->area.y; + x = 0; + y = 0; w = cur_x; h = cur_y; - client_try_configure(moveresize_client, lockcorner, &x, &y, &w, &h, + client_try_configure(moveresize_client, &x, &y, &w, &h, &lw, &lh, TRUE); if (w == moveresize_client->area.width && h == moveresize_client->area.height) @@ -285,8 +352,9 @@ static void do_resize() return; } - if (extensions_sync && moveresize_client->sync_request && - moveresize_client->sync_counter) +#ifdef SYNC + if (config_resize_redraw && extensions_sync && + moveresize_client->sync_request && moveresize_client->sync_counter) { XEvent ce; XSyncValue val; @@ -317,34 +385,35 @@ static void do_resize() } #endif - client_configure(moveresize_client, lockcorner, - moveresize_client->area.x, moveresize_client->area.y, - cur_x, cur_y, TRUE, FALSE); + get_resize_position(&x, &y, FALSE); + client_configure(moveresize_client, x, y, cur_x, cur_y, TRUE, FALSE, FALSE); /* this would be better with a fixed width font ... XXX can do it better if there are 2 text boxes */ if (config_resize_popup_show == 2 || /* == "Always" */ (config_resize_popup_show == 1 && /* == "Nonpixel" */ - (moveresize_client->size_inc.width > 1 || - moveresize_client->size_inc.height > 1)) - ) + moveresize_client->size_inc.width > 1 && + moveresize_client->size_inc.height > 1)) popup_coords(moveresize_client, "%d x %d", moveresize_client->logical_size.width, moveresize_client->logical_size.height); } -static void calc_resize(gboolean resist) +static void calc_resize(gboolean keyboard) { + gint resist; + /* resist_size_* needs the frame size */ cur_x += moveresize_client->frame->size.left + moveresize_client->frame->size.right; cur_y += moveresize_client->frame->size.top + moveresize_client->frame->size.bottom; - if (resist) { - resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner); - resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner); - } + if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */ + else resist = config_resist_win; + resist_size_windows(moveresize_client, resist, &cur_x, &cur_y, lockcorner); + if (!keyboard) resist = config_resist_edge; + resist_size_monitors(moveresize_client, resist, &cur_x, &cur_y,lockcorner); cur_x -= moveresize_client->frame->size.left + moveresize_client->frame->size.right; @@ -352,9 +421,70 @@ static void calc_resize(gboolean resist) moveresize_client->frame->size.bottom; } -void moveresize_event(XEvent *e) +static gboolean edge_warp_delay_func(gpointer data) { - g_assert(moveresize_in_progress); + guint d; + + d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE); + if (d != screen_desktop) screen_set_desktop(d, TRUE); + + edge_warp_dir = -1; + + return FALSE; /* don't repeat */ +} + +static void do_edge_warp(gint x, gint y) +{ + guint i; + ObDirection dir; + + if (!config_mouse_screenedgetime) return; + + dir = -1; + + for (i = 0; i < screen_num_monitors; ++i) { + Rect *a = screen_physical_area_monitor(i); + if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST; + if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST; + if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH; + if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH; + + /* try check for xinerama boundaries */ + if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) && + (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST)) + { + dir = -1; + } + if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) && + (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH)) + { + dir = -1; + } + g_free(a); + } + + if (dir != edge_warp_dir) { + if (dir == (ObDirection)-1) + cancel_edge_warp(); + else + ob_main_loop_timeout_add(ob_main_loop, + config_mouse_screenedgetime * 1000, + edge_warp_delay_func, + NULL, NULL, NULL); + edge_warp_dir = dir; + } +} + +static void cancel_edge_warp() +{ + ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func); +} + +gboolean moveresize_event(XEvent *e) +{ + gboolean used = FALSE; + + if (!moveresize_in_progress) return FALSE; if (e->type == ButtonPress) { if (!button) { @@ -362,15 +492,18 @@ void moveresize_event(XEvent *e) start_y = e->xbutton.y_root; button = e->xbutton.button; /* this will end it now */ } + used = e->xbutton.button == button; } else if (e->type == ButtonRelease) { if (!button || e->xbutton.button == button) { moveresize_end(FALSE); + used = TRUE; } } else if (e->type == MotionNotify) { if (moving) { cur_x = start_cx + e->xmotion.x_root - start_x; cur_y = start_cy + e->xmotion.y_root - start_y; - do_move(TRUE); + do_move(FALSE); + do_edge_warp(e->xmotion.x_root, e->xmotion.y_root); } else { if (corner == prop_atoms.net_wm_moveresize_size_topleft) { cur_x = start_cw - (e->xmotion.x_root - start_x); @@ -413,28 +546,33 @@ void moveresize_event(XEvent *e) } else g_assert_not_reached(); - calc_resize(TRUE); + calc_resize(FALSE); do_resize(); } + used = TRUE; } else if (e->type == KeyPress) { - if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) + if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) { moveresize_end(TRUE); - else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) + used = TRUE; + } else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) { moveresize_end(FALSE); - else { + used = TRUE; + } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) || + e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || + e->xkey.keycode == ob_keycode(OB_KEY_DOWN) || + 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(4, moveresize_client->size_inc.width); + dx = MAX(KEY_DIST, moveresize_client->size_inc.width); else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) - dx = -MAX(4, moveresize_client->size_inc.width); + dx = -MAX(KEY_DIST, moveresize_client->size_inc.width); else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) - dy = MAX(4, moveresize_client->size_inc.height); - else if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) - dy = -MAX(4, moveresize_client->size_inc.height); - else - return; + 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; @@ -446,7 +584,8 @@ void moveresize_event(XEvent *e) while (XCheckTypedEvent(ob_display, MotionNotify, &ce)); } - do_resize(FALSE); + calc_resize(TRUE); + do_resize(); /* because the cursor moves even though the window does not nessesarily (resistance), this adjusts where the curor @@ -454,20 +593,46 @@ void moveresize_event(XEvent *e) actually is */ start_x += dx - (cur_x - ox); start_y += dy - (cur_y - oy); + + 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 = 4; - else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) - dx = -4; - else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) - dy = 4; - else if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) - dy = -4; - else - return; + 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; @@ -481,7 +646,7 @@ void moveresize_event(XEvent *e) } screen_pointer_pos(&px, &py); - do_move(FALSE); + do_move(TRUE); /* because the cursor moves even though the window does not nessesarily (resistance), this adjusts where the curor @@ -489,6 +654,8 @@ void moveresize_event(XEvent *e) actually is */ start_x += (px - opx) - (cur_x - ox); start_y += (py - opy) - (cur_y - oy); + + used = TRUE; } } } @@ -497,6 +664,8 @@ void moveresize_event(XEvent *e) { waiting_for_sync = FALSE; /* we got our sync... */ do_resize(); /* ...so try resize if there is more change pending */ + used = TRUE; } #endif + return used; }