This patch adds the ability to "snap" a window to one side of the screen by
dragging it to that side. It is enabled by setting WindowSnapping = "YES" in
~/GNUstep/Defaults/WindowMaker.
Note that window snapping is automatically disabled if DontLinkWorkspaces =
"NO", as this feature also involves dragging a window to one side of the
screen.
---
src/WindowMaker.h | 1 +
src/defaults.c | 2 ++
src/moveres.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/src/WindowMaker.h b/src/WindowMaker.h
index 53d2eaf..a93a64d 100644
--- a/src/WindowMaker.h
+++ b/src/WindowMaker.h
@@ -352,6 +352,7 @@ extern struct WPreferences {
char no_dithering; /* use dithering or not */
char no_animations; /* enable/disable animations */
char no_autowrap; /* wrap workspace when window is moved
to the edge */
+ char window_snapping; /* enable window snapping */
char highlight_active_app; /* show the focused app by highlighting
its icon */
char auto_arrange_icons; /* automagically arrange icons */
diff --git a/src/defaults.c b/src/defaults.c
index 72c8b6f..7349443 100644
--- a/src/defaults.c
+++ b/src/defaults.c
@@ -450,6 +450,8 @@ WDefaultEntry optionList[] = {
&wPreferences.no_animations, getBool, NULL, NULL, NULL},
{"DontLinkWorkspaces", "NO", NULL,
&wPreferences.no_autowrap, getBool, NULL, NULL, NULL},
+ {"WindowSnapping", "NO", NULL,
+ &wPreferences.window_snapping, getBool, NULL, NULL, NULL},
{"HighlightActiveApp", "YES", NULL,
&wPreferences.highlight_active_app, getBool, NULL, NULL, NULL},
{"AutoArrangeIcons", "NO", NULL,
diff --git a/src/moveres.c b/src/moveres.c
index c88875b..6899a86 100644
--- a/src/moveres.c
+++ b/src/moveres.c
@@ -588,6 +588,8 @@ typedef struct {
int calcX, calcY; /* calculated position of window */
int omouseX, omouseY; /* old mouse position */
int mouseX, mouseY; /* last known position of the pointer */
+
+ enum {SNAP_NONE, SNAP_LEFT, SNAP_RIGHT} snap;
} MoveData;
#define WTOP(w) (w)->frame_y
@@ -829,6 +831,8 @@ static void initMoveData(WWindow * wwin, MoveData * data)
data->winWidth = wwin->frame->core->width +
(HAS_BORDER_WITH_SELECT(wwin) ? 2 * wwin->screen_ptr->frame_border_width : 0);
data->winHeight = wwin->frame->core->height +
(HAS_BORDER_WITH_SELECT(wwin) ? 2 * wwin->screen_ptr->frame_border_width : 0);
+
+ data->snap = SNAP_NONE;
}
static Bool checkWorkspaceChange(WWindow * wwin, MoveData * data, Bool
opaqueMove)
@@ -1642,12 +1646,48 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
break;
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);
+ }
+ }
+ }
+
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);
+
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);
+
if (!warped && !wPreferences.no_autowrap) {
int oldWorkspace =
w_global.workspace.current;
@@ -1703,6 +1743,7 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
showPosition(wwin,
moveData.realX, moveData.realY);
}
}
+
break;
case ButtonPress:
@@ -1712,7 +1753,28 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
if (event.xbutton.button != ev->xbutton.button)
break;
- if (started) {
+ 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) {
XEvent e;
if (!opaqueMove) {
drawFrames(wwin, scr->selected_windows,
--
1.9.1
--
To unsubscribe, send mail to [email protected].