diff --git a/src/display.c b/src/display.c index a1cfb02..8863679 100644 --- a/src/display.c +++ b/src/display.c @@ -406,6 +406,9 @@ myDisplayCreateCursor (DisplayInfo *display) XCreateFontCursor (display->dpy, XC_top_side); display->resize_cursor[CORNER_COUNT + SIDE_BOTTOM] = XCreateFontCursor (display->dpy, XC_bottom_side); + display->resize_cursor[CORNER_COUNT + TWM_GESTURE] = +// XCreateFontCursor (display->dpy, XC_dotbox); // XC_sizing); + XCreateFontCursor (display->dpy, XC_crosshair); } void @@ -455,7 +458,7 @@ Cursor myDisplayGetCursorResize (DisplayInfo *display, guint list) { g_return_val_if_fail (display, None); - g_return_val_if_fail (list < 8, None); + g_return_val_if_fail (list <= HANDLES_COUNT, None); return display->resize_cursor [list]; } diff --git a/src/display.h b/src/display.h index a2f8a9a..a5e7213 100644 --- a/src/display.h +++ b/src/display.h @@ -111,6 +111,7 @@ enum SIDE_RIGHT, SIDE_TOP, SIDE_BOTTOM, + TWM_GESTURE, SIDE_COUNT }; #define NO_HANDLE -1 diff --git a/src/events.c b/src/events.c index 50303b0..2e6cb4a 100644 --- a/src/events.c +++ b/src/events.c @@ -772,6 +772,7 @@ static void titleButton (Client * c, guint state, XButtonEvent * ev) { ScreenInfo *screen_info; + int part; g_return_if_fail (c != NULL); g_return_if_fail (ev != NULL); @@ -791,10 +792,16 @@ titleButton (Client * c, guint state, XButtonEvent * ev) { XfwmButtonClickType tclick; + if (!(c->type & WINDOW_TYPE_DONT_FOCUS)) + { + clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG); + } + clientRaise (c, None); + tclick = typeOfClick (screen_info, c->window, (XEvent *) ev, FALSE); if (tclick == XFWM_BUTTON_DRAG) { - clientMove (c, (XEvent *) ev); + clientResize (c, CORNER_COUNT + TWM_GESTURE, (XEvent *) ev); } else if (tclick != XFWM_BUTTON_UNDEFINED) { diff --git a/src/moveresize.c b/src/moveresize.c index 411520d..3eca810 100644 --- a/src/moveresize.c +++ b/src/moveresize.c @@ -73,6 +73,7 @@ struct _MoveResizeData gboolean is_transient; gboolean move_resized; gboolean released; + gboolean twm_gesture; guint button; gint cancel_x, cancel_y; gint cancel_w, cancel_h; @@ -1380,13 +1381,16 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) ScreenInfo *screen_info; DisplayInfo *display_info; Client *c; + Cursor cursor; GdkRectangle rect; MoveResizeData *passdata; eventFilterStatus status; int prev_width, prev_height; int cx, cy; - int move_top, move_bottom, move_left, move_right; +// int move_top, move_bottom, move_left, move_right; + int hmode, vmode; gboolean resizing; + gboolean newcursor; int right_edge; /* -Cliff */ int bottom_edge; /* -Cliff */ @@ -1403,26 +1407,32 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) * we use XFWM_FLAG_MOVING_RESIZING for that. */ resizing = FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING); + newcursor = FALSE; cx = frameExtentX (c) + (frameExtentWidth (c) / 2); cy = frameExtentY (c) + (frameExtentHeight (c) / 2); - move_top = ((passdata->handle == CORNER_TOP_RIGHT) + if ((passdata->handle == CORNER_TOP_RIGHT) || (passdata->handle == CORNER_TOP_LEFT) - || (passdata->handle == CORNER_COUNT + SIDE_TOP)) ? - 1 : 0; - move_bottom = ((passdata->handle == CORNER_BOTTOM_RIGHT) + || (passdata->handle == CORNER_COUNT + SIDE_TOP)) + vmode = SIDE_TOP; + else if ((passdata->handle == CORNER_BOTTOM_RIGHT) || (passdata->handle == CORNER_BOTTOM_LEFT) - || (passdata->handle == CORNER_COUNT + SIDE_BOTTOM)) ? - 1 : 0; - move_right = ((passdata->handle == CORNER_TOP_RIGHT) + || (passdata->handle == CORNER_COUNT + SIDE_BOTTOM)) + vmode = SIDE_BOTTOM; + else + vmode = NO_HANDLE; + + if ((passdata->handle == CORNER_TOP_RIGHT) || (passdata->handle == CORNER_BOTTOM_RIGHT) - || (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) ? - 1 : 0; - move_left = ((passdata->handle == CORNER_TOP_LEFT) + || (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) + hmode = SIDE_RIGHT; + else if ((passdata->handle == CORNER_TOP_LEFT) || (passdata->handle == CORNER_BOTTOM_LEFT) - || (passdata->handle == CORNER_COUNT + SIDE_LEFT)) ? - 1 : 0; + || (passdata->handle == CORNER_COUNT + SIDE_LEFT)) + hmode = SIDE_LEFT; + else + hmode = NO_HANDLE; myScreenFindMonitorAtPoint (screen_info, cx, cy, &rect); @@ -1566,7 +1576,42 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) right_edge = c->x + c->width; bottom_edge = c->y + c->height; - if (move_left) + if ((hmode == SIDE_LEFT || (hmode == NO_HANDLE && passdata->twm_gesture)) + && xevent->xmotion.x_root >= c->x + c->width + frameExtentRight (c) - 1) + { + /* when crossing the right edge while in left resize mode, flip the mode to right resize */ + hmode = SIDE_RIGHT; + switch (passdata->handle) + { + case CORNER_TOP_LEFT: case CORNER_COUNT + SIDE_TOP: passdata->handle = CORNER_TOP_RIGHT; break; + case CORNER_BOTTOM_LEFT: case CORNER_COUNT + SIDE_BOTTOM: passdata->handle = CORNER_BOTTOM_RIGHT; break; + case CORNER_COUNT + SIDE_LEFT: case CORNER_COUNT + TWM_GESTURE: passdata->handle = CORNER_COUNT + SIDE_RIGHT; break; + } + c->x = passdata->cancel_x; + c->width = passdata->cancel_w; + passdata->mx = c->x + c->width + frameExtentRight (c) - 1; + newcursor = TRUE; + } + else if ((hmode == SIDE_RIGHT || (hmode == NO_HANDLE && passdata->twm_gesture)) + && xevent->xmotion.x_root <= c->x - frameExtentLeft(c)) + { + /* when crossing the left edge while in right resize mode, flip the mode to left resize */ + hmode = SIDE_LEFT; + switch (passdata->handle) + { + case CORNER_TOP_RIGHT: case CORNER_COUNT + SIDE_TOP: passdata->handle = CORNER_TOP_LEFT; break; + case CORNER_BOTTOM_RIGHT: case CORNER_COUNT + SIDE_BOTTOM: passdata->handle = CORNER_BOTTOM_LEFT; break; + case CORNER_COUNT + SIDE_RIGHT: case CORNER_COUNT + TWM_GESTURE: passdata->handle = CORNER_COUNT + SIDE_LEFT; break; + } + c->x = passdata->cancel_x; + c->width = passdata->cancel_w; + passdata->oldw = c->width; + right_edge = c->x + c->width; + passdata->mx = passdata->ox - frameExtentLeft(c); + newcursor = TRUE; + } + + if (hmode == SIDE_LEFT) { c->width = passdata->ow - (xevent->xmotion.x_root - passdata->mx); c->x = c->x - (c->width - passdata->oldw); @@ -1575,7 +1620,7 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) c->x = clientFindClosestEdgeX (c, c->x - frameExtentLeft (c)) + frameExtentLeft (c); c->width = right_edge - c->x; } - else if (move_right) + else if (hmode == SIDE_RIGHT) { c->width = passdata->ow + (xevent->xmotion.x_root - passdata->mx); @@ -1585,7 +1630,42 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) } if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED)) { - if (move_top) + if ((vmode == SIDE_TOP || (vmode == NO_HANDLE && passdata->twm_gesture)) + && xevent->xmotion.y_root >= c->y + c->height + frameExtentBottom (c) - 1) + { + /* when crossing the bottom edge while in top resize mode, flip the mode to bottom resize */ + vmode = SIDE_BOTTOM; + switch (passdata->handle) + { + case CORNER_TOP_LEFT: case CORNER_COUNT + SIDE_LEFT: passdata->handle = CORNER_BOTTOM_LEFT; break; + case CORNER_TOP_RIGHT: case CORNER_COUNT + SIDE_RIGHT: passdata->handle = CORNER_BOTTOM_RIGHT; break; + case CORNER_COUNT + SIDE_TOP: case CORNER_COUNT + TWM_GESTURE: passdata->handle = CORNER_COUNT + SIDE_BOTTOM; break; + } + c->y = passdata->cancel_y; + c->height = passdata->cancel_h; + passdata->my = c->y + c->height + frameExtentBottom (c) - 1; + newcursor = TRUE; + } + else if ((vmode == SIDE_BOTTOM || (vmode == NO_HANDLE && passdata->twm_gesture)) + && xevent->xmotion.y_root <= c->y - frameExtentTop(c)) + { + /* when crossing the top edge while in bottom resize mode, flip the mode to top resize */ + vmode = SIDE_TOP; + switch (passdata->handle) + { + case CORNER_BOTTOM_LEFT: case CORNER_COUNT + SIDE_LEFT: passdata->handle = CORNER_TOP_LEFT; break; + case CORNER_BOTTOM_RIGHT: case CORNER_COUNT + SIDE_RIGHT: passdata->handle = CORNER_TOP_RIGHT; break; + case CORNER_COUNT + SIDE_BOTTOM: case CORNER_COUNT + TWM_GESTURE: passdata->handle = CORNER_COUNT + SIDE_TOP; break; + } + c->y = passdata->cancel_y; + c->height = passdata->cancel_h; + passdata->oldh = c->height; + bottom_edge = c->y + c->height; + passdata->my = passdata->oy - frameExtentTop(c); + newcursor = TRUE; + } + + if (vmode == SIDE_TOP) { c->height = passdata->oh - (xevent->xmotion.y_root - passdata->my); c->y = c->y - (c->height - passdata->oldh); @@ -1594,7 +1674,7 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) c->y = clientFindClosestEdgeY (c, c->y - frameExtentTop (c)) + frameExtentTop (c); c->height = bottom_edge - c->y; } - else if (move_bottom) + else if (vmode == SIDE_BOTTOM) { c->height = passdata->oh + (xevent->xmotion.y_root - passdata->my); @@ -1614,17 +1694,22 @@ clientResizeEventFilter (XEvent * xevent, gpointer data) clientConstrainRatio (c, passdata->handle); c->width = clientCheckWidth (c, c->width, FALSE); - if (move_left) + if (hmode == SIDE_LEFT) { c->x = right_edge - c->width; } c->height = clientCheckHeight (c, c->height, FALSE); - if (move_top && !FLAG_TEST (c->flags, CLIENT_FLAG_SHADED)) + if (vmode == SIDE_TOP && !FLAG_TEST (c->flags, CLIENT_FLAG_SHADED)) { c->y = bottom_edge - c->height; } + if (newcursor) + { + cursor = myDisplayGetCursorResize (display_info, passdata->handle); + myScreenChangeGrabPointer (screen_info, MOVERESIZE_EVENT_MASK, cursor, myDisplayGetCurrentTime (display_info)); + } if (passdata->poswin) { poswinSetPosition (passdata->poswin, c); @@ -1727,6 +1812,7 @@ clientResize (Client * c, int handle, XEvent * ev) passdata.use_keys = FALSE; passdata.grab = FALSE; passdata.released = FALSE; + passdata.twm_gesture = (handle == CORNER_COUNT + TWM_GESTURE ? TRUE : FALSE); passdata.button = AnyButton; passdata.handle = handle; passdata.wireframe = NULL;