diff options
-rw-r--r-- | src/client.c | 12 | ||||
-rw-r--r-- | src/display.c | 2 | ||||
-rw-r--r-- | src/display.h | 4 | ||||
-rw-r--r-- | src/events.c | 27 | ||||
-rw-r--r-- | src/menu.c | 3 | ||||
-rw-r--r-- | src/menu.h | 28 | ||||
-rw-r--r-- | src/moveresize.c | 493 | ||||
-rw-r--r-- | src/netwm.c | 36 | ||||
-rw-r--r-- | src/screen.c | 18 | ||||
-rw-r--r-- | src/screen.h | 4 |
10 files changed, 344 insertions, 283 deletions
diff --git a/src/client.c b/src/client.c index 72fac503f..8d8054d0f 100644 --- a/src/client.c +++ b/src/client.c @@ -68,6 +68,8 @@ #define FRAME_EVENT_MASK \ SubstructureNotifyMask|\ SubstructureRedirectMask|\ + PointerMotionMask|\ + ButtonMotionMask|\ FocusChangeMask|\ EnterWindowMask|\ PropertyChangeMask @@ -1685,7 +1687,6 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture) } clientAddToList (c); - clientSetNetActions (c); clientGrabButtons(c); /* Initialize per client menu button pixmap */ @@ -1763,6 +1764,8 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture) { clientRaise (c, None); clientInitFocusFlag (c); + clientSetNetState (c); + clientSetNetActions (c); } } else @@ -1770,6 +1773,7 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture) clientRaise (c, None); setWMState (display_info, c->window, IconicState); clientSetNetState (c); + clientSetNetActions (c); } if (!grabbed) @@ -2113,6 +2117,7 @@ clientShowSingle (Client * c, gboolean deiconify) setWMState (display_info, c->window, NormalState); } clientSetNetState (c); + clientSetNetActions (c); } void @@ -2171,6 +2176,7 @@ clientHideSingle (Client * c, gboolean iconify) setWMState (display_info, c->window, IconicState); } clientSetNetState (c); + clientSetNetActions (c); } void @@ -2720,6 +2726,7 @@ clientRemoveMaximizeFlag (Client * c) FLAG_UNSET (c->flags, CLIENT_FLAG_MAXIMIZED); frameQueueDraw (c, FALSE); clientSetNetState (c); + clientSetNetActions (c); } static void @@ -2890,6 +2897,9 @@ clientToggleMaximized (Client * c, int mode, gboolean restore_position) frameRight (c), frameBottom (c)); + /* Maximized windows w/out border cannot be resized, update allowed actions */ + clientSetNetActions (c); + if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED) && (restore_position)) { /* diff --git a/src/display.c b/src/display.c index d7f469807..aaecc76be 100644 --- a/src/display.c +++ b/src/display.c @@ -97,6 +97,8 @@ myDisplayInitAtoms (DisplayInfo *display_info) "_NET_SUPPORTED", "_NET_SUPPORTING_WM_CHECK", "_NET_SYSTEM_TRAY_OPCODE", + "_NET_WM_ACTION_ABOVE", + "_NET_WM_ACTION_BELOW", "_NET_WM_ACTION_CHANGE_DESKTOP", "_NET_WM_ACTION_CLOSE", "_NET_WM_ACTION_FULLSCREEN", diff --git a/src/display.h b/src/display.h index 7f6cd14f5..28702287b 100644 --- a/src/display.h +++ b/src/display.h @@ -113,6 +113,8 @@ enum SIDE_TOP, SIDE_COUNT }; +#define NO_HANDLE -1 +#define HANDLES_COUNT (CORNER_COUNT + SIDE_COUNT - 1) enum { @@ -189,6 +191,8 @@ enum NET_SUPPORTED, NET_SUPPORTING_WM_CHECK, NET_SYSTEM_TRAY_OPCODE, + NET_WM_ACTION_ABOVE, + NET_WM_ACTION_BELOW, NET_WM_ACTION_CHANGE_DESKTOP, NET_WM_ACTION_CLOSE, NET_WM_ACTION_FULLSCREEN, diff --git a/src/events.c b/src/events.c index da10f6f94..eca05478b 100644 --- a/src/events.c +++ b/src/events.c @@ -2599,6 +2599,12 @@ menu_callback (Menu * menu, MenuOp op, Window xid, gpointer menu_data, gpointer } frameQueueDraw (c, FALSE); break; + case MENU_OP_MOVE: + clientMove (c, NULL); + break; + case MENU_OP_RESIZE: + clientResize (c, CORNER_BOTTOM_RIGHT, NULL); + break; case MENU_OP_MINIMIZE_ALL: clientHideAll (c, c->win_workspace); frameQueueDraw (c, FALSE); @@ -2667,13 +2673,16 @@ show_window_menu (Client *c, gint px, gint py, guint button, guint32 time) return; } + screen_info = c->screen_info; + display_info = screen_info->display_info; + x = px; y = py; c->button_status[MENU_BUTTON] = BUTTON_STATE_PRESSED; frameQueueDraw (c, FALSE); y = (gdouble) c->y; - ops = MENU_OP_DELETE | MENU_OP_MINIMIZE_ALL | MENU_OP_WORKSPACES; + ops = MENU_OP_DELETE | MENU_OP_MINIMIZE_ALL | MENU_OP_WORKSPACES | MENU_OP_MOVE | MENU_OP_RESIZE; insensitive = 0; if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_CLOSE)) @@ -2698,6 +2707,18 @@ show_window_menu (Client *c, gint px, gint py, guint button, guint32 time) } } + if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE)) + { + insensitive |= MENU_OP_MOVE; + } + + if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE) || + ((FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED) + && (screen_info->params->borderless_maximize)))) + { + insensitive |= MENU_OP_RESIZE; + } + if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED)) { ops |= MENU_OP_UNMINIMIZE; @@ -2774,10 +2795,6 @@ show_window_menu (Client *c, gint px, gint py, guint button, guint32 time) insensitive |= MENU_OP_WORKSPACES; } - /* c is not null here */ - screen_info = c->screen_info; - display_info = screen_info->display_info; - if (screen_info->button_handler_id) { g_signal_handler_disconnect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)), screen_info->button_handler_id); diff --git a/src/menu.c b/src/menu.c index 87f0bf399..4663dc249 100644 --- a/src/menu.c +++ b/src/menu.c @@ -44,6 +44,9 @@ static MenuItem menuitems[] = { {MENU_OP_MINIMIZE, "gtk-undo", N_("_Hide")}, {MENU_OP_MINIMIZE_ALL, "gtk-clear", N_("Hide _all others")}, {MENU_OP_UNMINIMIZE, "gtk-add", N_("S_how")}, + {MENU_OP_MOVE, NULL, N_("Move")}, + {MENU_OP_RESIZE, NULL, N_("Resize")}, + {0, NULL, NULL}, {MENU_OP_SHADE, "gtk-goto-top", N_("_Shade")}, {MENU_OP_UNSHADE, "gtk-goto-bottom", N_("Un_shade")}, {MENU_OP_STICK, "gtk-add", N_("S_tick")}, diff --git a/src/menu.h b/src/menu.h index ac1039e26..05a5545d2 100644 --- a/src/menu.h +++ b/src/menu.h @@ -42,19 +42,21 @@ typedef enum MENU_OP_MINIMIZE = 1 << 2, MENU_OP_MINIMIZE_ALL = 1 << 3, MENU_OP_UNMINIMIZE = 1 << 4, - MENU_OP_SHADE = 1 << 5, - MENU_OP_UNSHADE = 1 << 6, - MENU_OP_STICK = 1 << 7, - MENU_OP_UNSTICK = 1 << 8, - MENU_OP_DELETE = 1 << 9, - MENU_OP_DESTROY = 1 << 10, - MENU_OP_WORKSPACES = 1 << 11, - MENU_OP_QUIT = 1 << 12, - MENU_OP_RESTART = 1 << 13, - MENU_OP_ABOVE = 1 << 14, - MENU_OP_NORMAL = 1 << 15, - MENU_OP_CONTEXT_HELP = 1 << 16, - MENU_OP_OTHER = 1 << 17 + MENU_OP_MOVE = 1 << 5, + MENU_OP_RESIZE = 1 << 6, + MENU_OP_SHADE = 1 << 7, + MENU_OP_UNSHADE = 1 << 8, + MENU_OP_STICK = 1 << 9, + MENU_OP_UNSTICK = 1 << 10, + MENU_OP_DELETE = 1 << 11, + MENU_OP_DESTROY = 1 << 12, + MENU_OP_WORKSPACES = 1 << 13, + MENU_OP_QUIT = 1 << 14, + MENU_OP_RESTART = 1 << 15, + MENU_OP_ABOVE = 1 << 16, + MENU_OP_NORMAL = 1 << 17, + MENU_OP_CONTEXT_HELP = 1 << 18, + MENU_OP_OTHER = 1 << 19 } MenuOp; diff --git a/src/moveresize.c b/src/moveresize.c index 8d7ea54d7..b3d18a569 100644 --- a/src/moveresize.c +++ b/src/moveresize.c @@ -46,6 +46,12 @@ #include "event_filter.h" #include "xsync.h" +#define MOVERESIZE_EVENT_MASK \ + PointerMotionMask | \ + ButtonMotionMask | \ + ButtonReleaseMask | \ + LeaveWindowMask + typedef struct _MoveResizeData MoveResizeData; struct _MoveResizeData { @@ -56,12 +62,14 @@ struct _MoveResizeData gboolean move_resized; gboolean released; int button; - int cancel_x, cancel_y; /* for cancellation (either position or size) */ + int cancel_x, cancel_y; + int cancel_w, cancel_h; int cancel_workspace; int mx, my; int ox, oy; + int ow, oh; int oldw, oldh; - int corner; + int handle; Poswin *poswin; }; @@ -174,6 +182,79 @@ clientSetHeight (Client * c, int h) c->height = temp; } +static void +clientMovePointer (DisplayInfo *display_info, gint dx, gint dy, guint repeat) +{ + gint i; + for (i = 0; i < repeat; ++i) + { + XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, dx, dy); + } +} + +static void +clientSetHandle(MoveResizeData *passdata, int handle) +{ + ScreenInfo *screen_info; + DisplayInfo *display_info; + Client *c; + int px, py; + + c = passdata->c; + screen_info = c->screen_info; + display_info = screen_info->display_info; + + switch (handle) + { + case CORNER_BOTTOM_LEFT: + px = frameX(c) + frameLeft(c) / 2; + py = frameY(c) + frameHeight(c) - frameBottom(c) / 2; + break; + case CORNER_BOTTOM_RIGHT: + px = frameX(c) + frameWidth(c) - frameRight(c) / 2; + py = frameY(c) + frameHeight(c) - frameBottom(c) / 2; + break; + case CORNER_TOP_LEFT: + px = frameX(c) + frameLeft(c) / 2; + py = frameY(c); + break; + case CORNER_TOP_RIGHT: + px = frameX(c) + frameWidth(c) - frameRight(c) / 2; + py = frameY(c); + break; + case CORNER_COUNT + SIDE_LEFT: + px = frameX(c) + frameLeft(c) / 2; + py = frameY(c) + frameHeight(c) / 2; + break; + case CORNER_COUNT + SIDE_RIGHT: + px = frameX(c) + frameWidth(c) - frameRight(c) / 2; + py = frameY(c) + frameHeight(c) / 2; + break; + case CORNER_COUNT + SIDE_TOP: + px = frameX(c) + frameWidth(c) / 2; + py = frameY(c); + break; + case CORNER_COUNT + SIDE_BOTTOM: + px = frameX(c) + frameWidth(c) / 2; + py = frameY(c) + frameHeight(c) - frameBottom(c) / 2; + break; + default: + px = frameX(c) + frameWidth(c) / 2; + py = frameY(c) + frameHeight(c) / 2; + break; + } + + XWarpPointer (display_info->dpy, None, screen_info->xroot, 0, 0, 0, 0, px, py); + /* Update internal data */ + passdata->handle = handle; + passdata->mx = px; + passdata->my = py; + passdata->ox = c->x; + passdata->oy = c->y; + passdata->ow = c->width; + passdata->oh = c->height; +} + /* clientConstrainRatio - adjust the given width and height to account for the constraints imposed by size hints @@ -182,7 +263,7 @@ clientSetHeight (Client * c, int h) #define MAKE_MULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) void -clientConstrainRatio (Client * c, int *w, int *h, int corner) +clientConstrainRatio (Client * c, int *w, int *h, int handle) { g_return_if_fail (c != NULL); @@ -201,7 +282,7 @@ clientConstrainRatio (Client * c, int *w, int *h, int corner) maxy = c->size->max_aspect.y; if ((minx * *h > miny * *w) && (miny) && - ((corner == CORNER_COUNT + SIDE_TOP) || (corner == CORNER_COUNT + SIDE_BOTTOM))) + ((handle == CORNER_COUNT + SIDE_TOP) || (handle == CORNER_COUNT + SIDE_BOTTOM))) { /* Change width to match */ delta = MAKE_MULT (minx * *h / miny - *w, xinc); @@ -229,7 +310,7 @@ clientConstrainRatio (Client * c, int *w, int *h, int corner) } if ((maxx * *h < maxy * *w) && (maxx) && - ((corner == CORNER_COUNT + SIDE_LEFT) || (corner == CORNER_COUNT + SIDE_RIGHT))) + ((handle == CORNER_COUNT + SIDE_LEFT) || (handle == CORNER_COUNT + SIDE_RIGHT))) { delta = MAKE_MULT (*w * maxy / maxx - *h, yinc); if (!(c->size->flags & PMaxSize) || @@ -480,117 +561,36 @@ clientMoveEventFilter (XEvent * xevent, gpointer data) if (xevent->type == KeyPress) { + int key_move; + while (XCheckMaskEvent (display_info->dpy, KeyPressMask, xevent)) { /* Update the display time */ myDisplayUpdateCurrentTime (display_info, xevent); } - if ((passdata->use_keys) && !FLAG_TEST_ALL(c->flags, CLIENT_FLAG_MAXIMIZED)) + key_move = 16; + if ((screen_info->params->snap_to_border) || (screen_info->params->snap_to_windows)) { - int key_move = 16; - unsigned int edge; - int direction = 0; - - if ((screen_info->params->snap_to_border) || (screen_info->params->snap_to_windows)) - { - key_move = MAX (16, screen_info->params->snap_width + 1); - } - - if (!passdata->grab && screen_info->params->box_move) - { - myDisplayGrabServer (display_info); - passdata->grab = TRUE; - clientDrawOutline (c); - } - if (screen_info->params->box_move) - { - clientDrawOutline (c); - } - if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_LEFT].keycode) - { - direction = KEY_MOVE_LEFT; - c->x = c->x - key_move; - } - else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_RIGHT].keycode) - { - direction = KEY_MOVE_RIGHT; - c->x = c->x + key_move; - } - else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_UP].keycode) - { - direction = KEY_MOVE_UP; - c->y = c->y - key_move; - } - else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_DOWN].keycode) - { - direction = KEY_MOVE_DOWN; - c->y = c->y + key_move; - } - - clientSnapPosition (c, prev_x, prev_y); - edge = clientConstrainPos (c, FALSE); - if ((edge) && (screen_info->params->wrap_windows)) - { - int maxx, maxy, maxw, maxh; - - maxx = 0; - maxy = 0; - maxw = screen_info->width; - maxh = screen_info->height; - clientMaxSpace (screen_info, &maxx, &maxy, &maxw, &maxh); - - if ((edge & CLIENT_CONSTRAINED_TOP) && (direction == KEY_MOVE_UP)) - { - if (workspaceMove (screen_info, -1, 0, c, xevent->xkey.time)) - { - c->y = maxy + maxh; - } - } - else if ((edge & CLIENT_CONSTRAINED_BOTTOM) && (direction == KEY_MOVE_DOWN)) - { - if (workspaceMove (screen_info, 1, 0, c, xevent->xkey.time)) - { - c->y = maxy + frameTop (c); - } - } - - if ((edge & CLIENT_CONSTRAINED_LEFT) && (direction == KEY_MOVE_LEFT)) - { - if (workspaceMove (screen_info, 0, -1, c, xevent->xkey.time)) - { - c->x = maxx + maxw - frameWidth (c) + frameRight (c); - } - } - else if ((edge & CLIENT_CONSTRAINED_RIGHT) && (direction == KEY_MOVE_RIGHT)) - { - if (workspaceMove (screen_info, 0, 1, c, xevent->xkey.time)) - { - c->x = maxx + frameLeft (c); - } - } - } -#ifdef SHOW_POSITION - if (passdata->poswin) - { - poswinSetPosition (passdata->poswin, c); - } -#endif /* SHOW_POSITION */ - if (screen_info->params->box_move) - { - clientDrawOutline (c); - } - else - { - wc.x = c->x; - wc.y = c->y; - clientConfigure (c, &wc, CWX | CWY, configure_flags); - } + key_move = MAX (key_move, screen_info->params->snap_width + 1); } - } - else if (xevent->type == KeyRelease) - { - if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode) + if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_LEFT].keycode) + { + clientMovePointer (display_info, -1, 0, key_move); + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_RIGHT].keycode) + { + clientMovePointer (display_info, 1, 0, key_move); + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_UP].keycode) + { + clientMovePointer (display_info, 0, -1, key_move); + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_DOWN].keycode) + { + clientMovePointer (display_info, 0, 1, key_move); + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode) { moving = FALSE; passdata->released = passdata->use_keys; @@ -625,25 +625,19 @@ clientMoveEventFilter (XEvent * xevent, gpointer data) passdata->move_resized = TRUE; } } - else if (passdata->use_keys) + else { - if (IsModifierKey (XLookupKeysym (&xevent->xkey, 0))) - { - moving = FALSE; - } + moving = FALSE; } } else if (xevent->type == ButtonRelease) { - if (!passdata->use_keys) - { - moving = FALSE; - passdata->released = (xevent->xbutton.button == passdata->button); - } + moving = FALSE; + passdata->released = passdata->use_keys || (xevent->xbutton.button == passdata->button); } else if (xevent->type == MotionNotify) { - while (XCheckMaskEvent (display_info->dpy, ButtonMotionMask, xevent)) + while (XCheckMaskEvent (display_info->dpy, PointerMotionMask | ButtonMotionMask, xevent)) { /* Update the display time */ myDisplayUpdateCurrentTime (display_info, xevent); @@ -907,31 +901,27 @@ clientMove (Client * c, XEvent * ev) passdata.use_keys = FALSE; passdata.grab = FALSE; passdata.released = FALSE; - passdata.button = ev->xbutton.button; + passdata.button = 0; passdata.is_transient = clientIsValidTransientOrModal (c); passdata.move_resized = FALSE; - if (ev->type == KeyPress) - { - passdata.released = passdata.use_keys = TRUE; - passdata.mx = ev->xkey.x_root; - passdata.my = ev->xkey.y_root; - } - else if (ev->type == ButtonPress) + if (ev && (ev->type == ButtonPress)) { + passdata.button = ev->xbutton.button; passdata.mx = ev->xbutton.x_root; passdata.my = ev->xbutton.y_root; } else { - getMouseXY (screen_info, screen_info->xroot, &passdata.mx, &passdata.my); + clientSetHandle(&passdata, NO_HANDLE); + passdata.released = passdata.use_keys = TRUE; } g1 = myScreenGrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); - g2 = myScreenGrabPointer (screen_info, ButtonMotionMask | ButtonReleaseMask | LeaveWindowMask, + g2 = myScreenGrabPointer (screen_info, MOVERESIZE_EVENT_MASK, myDisplayGetCursorMove (display_info), myDisplayGetCurrentTime (display_info)); - if ((passdata.use_keys && !g1) || (!g2)) + if (!g1 || !g2) { TRACE ("grab failed in clientMove"); @@ -949,7 +939,7 @@ clientMove (Client * c, XEvent * ev) poswinShow (passdata.poswin); #endif /* SHOW_POSITION */ - /* Set window translucent while moving, looks nice */ + /* Set window translucent while moving */ if ((screen_info->params->move_opacity < 100) && !(screen_info->params->box_move) && !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED)) @@ -966,10 +956,6 @@ clientMove (Client * c, XEvent * ev) FLAG_SET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING); TRACE ("entering move loop"); eventFilterPush (display_info->xfilter, clientMoveEventFilter, &passdata); - if (passdata.use_keys) - { - XPutBackEvent (display_info->dpy, ev); - } gtk_main (); eventFilterPop (display_info->xfilter); TRACE ("leaving move loop"); @@ -1019,6 +1005,34 @@ clientMove (Client * c, XEvent * ev) } } +static gboolean +clientChangeHandle(MoveResizeData *passdata, int handle) +{ + ScreenInfo *screen_info; + DisplayInfo *display_info; + Client *c; + Cursor cursor; + gboolean grab; + + c = passdata->c; + screen_info = c->screen_info; + display_info = screen_info->display_info; + + clientSetHandle(passdata, handle); + if ((handle > NO_HANDLE) && (handle <= HANDLES_COUNT)) + { + cursor = myDisplayGetCursorResize (display_info, handle); + } + else + { + cursor = myDisplayGetCursorMove (display_info); + } + grab = myScreenChangeGrabPointer (screen_info, MOVERESIZE_EVENT_MASK, + cursor, myDisplayGetCurrentTime (display_info)); + + return (grab); +} + static void clientResizeConfigure (Client *c, int px, int py, int pw, int ph) { @@ -1112,21 +1126,21 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) cx = frame_x + (frame_width / 2); cy = frame_y + (frame_height / 2); - move_top = ((passdata->corner == CORNER_TOP_RIGHT) - || (passdata->corner == CORNER_TOP_LEFT) - || (passdata->corner == CORNER_COUNT + SIDE_TOP)) ? + move_top = ((passdata->handle == CORNER_TOP_RIGHT) + || (passdata->handle == CORNER_TOP_LEFT) + || (passdata->handle == CORNER_COUNT + SIDE_TOP)) ? 1 : 0; - move_bottom = ((passdata->corner == CORNER_BOTTOM_RIGHT) - || (passdata->corner == CORNER_BOTTOM_LEFT) - || (passdata->corner == CORNER_COUNT + SIDE_BOTTOM)) ? + move_bottom = ((passdata->handle == CORNER_BOTTOM_RIGHT) + || (passdata->handle == CORNER_BOTTOM_LEFT) + || (passdata->handle == CORNER_COUNT + SIDE_BOTTOM)) ? 1 : 0; - move_right = ((passdata->corner == CORNER_TOP_RIGHT) - || (passdata->corner == CORNER_BOTTOM_RIGHT) - || (passdata->corner == CORNER_COUNT + SIDE_RIGHT)) ? + move_right = ((passdata->handle == CORNER_TOP_RIGHT) + || (passdata->handle == CORNER_BOTTOM_RIGHT) + || (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) ? 1 : 0; - move_left = ((passdata->corner == CORNER_TOP_LEFT) - || (passdata->corner == CORNER_BOTTOM_LEFT) - || (passdata->corner == CORNER_COUNT + SIDE_LEFT)) ? + move_left = ((passdata->handle == CORNER_TOP_LEFT) + || (passdata->handle == CORNER_BOTTOM_LEFT) + || (passdata->handle == CORNER_COUNT + SIDE_LEFT)) ? 1 : 0; monitor_nbr = find_monitor_at_point (screen_info->gscr, cx, cy); @@ -1148,92 +1162,75 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) if (xevent->type == KeyPress) { + int key_width_inc, key_height_inc; + while (XCheckMaskEvent (display_info->dpy, KeyPressMask, xevent)) { /* Update the display time */ myDisplayUpdateCurrentTime (display_info, xevent); } - if (passdata->use_keys) - { - int key_width_inc, key_height_inc; - int corner = -1; - - key_width_inc = c->size->width_inc; - key_height_inc = c->size->height_inc; + key_width_inc = c->size->width_inc; + key_height_inc = c->size->height_inc; - if (key_width_inc < 10) - { - key_width_inc = ((int) (10 / key_width_inc)) * key_width_inc; - } - if (key_height_inc < 10) - { - key_height_inc = ((int) (10 / key_height_inc)) * key_height_inc; - } - if (!passdata->grab && screen_info->params->box_resize) - { - myDisplayGrabServer (display_info); - passdata->grab = TRUE; - clientDrawOutline (c); - } - if (screen_info->params->box_resize) - { - clientDrawOutline (c); - } + if (key_width_inc < 10) + { + key_width_inc = ((int) (10 / key_width_inc)) * key_width_inc; + } + if (key_height_inc < 10) + { + key_height_inc = ((int) (10 / key_height_inc)) * key_height_inc; + } - if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED) - && (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_UP].keycode)) - { - c->height = c->height - key_height_inc; - corner = CORNER_COUNT + SIDE_BOTTOM; - } - else if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED) - && (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_DOWN].keycode)) - { - c->height = c->height + key_height_inc; - corner = CORNER_COUNT + SIDE_BOTTOM; - } - else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_LEFT].keycode) + if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_UP].keycode) + { + if ((passdata->handle == CORNER_COUNT + SIDE_BOTTOM) || + (passdata->handle == CORNER_COUNT + SIDE_TOP)) { - c->width = c->width - key_width_inc; - corner = CORNER_COUNT + SIDE_RIGHT; + clientMovePointer (display_info, 0, -1, key_height_inc); } - else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_RIGHT].keycode) + else { - c->width = c->width + key_width_inc; - corner = CORNER_COUNT + SIDE_RIGHT; + clientChangeHandle (passdata, CORNER_COUNT + SIDE_TOP); } - if (corner >= 0) + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_DOWN].keycode) + { + if ((passdata->handle == CORNER_COUNT + SIDE_BOTTOM) || + (passdata->handle == CORNER_COUNT + SIDE_TOP)) { - clientConstrainRatio (c, &c->width, &c->height, corner); + clientMovePointer (display_info, 0, 1, key_height_inc); } - if ((c->x + c->width < disp_x + min_visible) - || (c->x + c->width < screen_info->margins [STRUTS_LEFT] + min_visible)) + else { - c->width = prev_width; + clientChangeHandle (passdata, CORNER_COUNT + SIDE_BOTTOM); } - if ((c->y + c->height < disp_y + min_visible) - || (c->y + c->height < screen_info->margins [STRUTS_TOP] + min_visible)) + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_LEFT].keycode) + { + if ((passdata->handle == CORNER_COUNT + SIDE_LEFT) || + (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) { - c->height = prev_height; + clientMovePointer (display_info, -1, 0, key_width_inc); } - if (passdata->poswin) + else { - poswinSetPosition (passdata->poswin, c); + clientChangeHandle (passdata, CORNER_COUNT + SIDE_LEFT); } - if (screen_info->params->box_resize) + } + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_RIGHT].keycode) + { + if ((passdata->handle == CORNER_COUNT + SIDE_LEFT) || + (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) { - clientDrawOutline (c); + clientMovePointer (display_info, 1, 0, key_width_inc); } else { - clientResizeConfigure (c, prev_x, prev_y, prev_width, prev_height); + clientChangeHandle (passdata, CORNER_COUNT + SIDE_RIGHT); } } - } - else if (xevent->type == KeyRelease) - { - if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode) + else if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode) { resizing = FALSE; passdata->released = passdata->use_keys; @@ -1244,16 +1241,10 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) } /* restore the pre-resize position & size */ - if (move_left) - { - c->x += c->width - passdata->cancel_x; - } - if (move_top) - { - c->y += c->height - passdata->cancel_y; - } - c->width = passdata->cancel_x; - c->height = passdata->cancel_y; + c->x = passdata->cancel_x; + c->y = passdata->cancel_y; + c->width = passdata->cancel_w; + c->height = passdata->cancel_h; if (screen_info->params->box_resize) { clientDrawOutline (c); @@ -1263,12 +1254,9 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) clientResizeConfigure (c, prev_x, prev_y, prev_width, prev_height); } } - else if (passdata->use_keys) + else { - if (IsModifierKey (XLookupKeysym (&xevent->xkey, 0))) - { - resizing = FALSE; - } + resizing = FALSE; } } else if (xevent->type == MotionNotify) @@ -1298,24 +1286,24 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) if (move_left) { - c->width = passdata->ox - (xevent->xmotion.x_root - passdata->mx); + c->width = passdata->ow - (xevent->xmotion.x_root - passdata->mx); } else if (move_right) { - c->width = passdata->ox + (xevent->xmotion.x_root - passdata->mx); + c->width = passdata->ow + (xevent->xmotion.x_root - passdata->mx); } if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED)) { if (move_top) { - c->height = passdata->oy - (xevent->xmotion.y_root - passdata->my); + c->height = passdata->oh - (xevent->xmotion.y_root - passdata->my); } else if (move_bottom) { - c->height = passdata->oy + (xevent->xmotion.y_root - passdata->my); + c->height = passdata->oh + (xevent->xmotion.y_root - passdata->my); } } - clientConstrainRatio (c, &c->width, &c->height, passdata->corner); + clientConstrainRatio (c, &c->width, &c->height, passdata->handle); clientSetWidth (c, c->width); if (move_left) @@ -1393,11 +1381,8 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) } else if (xevent->type == ButtonRelease) { - if (!passdata->use_keys) - { - resizing = FALSE; - passdata->released = (xevent->xbutton.button == passdata->button); - } + resizing = FALSE; + passdata->released = (passdata->use_keys || (xevent->xbutton.button == passdata->button)); } else if ((xevent->type == UnmapNotify) && (xevent->xunmap.window == c->window)) { @@ -1424,13 +1409,14 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) } void -clientResize (Client * c, int corner, XEvent * ev) +clientResize (Client * c, int handle, XEvent * ev) { ScreenInfo *screen_info; DisplayInfo *display_info; XWindowChanges wc; MoveResizeData passdata; int w_orig, h_orig; + Cursor cursor; gboolean g1, g2; g_return_if_fail (c != NULL); @@ -1447,38 +1433,43 @@ clientResize (Client * c, int corner, XEvent * ev) } passdata.c = c; - passdata.cancel_x = passdata.ox = c->width; - passdata.cancel_y = passdata.oy = c->height; + passdata.cancel_x = passdata.ox = c->x; + passdata.cancel_y = passdata.oy = c->y; + passdata.cancel_w = passdata.ow = c->width; + passdata.cancel_h = passdata.oh = c->height; passdata.use_keys = FALSE; passdata.grab = FALSE; passdata.released = FALSE; - passdata.button = ev->xbutton.button; - passdata.corner = corner; + passdata.button = 0; + passdata.handle = handle; w_orig = c->width; h_orig = c->height; - if (ev->type == KeyPress) + if (ev && (ev->type == ButtonPress)) + { + passdata.button = ev->xbutton.button; + passdata.mx = ev->xbutton.x_root; + passdata.my = ev->xbutton.y_root; + } + else { + clientSetHandle (&passdata, handle); passdata.released = passdata.use_keys = TRUE; - passdata.mx = ev->xkey.x_root; - passdata.my = ev->xkey.y_root; } - else if (ev->type == ButtonPress) + if ((handle > NO_HANDLE) && (handle <= HANDLES_COUNT)) { - passdata.mx = ev->xbutton.x_root; - passdata.my = ev->xbutton.y_root; + cursor = myDisplayGetCursorResize (display_info, passdata.handle); } else { - getMouseXY (screen_info, screen_info->xroot, &passdata.mx, &passdata.my); + cursor = myDisplayGetCursorMove (display_info); } g1 = myScreenGrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); - g2 = myScreenGrabPointer (screen_info, ButtonMotionMask | ButtonReleaseMask | LeaveWindowMask, - myDisplayGetCursorResize(display_info, passdata.corner), - myDisplayGetCurrentTime (display_info)); + g2 = myScreenGrabPointer (screen_info, MOVERESIZE_EVENT_MASK, + cursor, myDisplayGetCurrentTime (display_info)); - if ((passdata.use_keys && !g1) || (!g2)) + if (!g1 || !g2) { TRACE ("grab failed in clientResize"); @@ -1503,7 +1494,7 @@ clientResize (Client * c, int corner, XEvent * ev) clientXSyncEnable (c); #endif /* HAVE_XSYNC */ - /* Set window translucent while resizing, doesn't looks too nice :( */ + /* Set window translucent while resizing */ if ((screen_info->params->resize_opacity < 100) && !(screen_info->params->box_resize) && !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED)) @@ -1514,10 +1505,6 @@ clientResize (Client * c, int corner, XEvent * ev) FLAG_SET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING); TRACE ("entering resize loop"); eventFilterPush (display_info->xfilter, clientResizeEventFilter, &passdata); - if (passdata.use_keys) - { - XPutBackEvent (display_info->dpy, ev); - } gtk_main (); eventFilterPop (display_info->xfilter); TRACE ("leaving resize loop"); diff --git a/src/netwm.c b/src/netwm.c index 25191e389..1bb31d6e1 100644 --- a/src/netwm.c +++ b/src/netwm.c @@ -597,8 +597,8 @@ clientNetMoveResize (Client * c, XClientMessageEvent * ev) } else { - g_warning ("Could not determine the mouse button used"); - return; + /* Fallback */ + button = Button1; } } @@ -1126,7 +1126,7 @@ clientSetNetActions (Client * c) { ScreenInfo *screen_info; DisplayInfo *display_info; - Atom atoms[12]; + Atom atoms[16]; int i; g_return_if_fail (c != NULL); @@ -1137,11 +1137,29 @@ clientSetNetActions (Client * c) i = 0; atoms[i++] = display_info->atoms[NET_WM_ACTION_CLOSE]; - atoms[i++] = display_info->atoms[NET_WM_ACTION_FULLSCREEN]; - if (CLIENT_CAN_MAXIMIZE_WINDOW (c)) + atoms[i++] = display_info->atoms[NET_WM_ACTION_ABOVE]; + if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE)) { - atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_HORZ]; - atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_VERT]; + atoms[i++] = display_info->atoms[NET_WM_ACTION_FULLSCREEN]; + if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE)) + { + atoms[i++] = display_info->atoms[NET_WM_ACTION_MOVE]; + } + if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE) && + !((FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED) + && (screen_info->params->borderless_maximize)))) + { + atoms[i++] = display_info->atoms[NET_WM_ACTION_RESIZE]; + } + if (CLIENT_CAN_MAXIMIZE_WINDOW (c)) + { + atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_HORZ]; + atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_VERT]; + } + if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER)) + { + atoms[i++] = display_info->atoms[NET_WM_ACTION_SHADE]; + } } if (CLIENT_CAN_HIDE_WINDOW (c)) { @@ -1152,10 +1170,6 @@ clientSetNetActions (Client * c) atoms[i++] = display_info->atoms[NET_WM_ACTION_CHANGE_DESKTOP]; atoms[i++] = display_info->atoms[NET_WM_ACTION_STICK]; } - if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER)) - { - atoms[i++] = display_info->atoms[NET_WM_ACTION_SHADE]; - } XChangeProperty (clientGetXDisplay (c), c->window, display_info->atoms[NET_WM_ALLOWED_ACTIONS], XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, i); } diff --git a/src/screen.c b/src/screen.c index 88310dce1..eb2d94ead 100644 --- a/src/screen.c +++ b/src/screen.c @@ -438,6 +438,24 @@ myScreenGrabPointer (ScreenInfo *screen_info, unsigned int event_mask, Cursor cu return grab; } +gboolean +myScreenChangeGrabPointer (ScreenInfo *screen_info, unsigned int event_mask, Cursor cursor, Time time) +{ + gboolean grab; + + g_return_val_if_fail (screen_info, FALSE); + TRACE ("entering myScreenGrabPointer"); + + grab = FALSE; + if (screen_info->pointer_grabs > 0) + { + grab = (XChangeActivePointerGrab (myScreenGetXDisplay (screen_info), + event_mask, cursor, time) == GrabSuccess); + } + + return grab; +} + unsigned int myScreenUngrabKeyboard (ScreenInfo *screen_info, Time time) { diff --git a/src/screen.h b/src/screen.h index 8df75e693..122af074d 100644 --- a/src/screen.h +++ b/src/screen.h @@ -180,6 +180,10 @@ gboolean myScreenGrabPointer (ScreenInfo *, unsigned int, Cursor, Time); +gboolean myScreenChangeGrabPointer (ScreenInfo *, + unsigned int, + Cursor, + Time); unsigned int myScreenUngrabKeyboard (ScreenInfo *, Time); unsigned int myScreenUngrabPointer (ScreenInfo *, |