summaryrefslogtreecommitdiff
path: root/mcwm.c
diff options
context:
space:
mode:
authorMC <mc@hack.org>2010-06-19 10:28:12 +0200
committerMC <mc@hack.org>2010-06-19 10:28:12 +0200
commitafce86dd49a219c698bdc4409863684a9a43b1bd (patch)
tree71a2516a63755c85552f003329e89709cb72f863 /mcwm.c
parent6cf617c0a560ffea77f9c97c502bffaac145a2b0 (diff)
downloadmcwm-afce86dd49a219c698bdc4409863684a9a43b1bd.zip
Try subscribing to SUBSTRUCTURE REDIRECT events first and fallback to
SUBSTRUCTURE NOTIFY if that fails (ie, another window manager is running). This means we can still run simultaneously with another wm. newwin(): New function. Gets called when we're the only wm when new windows wants to be mapped. We map them at the position of the pointer. Don't map all existing windows when starting at all. Removed -m. Moved events loop to its own function, events().
Diffstat (limited to 'mcwm.c')
-rw-r--r--mcwm.c321
1 files changed, 181 insertions, 140 deletions
diff --git a/mcwm.c b/mcwm.c
index 66563fa..13ac63b 100644
--- a/mcwm.c
+++ b/mcwm.c
@@ -95,13 +95,11 @@ struct keys
struct conf
{
bool borders;
- bool map;
-
} conf;
/* Functions declerations. */
-
+void newwin(xcb_window_t win);
void setupwin(xcb_window_t win);
xcb_keycode_t keysymtokeycode(xcb_keysym_t keysym, xcb_key_symbols_t *keysyms);
int setupkeys(void);
@@ -123,14 +121,47 @@ void handle_keypress(xcb_drawable_t win, xcb_key_press_event_t *ev);
/* Function bodies. */
+/* Set position, geometry and attributes of a new window. */
+void newwin(xcb_window_t win)
+{
+ xcb_query_pointer_reply_t *pointer;
+ int x;
+ int y;
+
+ /* Get pointer position. */
+ pointer = xcb_query_pointer_reply(
+ conn, xcb_query_pointer(conn, screen->root), 0);
+
+ if (NULL == pointer)
+ {
+ x = 1;
+ y = 1;
+ }
+ else
+ {
+ x = pointer->root_x;
+ y = pointer->root_y;
+ }
+
+ /* Move the window to cursor position. */
+ movewindow(win, x, y);
+
+ /* Set up stuff and raise the window. */
+ setupwin(win);
+ raisewindow(win);
+
+ /* Show window on screen. */
+ xcb_map_window(conn, win);
+
+ xcb_flush(conn);
+}
+
/* set border colour, width and event mask for window. */
void setupwin(xcb_window_t win)
{
uint32_t mask = 0;
uint32_t values[2];
- PDEBUG("Setting up window %d\n", win);
-
if (conf.borders)
{
/* Set border color. */
@@ -146,12 +177,6 @@ void setupwin(xcb_window_t win)
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_ENTER_WINDOW;
xcb_change_window_attributes_checked(conn, win, mask, values);
-
- if (conf.map)
- {
- /* Show window on screen. */
- xcb_map_window(conn, win);
- }
/* FIXME: set properties. */
@@ -231,6 +256,8 @@ int setupscreen(void)
setupwin(children[i]);
}
+ xcb_flush(conn);
+
free(reply);
return 0;
@@ -715,7 +742,7 @@ void handle_keypress(xcb_drawable_t win, xcb_key_press_event_t *ev)
{
int i;
key_enum_t key;
-
+
for (key = KEY_MAX, i = KEY_H; i < KEY_MAX; i ++)
{
if (ev->detail == keys[i].keycode)
@@ -794,136 +821,16 @@ void handle_keypress(xcb_drawable_t win, xcb_key_press_event_t *ev)
}
} /* handle_keypress() */
-int main(int argc, char **argv)
+
+void events(void)
{
- xcb_window_t root;
xcb_generic_event_t *ev;
- uint32_t mask = 0;
- uint32_t values[2];
xcb_drawable_t win;
xcb_get_geometry_reply_t *geom;
int mode = 0;
uint16_t mode_x;
uint16_t mode_y;
- char ch; /* Option character */
-
- /*
- int xcb_parse_display(const char *name, char **host, int *display, int *screen);
- */
-/*
- xcb_parse_display(dispname, &host, &disp, NULL)
-*/
-
- conf.borders = true;
- conf.map = true;
-
- while (1)
- {
- ch = getopt(argc, argv, "bm");
- if (-1 == ch)
- {
-
- /* No more options, break out of while loop. */
- break;
- }
-
- switch (ch)
- {
- case 'b':
- /* No borders. */
- conf.borders = false;
- break;
-
- case 'm':
- /* Don't map all windows when initializing. */
- conf.map = false;
- break;
-
- }
- }
-
- conn = xcb_connect(NULL, NULL);
- if (xcb_connection_has_error(conn))
- {
- perror("xcb_connect");
- exit(1);
- }
-
- /* Get the first screen */
- screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
-
- /* screen->root is our root. */
- root = screen->root;
-
- /* Initial focus is root */
- /* FIXME: Ask the X server what window has focus. */
- focuswin = root;
-
- PDEBUG("Screen size: %dx%d\nRoot window: %d\n", screen->width_in_pixels,
- screen->height_in_pixels, screen->root);
-
- /* FIXME: Get some colours. */
-
- /* Loop over all clients and set up stuff. */
- if (0 != setupscreen())
- {
- fprintf(stderr, "Failed to initialize windows. Exiting.\n");
- exit(1);
- }
-
- /* Set up key bindings. */
- if (0 != setupkeys())
- {
- fprintf(stderr, "mcwm: Couldn't set up keycodes. Exiting.");
- exit(1);
- }
-
- /* Grab some keys and mouse buttons. */
-
- xcb_grab_key(conn, 1, root, MODKEY, XCB_NO_SYMBOL,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
-
- xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
- | XCB_EVENT_MASK_BUTTON_RELEASE,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
- 1 /* left mouse button */,
- MOUSEMODKEY);
-
- xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
- | XCB_EVENT_MASK_BUTTON_RELEASE,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
- 2 /* middle mouse button */,
- MOUSEMODKEY);
-
- xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
- | XCB_EVENT_MASK_BUTTON_RELEASE,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
- 3 /* right mouse button */,
- MOUSEMODKEY);
-
-#if 0
-
- /*
- * If we really want to be a wm, ask for these events as well:
- */
- mask = XCB_CW_EVENT_MASK;
- values[0] =
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT /* only one client can use this. */
- | XCB_EVENT_MASK_STRUCTURE_NOTIFY; /* don't know about this. New screens? */
-
- xcb_void_cookie_t cookie;
- cookie = xcb_change_window_attributes_checked(conn, root, mask, values);
-
-#endif
-
- mask = XCB_CW_EVENT_MASK;
- values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
- xcb_change_window_attributes_checked(conn, root, mask, values);
-
- xcb_flush(conn);
-
- /* Loop over events. */
for (;;)
{
ev = xcb_wait_for_event(conn);
@@ -937,16 +844,28 @@ int main(int argc, char **argv)
switch (ev->response_type & ~0x80)
{
+
+ /* If we're the only wm, we get these when a new window is created. */
+ case XCB_MAP_REQUEST:
+ {
+ xcb_create_notify_event_t *e;
+
+ PDEBUG("Map request\n");
+ e = ( xcb_create_notify_event_t *) ev;
+ newwin(e->window);
+ }
+ break;
+
+ /* If we're not the only window manager, we receive these instead. */
case XCB_CREATE_NOTIFY:
{
xcb_create_notify_event_t *e;
- PDEBUG("A new window!\n");
+ PDEBUG("Create notify event\n");
e = ( xcb_create_notify_event_t *) ev;
setupwin(e->window);
- }
- break;
-
+ }
+
case XCB_BUTTON_PRESS:
{
xcb_button_press_event_t *e;
@@ -1012,12 +931,12 @@ int main(int argc, char **argv)
xcb_grab_pointer(conn,
0, /* get all from mask below */
- root, /* grab here */
+ screen->root, /* grab here */
XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION,
XCB_GRAB_MODE_ASYNC, /* get more pointer events */
XCB_GRAB_MODE_ASYNC,
- root, /* stay here */
+ screen->root, /* stay here */
XCB_NONE, /* no other cursor. */
XCB_CURRENT_TIME);
xcb_flush(conn);
@@ -1115,6 +1034,128 @@ int main(int argc, char **argv)
free(ev);
}
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t mask = 0;
+ uint32_t values[2];
+ char ch; /* Option character */
+ xcb_void_cookie_t cookie;
+ xcb_generic_error_t *error;
+ xcb_drawable_t root;
+
+ conf.borders = true;
+
+ while (1)
+ {
+ ch = getopt(argc, argv, "bm");
+ if (-1 == ch)
+ {
+
+ /* No more options, break out of while loop. */
+ break;
+ }
+
+ switch (ch)
+ {
+ case 'b':
+ /* No borders. */
+ conf.borders = false;
+ break;
+ }
+ }
+
+ conn = xcb_connect(NULL, NULL);
+ if (xcb_connection_has_error(conn))
+ {
+ perror("xcb_connect");
+ exit(1);
+ }
+
+ /* Get the first screen */
+ screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
+
+ root = screen->root;
+ /* Initial focus is root */
+ /* FIXME: Ask the X server what window has focus. */
+ focuswin = screen->root;
+
+ PDEBUG("Screen size: %dx%d\nRoot window: %d\n", screen->width_in_pixels,
+ screen->height_in_pixels, screen->root);
+
+ /* FIXME: Get some colours. */
+
+ /* Loop over all clients and set up stuff. */
+ if (0 != setupscreen())
+ {
+ fprintf(stderr, "Failed to initialize windows. Exiting.\n");
+ exit(1);
+ }
+
+ /* Set up key bindings. */
+ if (0 != setupkeys())
+ {
+ fprintf(stderr, "mcwm: Couldn't set up keycodes. Exiting.");
+ exit(1);
+ }
+
+ /* Grab some keys and mouse buttons. */
+
+ xcb_grab_key(conn, 1, root, MODKEY, XCB_NO_SYMBOL,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
+
+ xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
+ | XCB_EVENT_MASK_BUTTON_RELEASE,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
+ 1 /* left mouse button */,
+ MOUSEMODKEY);
+
+ xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
+ | XCB_EVENT_MASK_BUTTON_RELEASE,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
+ 2 /* middle mouse button */,
+ MOUSEMODKEY);
+
+ xcb_grab_button(conn, 0, root, XCB_EVENT_MASK_BUTTON_PRESS
+ | XCB_EVENT_MASK_BUTTON_RELEASE,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
+ 3 /* right mouse button */,
+ MOUSEMODKEY);
+
+ /* Subscribe to events. */
+ mask = XCB_CW_EVENT_MASK;
+ values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+
+ cookie =
+ xcb_change_window_attributes_checked(conn, root, mask, values);
+ error = xcb_request_check(conn, cookie);
+ if (NULL != error)
+ {
+ fprintf(stderr, "mcwm: Can't subscribe to SUBSTRUCTURE REDIRECT event. "
+ "Error code: %d\n"
+ "Another window manager running?\n"
+ "Falling back to co-running mode.\n",
+ error->error_code);
+
+ values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
+ cookie =
+ xcb_change_window_attributes_checked(conn, root, mask, values);
+ error = xcb_request_check(conn, cookie);
+ if (NULL != error)
+ {
+ fprintf(stderr, "Co-running didn't work either. Error code: %d\n"
+ "Exiting\n",
+ error->error_code);
+ xcb_disconnect(conn);
+ exit(1);
+ }
+ }
+
+ xcb_flush(conn);
+
+ /* Loop over events. */
+ events();
xcb_disconnect(conn);