summaryrefslogtreecommitdiff
path: root/mcwm.c
diff options
context:
space:
mode:
authorMC <mc@hack.org>2010-07-09 23:51:42 +0200
committerMC <mc@brain.hack.org>2010-07-10 00:01:35 +0200
commitfa5c3e8cabb7cda02b26d4edaf3f2eb0ed1783d2 (patch)
tree6c901dc883d71b7886e4520038eecaae9dc82dd0 /mcwm.c
parente451e99ff498b7238e0a8ddab601f14588bb1fa3 (diff)
downloadmcwm-fa5c3e8cabb7cda02b26d4edaf3f2eb0ed1783d2.zip
Only handle visible windows when starting.
This means we also have to die gracefully ourselves and map all windows we know about. When terminating, we also set the keyboard focus model back to following the pointer. Handle some signals to attempt to die gracefully.
Diffstat (limited to 'mcwm.c')
-rw-r--r--mcwm.c95
1 files changed, 68 insertions, 27 deletions
diff --git a/mcwm.c b/mcwm.c
index 97ca141..c98b108 100644
--- a/mcwm.c
+++ b/mcwm.c
@@ -29,6 +29,7 @@
#include <errno.h>
#include <getopt.h>
#include <string.h>
+#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -125,6 +126,7 @@ struct client
/* Globals */
+int exitcode;
xcb_connection_t *conn; /* Connection to X server. */
xcb_screen_t *screen; /* Our current screen. */
uint32_t curws = 0; /* Current workspace. */
@@ -187,6 +189,8 @@ int unmaps_to_expect;
/* Functions declerations. */
+
+void die(int code);
void arrangewindows(int32_t rootwidth, int32_t rootheight);
void setwmdesktop(xcb_drawable_t win, uint32_t ws);
int32_t getwmdesktop(xcb_drawable_t win);
@@ -220,11 +224,41 @@ void maximize(struct client *client);
void maxvert(struct client *client);
void handle_keypress(xcb_key_press_event_t *ev);
void printhelp(void);
+void sigcatch(int sig);
/* Function bodies. */
/*
+ * Map all windows we know about. Set keyboard focus to be wherever
+ * the mouse pointer is. Then exit.
+ */
+void die(int code)
+{
+ struct item *item;
+ struct client *client;
+
+ xcb_set_input_focus(conn, XCB_NONE,
+ XCB_INPUT_FOCUS_POINTER_ROOT,
+ XCB_CURRENT_TIME);
+
+ for (item = winlist; item != NULL; item = item->next)
+ {
+ client = item->data;
+ xcb_map_window(conn, client->id);
+ }
+
+ xcb_flush(conn);
+
+ if (SIGSEGV == code)
+ {
+ abort();
+ }
+
+ exit(code);
+}
+
+/*
*
* Rearrange windows to fit new screen size rootwidth x rootheight.
*/
@@ -881,16 +915,18 @@ int setupscreen(void)
* with a MapRequest if we had been running, so in the
* normal case we wouldn't have seen them.
*
+ * Only handle visible windows.
*/
- if (!attr->override_redirect)
+ if (!attr->override_redirect
+ && attr->map_state == XCB_MAP_STATE_VIEWABLE)
{
client = setupwin(children[i]);
if (NULL != client)
{
/*
- * Check if this window has a workspace set already.
+ * Check if this window has a workspace set already as
+ * a WM hint.
*
- * If not and it is not mapped either, ignore it.
*/
ws = getwmdesktop(children[i]);
@@ -902,12 +938,17 @@ int setupscreen(void)
else if (MCWM_NOWS != ws && ws < WORKSPACE_MAX)
{
addtoworkspace(client, ws);
+ /* If it's not our current workspace, hide it. */
+ if (ws != curws)
+ {
+ xcb_unmap_window(conn, client->id);
+ }
}
- else if (XCB_MAP_STATE_UNMAPPED != attr->map_state)
+ else
{
/*
- * Not unmapped and not any _NET_WM_DESKTOP set.
- * Add it to our current workspace.
+ * No workspace hint at all. Just add it to our
+ * current workspace.
*/
addtoworkspace(client, curws);
}
@@ -1102,12 +1143,12 @@ void setfocus(struct client *client)
{
uint32_t values[1];
- /* if client is NULL, we focus on the root. */
+ /* if client is NULL, we focus on whatever the pointer is on. */
if (NULL == client)
{
focuswin = NULL;
- xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, screen->root,
+ xcb_set_input_focus(conn, XCB_NONE, XCB_INPUT_FOCUS_POINTER_ROOT,
XCB_CURRENT_TIME);
xcb_flush(conn);
@@ -1867,8 +1908,8 @@ void events(void)
int mode = 0; /* Internal mode. */
uint16_t mode_x;
uint16_t mode_y;
-
- for (;;)
+
+ for (exitcode = 0; 0 == exitcode;)
{
ev = xcb_wait_for_event(conn);
if (NULL == ev)
@@ -2216,20 +2257,6 @@ void events(void)
i ++;
values[i] = e->height;
}
-
-#if 0
- /* We handle a request to change the border width, but
- * only change it to what we think is right.
- */
- if (e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
- {
- PDEBUG("Changing width to %d, but not really.\n",
- e->border_width);
- mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
- i ++;
- values[i] = BORDERWIDTH;
- }
-#endif
if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING)
{
@@ -2278,9 +2305,6 @@ void events(void)
struct item *item;
struct client *client;
- PDEBUG("\n root: %d\n event: %d\n window: %d\n", screen->root,
- e->event, e->window);
-
/*
* If we're currently changing workspace, unmaps_to_expect
* is larger than 0.
@@ -2343,6 +2367,11 @@ void printhelp(void)
printf(" -u color sets colour for unfocused window borders.");
}
+void sigcatch(int sig)
+{
+ exitcode = sig;
+}
+
int main(int argc, char **argv)
{
uint32_t mask = 0;
@@ -2353,7 +2382,16 @@ int main(int argc, char **argv)
xcb_drawable_t root;
char *focuscol;
char *unfocuscol;
+ struct sigaction sigact; /* Signal handler. */
+
+ /* Install signal handlers. */
+ sigact.sa_flags = 0;
+ sigact.sa_handler = sigcatch;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGSEGV, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+
/* Set up defaults. */
conf.borders = true;
@@ -2483,6 +2521,9 @@ int main(int argc, char **argv)
/* Loop over events. */
events();
+ /* Die gracefully. */
+ die(exitcode);
+
xcb_disconnect(conn);
exit(0);