summaryrefslogtreecommitdiff
path: root/mcwm.c
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 /mcwm.c
parentb67b7a9b529bae40848f429cd9d201abf18e9d5f (diff)
downloadmcwm-a389d4ade00b578b5d4a8148601c831e7347c321.zip
Rewrote ConfigureRequest handling. Don't obey window moves not
initiated by user. Always fit window on physical screen.
Diffstat (limited to 'mcwm.c')
-rw-r--r--mcwm.c337
1 files changed, 224 insertions, 113 deletions
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)