1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00

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 <crmafra@gmail.com>
This commit is contained in:
Doug Torrance
2014-09-25 16:02:51 -05:00
committed by Carlos R. Mafra
parent da940a1e4d
commit 47ec274760
2 changed files with 148 additions and 56 deletions

4
NEWS
View File

@@ -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.

View File

@@ -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);