From 47ec274760cff6b331c02d6e46fa924a8d536fc8 Mon Sep 17 00:00:00 2001 From: Doug Torrance Date: Thu, 25 Sep 2014 16:02:51 -0500 Subject: [PATCH] wmaker: Add more directions for window snapping. This patch adds the ability to "snap" a window to the top, bottom, or any of the four corners of the screen. It uses three new helper functions, drawSnapFrame, getSnapDirection, and doSnap, to reduce code duplication and increase readability. It also updates NEWS to indicate the additional directions. Signed-off-by: Carlos R. Mafra --- NEWS | 4 +- src/moveres.c | 200 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 148 insertions(+), 56 deletions(-) diff --git a/NEWS b/NEWS index ac03d901..889d019f 100644 --- a/NEWS +++ b/NEWS @@ -7,8 +7,8 @@ NEWS for veteran Window Maker users Window snapping --------------- -You can now "snap" a window, i.e., maximize it to the left or right half of the -screen, by dragging it to that side. It is enabled by setting +You can now "snap" a window, i.e., maximize it to a side or corner of the +screen, by dragging it to that side or corner. It is enabled by setting "WindowSnapping = YES" in ~/GNUstep/Defaults/WindowMaker or selecting "Enable window snapping" under "Expert User Preferences" in WPrefs.app. diff --git a/src/moveres.c b/src/moveres.c index c77a1058..27f6ce1d 100644 --- a/src/moveres.c +++ b/src/moveres.c @@ -589,7 +589,17 @@ typedef struct { int omouseX, omouseY; /* old mouse position */ int mouseX, mouseY; /* last known position of the pointer */ - enum {SNAP_NONE, SNAP_LEFT, SNAP_RIGHT} snap; + enum { + SNAP_NONE, + SNAP_LEFT, + SNAP_RIGHT, + SNAP_TOP, + SNAP_BOTTOM, + SNAP_TOPLEFT, + SNAP_TOPRIGHT, + SNAP_BOTTOMLEFT, + SNAP_BOTTOMRIGHT + } snap; } MoveData; #define WTOP(w) (w)->frame_y @@ -1188,6 +1198,118 @@ updateWindowPosition(WWindow * wwin, MoveData * data, Bool doResistance, data->realY = newY; } +static void draw_snap_frame(WWindow *wwin, int direction) +{ + WScreen *scr; + + scr = wwin->screen_ptr; + + switch (direction) { + case SNAP_LEFT: + drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height); + break; + + case SNAP_RIGHT: + drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, scr->scr_height); + break; + + case SNAP_TOP: + drawTransparentFrame(wwin, 0, 0, scr->scr_width, scr->scr_height/2); + break; + + case SNAP_BOTTOM: + drawTransparentFrame(wwin, 0, scr->scr_height/2, scr->scr_width, scr->scr_height/2); + break; + + case SNAP_TOPLEFT: + drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height/2); + break; + + case SNAP_TOPRIGHT: + drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, scr->scr_height/2); + break; + + case SNAP_BOTTOMLEFT: + drawTransparentFrame(wwin, 0, scr->scr_height/2, scr->scr_width/2, scr->scr_height/2); + break; + + case SNAP_BOTTOMRIGHT: + drawTransparentFrame(wwin, scr->scr_width/2, scr->scr_height/2, + scr->scr_width/2, scr->scr_height/2); + break; + } +} + +static int get_snap_direction(WScreen *scr, int x, int y) +{ + if (x < 1) { + if (y < 1) + return SNAP_TOPLEFT; + if (y > scr->scr_height - 2) + return SNAP_BOTTOMLEFT; + return SNAP_LEFT; + } + if (x > scr->scr_width - 2) { + if (y < 1) + return SNAP_TOPRIGHT; + if (y > scr->scr_height - 2) + return SNAP_BOTTOMRIGHT; + return SNAP_RIGHT; + } + if (y < 1) + return SNAP_TOP; + if (y > scr->scr_height - 2) + return SNAP_BOTTOM; + return SNAP_NONE; +} + +static void do_snap(WWindow *wwin, MoveData *data, Bool opaqueMove) +{ + int directions; + WScreen *scr; + + directions = 0; + scr = wwin->screen_ptr; + + /* erase frames */ + if (!opaqueMove) + drawFrames(wwin, scr->selected_windows, data->realX - wwin->frame_x, data->realY - wwin->frame_y); + draw_snap_frame(wwin, data->snap); + + switch (data->snap) { + case SNAP_NONE: + return; + case SNAP_LEFT: + directions = MAX_VERTICAL | MAX_LEFTHALF; + break; + case SNAP_RIGHT: + directions = MAX_VERTICAL | MAX_RIGHTHALF; + break; + case SNAP_TOP: + directions = MAX_HORIZONTAL | MAX_TOPHALF; + break; + case SNAP_BOTTOM: + directions = MAX_HORIZONTAL | MAX_BOTTOMHALF; + break; + case SNAP_TOPLEFT: + directions = MAX_TOPHALF | MAX_LEFTHALF; + break; + case SNAP_TOPRIGHT: + directions = MAX_TOPHALF | MAX_RIGHTHALF; + break; + case SNAP_BOTTOMLEFT: + directions = MAX_BOTTOMHALF | MAX_LEFTHALF; + break; + case SNAP_BOTTOMRIGHT: + directions = MAX_BOTTOMHALF | MAX_RIGHTHALF; + break; + } + + if (directions) + handleMaximize(wwin, directions); + data->snap = SNAP_NONE; +} + #define _KS KEY_CONTROL_WINDOW_WEIGHT #define MOVABLE_BIT 0x01 @@ -1647,46 +1769,34 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev) case MotionNotify: if (IS_RESIZABLE(wwin) && wPreferences.window_snapping && wPreferences.no_autowrap) { - if (moveData.snap == SNAP_LEFT && moveData.mouseX > 1) { - moveData.snap = SNAP_NONE; - drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height); - } - if (moveData.snap == SNAP_RIGHT && moveData.mouseX < scr->scr_width - 2) { - moveData.snap = SNAP_NONE; - drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, - scr->scr_height); - } - if (moveData.snap == SNAP_NONE) { - if (moveData.mouseX <= 1) { - moveData.snap = SNAP_LEFT; - drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, - scr->scr_height); - } - if (moveData.mouseX >= scr->scr_width - 2) { - moveData.snap = SNAP_RIGHT; - drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, - scr->scr_height); - } + int snap_direction; + + snap_direction = get_snap_direction(scr, moveData.mouseX, moveData.mouseY); + + if (moveData.snap != snap_direction) { + /* erase old frame */ + if (moveData.snap) + draw_snap_frame(wwin, moveData.snap); + /* draw new frame */ + if (snap_direction) + draw_snap_frame(wwin, snap_direction); + moveData.snap = snap_direction; } } if (started) { - if (moveData.snap == SNAP_LEFT) - drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height); - if (moveData.snap == SNAP_RIGHT) - drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, - scr->scr_height); + /* erase snap frame */ + if (moveData.snap) + draw_snap_frame(wwin, moveData.snap); updateWindowPosition(wwin, &moveData, scr->selected_windows == NULL && wPreferences.edge_resistance > 0, opaqueMove, event.xmotion.x_root, event.xmotion.y_root); - if (moveData.snap == SNAP_LEFT) - drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height); - if (moveData.snap == SNAP_RIGHT) - drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, - scr->scr_height); + /* redraw snap frame */ + if (moveData.snap) + draw_snap_frame(wwin, moveData.snap); if (!warped && !wPreferences.no_autowrap) { int oldWorkspace = w_global.workspace.current; @@ -1773,30 +1883,12 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev) if (event.xbutton.button != ev->xbutton.button) break; - if (moveData.snap != SNAP_NONE) { - if (moveData.snap == SNAP_LEFT) { - /* erase frames */ - if (!opaqueMove) - drawFrames(wwin, scr->selected_windows, - moveData.realX - wwin->frame_x, - moveData.realY - wwin->frame_y); - drawTransparentFrame(wwin, 0, 0, scr->scr_width/2, scr->scr_height); - handleMaximize(wwin, MAX_VERTICAL | MAX_LEFTHALF); - } - if (moveData.snap == SNAP_RIGHT) { - /* erase frames */ - if (!opaqueMove) - drawFrames(wwin, scr->selected_windows, - moveData.realX - wwin->frame_x, - moveData.realY - wwin->frame_y); - drawTransparentFrame(wwin, scr->scr_width/2, 0, scr->scr_width/2, - scr->scr_height); - handleMaximize(wwin, MAX_VERTICAL | MAX_RIGHTHALF); - } - moveData.snap = SNAP_NONE; - } else if (started) { + if (started) { XEvent e; - if (!opaqueMove) { + + if (moveData.snap) + do_snap(wwin, &moveData, opaqueMove); + else if (!opaqueMove) { drawFrames(wwin, scr->selected_windows, moveData.realX - wwin->frame_x, moveData.realY - wwin->frame_y); XSync(dpy, 0); -- 2.11.4.GIT