From d20afb197384ca8fdd3b9873a74fb856f0a8abf7 Mon Sep 17 00:00:00 2001 From: Simone Vellei Date: Sun, 11 Aug 2013 16:27:22 +0200 Subject: Support for window snapping to screen border and other windows. Turn on with -s snap-margin. Contributed by Simone Vellei . Committed with small changes. --- TODO | 2 - config.h | 3 ++ mcwm.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- mcwm.man | 18 +++++-- 4 files changed, 186 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index f85cb77..0bd7a0f 100644 --- a/TODO +++ b/TODO @@ -147,8 +147,6 @@ Idea from Christian Neukirchen. -* Snap to border and screen edge, which favours the edge. - * Gaps on borders for docks, status windows et cetera. Keep space reserved for Conky, dzen2 et cetera. diff --git a/config.h b/config.h index 0bfb3c3..0129989 100644 --- a/config.h +++ b/config.h @@ -61,6 +61,9 @@ /* Default width of border window, in pixels. Used unless -b width. */ #define BORDERWIDTH 1 +/* Default snap margin in pixels. Used unless -s width. */ +#define SNAPMARGIN 0 + /* * Keysym codes for window operations. Look in X11/keysymdefs.h for * actual symbols. Use XK_VoidSymbol to disable a function. diff --git a/mcwm.c b/mcwm.c index acb26af..0d916e5 100644 --- a/mcwm.c +++ b/mcwm.c @@ -7,7 +7,7 @@ * MC, mc at the domain hack.org * http://hack.org/mc/ * - * Copyright (c) 2010, 2011, 2012 Michael Cardell Widerkrantz, mc at + * Copyright (c) 2010, 2011, 2012, 2013 Michael Cardell Widerkrantz, mc at * the domain hack.org. * * Permission to use, copy, modify, and distribute this software for any @@ -22,6 +22,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define _GNU_SOURCE #include #include #include @@ -278,6 +279,7 @@ struct modkeycodes struct conf { int borderwidth; /* Do we draw borders? If so, how large? */ + int snapmargin; /* Do we have snap margin? If so, how large? */ char *terminal; /* Path to terminal to start. */ uint32_t focuscol; /* Focused border colour. */ uint32_t unfocuscol; /* Unfocused border colour. */ @@ -345,6 +347,7 @@ static void moveresize(xcb_drawable_t win, uint16_t x, uint16_t y, uint16_t width, uint16_t height); static void resize(xcb_drawable_t win, uint16_t width, uint16_t height); static void resizestep(struct client *client, char direction); +void snapwindow(struct client *client, int snap_mode); static void mousemove(struct client *client, int rel_x, int rel_y); static void mouseresize(struct client *client, int rel_x, int rel_y); static void movestep(struct client *client, char direction); @@ -2349,7 +2352,7 @@ void resizestep(struct client *client, char direction) PDEBUG("resizestep in unknown direction.\n"); break; } /* switch direction */ - + resizelim(client); /* If this window was vertically maximized, remember that it isn't now. */ @@ -2363,6 +2366,145 @@ void resizestep(struct client *client, char direction) xcb_flush(conn); } +/* + * Try to snap to other windows and monitor border + */ +void snapwindow(struct client *client, int snap_mode) +{ + struct item *item; + struct client *win; + int16_t mon_x; + int16_t mon_y; + uint16_t mon_width; + uint16_t mon_height; + + if (NULL == client->monitor) + { + mon_x = 0; + mon_y = 0; + mon_width = screen->width_in_pixels; + mon_height = screen->height_in_pixels; + } + else + { + mon_x = client->monitor->x; + mon_y = client->monitor->y; + mon_width = client->monitor->width; + mon_height = client->monitor->height; + } + /* + * Go through all windows on current workspace. + */ + for (item = wslist[curws]; item != NULL; item = item->next) + { + win = item->data; + + if (client == win) + { + continue; + } + + if (snap_mode == MCWM_MOVE) + { + if (abs((win->x +win->width) - client->x) < conf.snapmargin) + { + if (client->y + client->height > win->y + && client->y < win->y + win->height) + { + client->x = (win->x + win->width) + (2 * conf.borderwidth); + } + } + + if (abs((win->y +win->height) - client->y) < conf.snapmargin) + { + if (client->x + client->width >win->x + && client->x < win->x + win->width) + { + client->y = (win->y + win->height) + (2 * conf.borderwidth); + } + } + + if (abs((client->x + client->width) - win->x) < conf.snapmargin) + { + if (client->y + client->height > win->y + && client->y < win->y + win->height) + { + client->x = (win->x - client->width) + - (2 * conf.borderwidth); + } + } + + if (abs((client->y + client->height) - win->y) < conf.snapmargin) + { + if (client->x + client->width >win->x + && client->x < win->x + win->width) + { + client->y = (win->y - client->height) + - (2 * conf.borderwidth); + } + } + + } /* mcwm_move */ + else if (snap_mode == MCWM_RESIZE) + { + if (abs((client->x + client->width) - win->x) < conf.snapmargin) + { + if (client->y + client->height > win->y + && client->y < win->y + win->height) + { + client->width = (win->x - client->x) + - (2 * conf.borderwidth); + } + } + + if (abs((client->y + client->height) - win->y) < conf.snapmargin) + { + if (client->x + client->width >win->x + && client->x < win->x + win->width) + { + client->height = (win->y - client->y) + - (2 * conf.borderwidth); + } + } + } /* mcwm_resize */ + } /* for */ + + /* monitor border */ + if (snap_mode == MCWM_MOVE) { + + if (abs(client->x - mon_x) < conf.snapmargin) + { + client->x = mon_x; + } + + if (abs(client->y - mon_y) < conf.snapmargin) + { + client->y = mon_y; + } + + if (abs((client->x + client->width) - mon_width) < conf.snapmargin) + { + client->x = (mon_width - client->width); + } + + if (abs((client->y + client->height) - mon_height) < conf.snapmargin) + { + client->y = (mon_height - client->height); + } + } + else if (snap_mode == MCWM_RESIZE) + { + if (abs((client->width + client->x) - mon_width) < conf.snapmargin) + { + client->width = mon_width; + } + if (abs((client->height + client->y) - mon_height) < conf.snapmargin) + { + client->height = mon_height; + } + } +} + /* * Move window win as a result of pointer motion to coordinates * rel_x,rel_y. @@ -2371,12 +2513,18 @@ void mousemove(struct client *client, int rel_x, int rel_y) { client->x = rel_x; client->y = rel_y; - + + if (conf.snapmargin > 0) + { + snapwindow(client, MCWM_MOVE); + } + movelim(client); } void mouseresize(struct client *client, int rel_x, int rel_y) { + client->width = abs(rel_x - client->x); client->height = abs(rel_y - client->y); @@ -2388,6 +2536,11 @@ void mouseresize(struct client *client, int rel_x, int rel_y) (client->width - client->base_width) / client->width_inc, (client->height - client->base_height) / client->height_inc); + if (conf.snapmargin > 0) + { + snapwindow(client, MCWM_RESIZE); + } + resizelim(client); /* If this window was vertically maximized, remember that it isn't now. */ @@ -2442,7 +2595,7 @@ void movestep(struct client *client, char direction) PDEBUG("movestep: Moving in unknown direction.\n"); break; } /* switch direction */ - + movelim(client); /* @@ -4110,14 +4263,15 @@ void events(void) void printhelp(void) { - printf("mcwm: Usage: mcwm [-b] [-t terminal-program] [-f colour] " - "[-u colour] [-x colour] \n"); + printf("mcwm: Usage: mcwm [-b] [-s snapmargin] [-t terminal-program] " + "[-f colour] [-u colour] [-x colour] \n"); printf(" -b means draw no borders\n"); + printf(" -s snapmargin in pixels\n"); printf(" -t urxvt will start urxvt when MODKEY + Return is pressed\n"); printf(" -f colour sets colour for focused window borders of focused " "to a named color.\n"); - printf(" -u colour sets colour for unfocused window borders."); - printf(" -x color sets colour for fixed window borders."); + printf(" -u colour sets colour for unfocused window borders.\n"); + printf(" -x color sets colour for fixed window borders.\n"); } void sigcatch(int sig) @@ -4188,6 +4342,7 @@ int main(int argc, char **argv) /* Set up defaults. */ conf.borderwidth = BORDERWIDTH; + conf.snapmargin = SNAPMARGIN; conf.terminal = TERMINAL; conf.allowicons = ALLOWICONS; focuscol = FOCUSCOL; @@ -4196,7 +4351,7 @@ int main(int argc, char **argv) while (1) { - ch = getopt(argc, argv, "b:it:f:u:x:"); + ch = getopt(argc, argv, "b:s:it:f:u:x:"); if (-1 == ch) { @@ -4211,6 +4366,11 @@ int main(int argc, char **argv) conf.borderwidth = atoi(optarg); break; + case 's': + /* Snap margin */ + conf.snapmargin = atoi(optarg); + break; + case 'i': conf.allowicons = true; break; diff --git a/mcwm.man b/mcwm.man index 6d6cd4a..ef59b73 100644 --- a/mcwm.man +++ b/mcwm.man @@ -1,4 +1,4 @@ -.TH mcwm 1 "Apr 30, 2012" "" "" +.TH mcwm 1 "Aug 8, 2013" "" "" .SH NAME mcwm \- MC's Window Manager for X11. .SH SYNOPSIS @@ -8,17 +8,24 @@ mcwm \- MC's Window Manager for X11. width ] [ .B \-i +] +[ +.B \-s +.I snapmargin ] [ .B \-t .I terminal-program -] [ +] +[ .B \-f .I colour -] [ +] +[ .B \-u .I colour -] [ +] +[ .B \-x .I colour ] @@ -36,6 +43,9 @@ that there is no way from mcwm to get a hidden window back! You have to use an external program such as a panel or the mcicon or 9icon scripts (see below) to get the window mapped again. .PP +\-s snapmargin turns on window snapping to borders and other windows +within snapmargin pixels. +.PP \-t urxvt will start urxvt when MODKEY + Return is pressed. Change to your prefered terminal program or something else entirely. .PP -- cgit v1.2.3