summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cardell Widerkrantz <mc@hack.org>2011-11-17 08:34:25 +0100
committerMichael Cardell Widerkrantz <mc@hack.org>2011-11-17 08:34:25 +0100
commita389d4ade00b578b5d4a8148601c831e7347c321 (patch)
tree107cde5a9d103fe3bfb062fc17a69880bead8e77
parentb67b7a9b529bae40848f429cd9d201abf18e9d5f (diff)
downloadmcwm-a389d4ade00b578b5d4a8148601c831e7347c321.zip
Rewrote ConfigureRequest handling. Don't obey window moves not
initiated by user. Always fit window on physical screen.
-rw-r--r--NEWS3
-rw-r--r--TODO3
-rw-r--r--mcwm.c337
3 files changed, 227 insertions, 116 deletions
diff --git a/NEWS b/NEWS
index 3238065..8d5a9f0 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ User visible changes
2011-11-17
+ * In a ConfigureRequest we no longer obey window movements not
+ initiated by the user.
+
* Fixed bug with topright command on other physical screens.
* -b no longer boolean. Now takes parameter number of pixels.
diff --git a/TODO b/TODO
index b163683..49dd388 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,5 @@
-*- text -*-
-* In configurerequest() we should honour physical screen limits,
- perhaps by a call to fitonscreen().
-
* When a window tries to map itself outside the physical screens,
always map it to the screen closest to the coordinates it asked for
instead of always mapping on the first screen in the list.
diff --git a/mcwm.c b/mcwm.c
index 6292369..613d53e 100644
--- a/mcwm.c
+++ b/mcwm.c
@@ -168,7 +168,19 @@ struct client
struct item *wsitem[WORKSPACES]; /* Pointer to our place in every
* workspace window list. */
};
-
+
+/* Window configuration data. */
+struct winconf
+{
+ int16_t x;
+ int16_t y;
+ uint16_t width;
+ uint16_t height;
+ uint8_t stackmode;
+ xcb_window_t sibling;
+ uint16_t borderwidth;
+};
+
/* Globals */
@@ -316,6 +328,8 @@ static void setunfocus(xcb_drawable_t win);
static void setfocus(struct client *client);
static int start_terminal(void);
static void resizelim(struct client *client);
+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);
static void mousemove(struct client *client, int rel_x, int rel_y);
@@ -336,6 +350,7 @@ static void deletewin(void);
static void prevscreen(void);
static void nextscreen(void);
static void handle_keypress(xcb_key_press_event_t *ev);
+static void configwin(xcb_window_t win, uint16_t mask, struct winconf wc);
static void configurerequest(xcb_configure_request_event_t *e);
static void events(void);
static void printhelp(void);
@@ -2187,6 +2202,32 @@ void resizelim(struct client *client)
resize(client->id, client->width, client->height);
}
+void moveresize(xcb_drawable_t win, uint16_t x, uint16_t y,
+ uint16_t width, uint16_t height)
+{
+ uint32_t values[4];
+
+ if (screen->root == win || 0 == win)
+ {
+ /* Can't move or resize root. */
+ return;
+ }
+
+ PDEBUG("Moving to %d, %d, resizing to %d x %d.\n", x, y, width, height);
+
+ values[0] = x;
+ values[1] = y;
+ values[2] = width;
+ values[3] = height;
+
+ xcb_configure_window(conn, win,
+ XCB_CONFIG_WINDOW_X
+ | XCB_CONFIG_WINDOW_Y
+ | XCB_CONFIG_WINDOW_WIDTH
+ | XCB_CONFIG_WINDOW_HEIGHT, values);
+ xcb_flush(conn);
+}
+
/* Resize window win to width,height. */
void resize(xcb_drawable_t win, uint16_t width, uint16_t height)
{
@@ -3083,163 +3124,233 @@ void handle_keypress(xcb_key_press_event_t *ev)
}
} /* handle_keypress() */
-void configurerequest(xcb_configure_request_event_t *e)
+/* Helper function to configure a window. */
+void configwin(xcb_window_t win, uint16_t mask, struct winconf wc)
{
- uint32_t mask = 0;
uint32_t values[7];
int i = -1;
- struct client *client;
- int16_t mon_x;
- int16_t mon_y;
- uint16_t mon_width;
- uint16_t mon_height;
-
- PDEBUG("event: Configure request. mask = %d\n", e->value_mask);
+
+ if (mask & XCB_CONFIG_WINDOW_X)
+ {
+ mask |= XCB_CONFIG_WINDOW_X;
+ i ++;
+ values[i] = wc.x;
+ }
- /* Find the client. */
- client = findclient(e->window);
- if (NULL == client)
+ if (mask & XCB_CONFIG_WINDOW_Y)
{
- PDEBUG("We don't know about this window yet.\n");
+ mask |= XCB_CONFIG_WINDOW_Y;
+ i ++;
+ values[i] = wc.y;
}
-
- if (NULL == client || NULL == client->monitor)
+
+ if (mask & XCB_CONFIG_WINDOW_WIDTH)
{
- mon_x = 0;
- mon_y = 0;
- mon_width = screen->width_in_pixels;
- mon_height = screen->height_in_pixels;
+ mask |= XCB_CONFIG_WINDOW_WIDTH;
+ i ++;
+ values[i] = wc.width;
}
- else
+
+ if (mask & XCB_CONFIG_WINDOW_HEIGHT)
{
- mon_x = client->monitor->x;
- mon_y = client->monitor->y;
- mon_width = client->monitor->width;
- mon_height = client->monitor->height;
+ mask |= XCB_CONFIG_WINDOW_HEIGHT;
+ i ++;
+ values[i] = wc.height;
}
- /*
- * We ignore border width configurations, but handle all
- * others.
- */
+ if (mask & XCB_CONFIG_WINDOW_SIBLING)
+ {
+ mask |= XCB_CONFIG_WINDOW_SIBLING;
+ i ++;
+ values[i] = wc.sibling;
+ }
- if (e->value_mask & XCB_CONFIG_WINDOW_X)
+ if (mask & XCB_CONFIG_WINDOW_STACK_MODE)
{
- PDEBUG("Changing X coordinate to %d\n", e->x);
- mask |= XCB_CONFIG_WINDOW_X;
- i ++;
+ mask |= XCB_CONFIG_WINDOW_STACK_MODE;
+ i ++;
+ values[i] = wc.stackmode;
+ }
+
+ if (-1 != i)
+ {
+ xcb_configure_window(conn, win, mask, values);
+ xcb_flush(conn);
+ }
+}
+
+void configurerequest(xcb_configure_request_event_t *e)
+{
+ struct client *client;
+ struct winconf wc;
+ int16_t mon_x;
+ int16_t mon_y;
+ uint16_t mon_width;
+ uint16_t mon_height;
- if (client)
+ PDEBUG("event: Configure request. mask = %d\n", e->value_mask);
+
+ /* Find the client. */
+ if ((client = findclient(e->window)))
+ {
+ /* Find monitor position and size. */
+ if (NULL == client || NULL == client->monitor)
{
- client->x = e->x;
- if (client->x < mon_x)
- {
- client->x = mon_x;
- }
- else if (client->x + client->width > mon_x + mon_width)
- {
- client->x = (mon_x + mon_width) - client->width;
- }
-
- values[i] = client->x;
+ mon_x = 0;
+ mon_y = 0;
+ mon_width = screen->width_in_pixels;
+ mon_height = screen->height_in_pixels;
}
else
{
- values[i] = e->x;
+ mon_x = client->monitor->x;
+ mon_y = client->monitor->y;
+ mon_width = client->monitor->width;
+ mon_height = client->monitor->height;
}
- }
- if (e->value_mask & XCB_CONFIG_WINDOW_Y)
- {
- PDEBUG("Changing Y coordinate to %d.\n", e->y);
- mask |= XCB_CONFIG_WINDOW_Y;
- i ++;
-
- if (client)
+#if 0
+ /*
+ * We ignore moves the user haven't initiated, that is do
+ * nothing on XCB_CONFIG_WINDOW_X and XCB_CONFIG_WINDOW_Y
+ * ConfigureRequests.
+ *
+ * Code here if we ever change our minds or if you, dear user,
+ * wants this functionality.
+ */
+
+ if (e->value_mask & XCB_CONFIG_WINDOW_X)
{
- client->y = e->y;
- if (client->y < mon_y)
+ /* Don't move window if maximized. Don't move off the screen. */
+ if (!client->maxed && e->x > 0)
{
- client->y = mon_y;
+ client->x = e->x;
}
- else if (client->y + client->height > mon_y + mon_height)
+ }
+
+ if (e->value_mask & XCB_CONFIG_WINDOW_Y)
+ {
+ /*
+ * Don't move window if maximized. Don't move off the
+ * screen.
+ */
+ if (!client->maxed && !client->vertmaxed && e->y > 0)
{
- client->y = (mon_y + mon_height) - client->height;
+ client->y = e->y;
}
-
- values[i] = client->y;
}
- else
+#endif
+
+ if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH)
{
- values[i] = e->y;
- }
- }
-
- if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH)
- {
- PDEBUG("Changing width to %d.\n", e->width);
- mask |= XCB_CONFIG_WINDOW_WIDTH;
- i ++;
+ /* Don't resize if maximized. */
+ if (!client->maxed)
+ {
+ client->width = e->width;
+ }
+ }
- if (client)
+ if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
{
- client->width = e->width;
-
- if (client->width + conf.borderwidth * 2 > mon_width)
+ /* Don't resize if maximized. */
+ if (!client->maxed && !client->vertmaxed)
{
- client->width = mon_width - conf.borderwidth * 2;
+ client->height = e->height;
}
-
- values[i] = client->width;
}
- else
+
+ /*
+ * XXX Do we really need to pass on sibling and stack mode
+ * configuration? Do we want to?
+ */
+ if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING)
{
- values[i] = e->width;
+ uint32_t values[1];
+
+ values[0] = e->sibling;
+ xcb_configure_window(conn, e->window,
+ XCB_CONFIG_WINDOW_SIBLING,
+ values);
+ xcb_flush(conn);
+
}
- }
+
+ if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE)
+ {
+ uint32_t values[1];
- if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
- {
- PDEBUG("Changing height to %d.\n", e->height);
- mask |= XCB_CONFIG_WINDOW_HEIGHT;
- i ++;
+ values[0] = e->stack_mode;
+ xcb_configure_window(conn, e->window,
+ XCB_CONFIG_WINDOW_STACK_MODE,
+ values);
+ xcb_flush(conn);
+ }
- if (client)
+ /* Check if window fits on screen after resizing. */
+
+ if (client->x + client->width + 2 * conf.borderwidth
+ > mon_x + mon_width)
{
- client->height = e->height;
- if (client->height + conf.borderwidth * 2 > mon_height)
+ /*
+ * See if it fits if we move away the window from the
+ * right edge of the screen.
+ */
+ client->x = mon_x + mon_width
+ - (client->width + 2 * conf.borderwidth);
+
+ /*
+ * If we moved over the left screen edge, move back and
+ * fit exactly on screen.
+ */
+ if (client->x < mon_x)
{
- client->height = mon_height - conf.borderwidth * 2;
- }
-
- values[i] = client->height;
+ client->x = mon_x;
+ client->width = mon_width - 2 * conf.borderwidth;
+ }
}
- else
+
+ if (client->y + client->height + 2 * conf.borderwidth
+ > mon_y + mon_height)
{
- values[i] = e->height;
+ /*
+ * See if it fits if we move away the window from the
+ * bottom edge.
+ */
+ client->y = mon_y + mon_height
+ - (client->height + 2 * conf.borderwidth);
+
+ /*
+ * If we moved over the top screen edge, move back and fit
+ * on screen.
+ */
+ if (client->y < mon_y)
+ {
+ PDEBUG("over the edge: y < %d\n", mon_y);
+ client->y = mon_y;
+ client->height = mon_height - 2 * conf.borderwidth;
+ }
}
+
+ moveresize(client->id, client->x, client->y, client->width,
+ client->height);
}
-
- if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING)
+ else
{
- mask |= XCB_CONFIG_WINDOW_SIBLING;
- i ++;
- values[i] = e->sibling;
- }
+ PDEBUG("We don't know about this window yet.\n");
- if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE)
- {
- PDEBUG("Changing stack order.\n");
- mask |= XCB_CONFIG_WINDOW_STACK_MODE;
- i ++;
- values[i] = e->stack_mode;
- }
+ /*
+ * Unmapped window. Just pass all options except border
+ * width.
+ */
+ wc.x = e->x;
+ wc.y = e->y;
+ wc.width = e->width;
+ wc.height = e->height;
+ wc.sibling = e->sibling;
+ wc.stackmode = e->stack_mode;
- if (-1 != i)
- {
- xcb_configure_window(conn, e->window, mask, values);
- xcb_flush(conn);
- }
+ configwin(e->window, e->value_mask, wc);
+ }
}
void events(void)