From 30cf32f830f835d49417b6208eb4467898751ec5 Mon Sep 17 00:00:00 2001 From: koma Date: Thu, 18 Aug 2022 17:34:02 +0200 Subject: [PATCH] focus fixes, add focus on motion, add structs and functions for keyboard config, cleaned up keypress_handler --- wm.c | 524 ++++++++++++++++++++++++++++++++++------------------------- wm.h | 49 +++++- 2 files changed, 346 insertions(+), 227 deletions(-) diff --git a/wm.c b/wm.c index 28224c7..77bf211 100644 --- a/wm.c +++ b/wm.c @@ -10,6 +10,7 @@ #include #include #include +#include Monitor wm_monitor_open(Display *d, XineramaScreenInfo info) { @@ -214,26 +215,17 @@ void wm_configure_handler(XConfigureRequestEvent e) DEBUG_PRINT("ConfigureRequest handler: window %d has property %s\n", (int)e.window, XGetAtomName(wm_display, ((Atom*)prop_ret)[i])); if (strcmp(XGetAtomName(wm_display, ((Atom*)prop_ret)[i]), - "_NET_WM_WINDOW_TYPE_NORMAL") == 0) { + "_NET_WM_WINDOW_TYPE_NORMAL") == 0) { is_normal = true; } else if (strcmp(XGetAtomName(wm_display, ((Atom*)prop_ret)[i]), - "_NET_WM_WINDOW_TYPE_DOCK") == 0) { + "_NET_WM_WINDOW_TYPE_DOCK") == 0) { wm_dock = e.window; + } else if (strcmp(XGetAtomName(wm_display, ((Atom*)prop_ret)[i]), + "_NET_WM_WINDOW_TYPE_DIALOG") == 0) { + c->is_floating = true; } } - /* - _NET_WM_WINDOW_TYPE_NORMAL indicates that this is a normal, - top-level window, [...] windows without _NET_WM_WINDOW_TYPE, - must be taken as this type [...] - - https://specifications.freedesktop.org/wm-spec - */ - if (type == None) { - DEBUG_PRINT("Atom %s does not exist for window.\n", name) - // is_normal = true; - } - if (!is_normal) { DEBUG_PRINT("configure handler: window %d is not normal, returning\n", (int)e.window) @@ -241,38 +233,7 @@ void wm_configure_handler(XConfigureRequestEvent e) return; } - - // wm_client_is_dock(nc); - wm_mstack(c->m); - // wm_client_is_dock(wm_client_find(e.window)); - // Client *c; - // XWindowChanges ch; - // int cc_sws = 0; - - // // for (c = wm_smon->clients; c; c = c->next) { - // // if (c->ws == wm_smon->selws) { - // // cc_sws++; - // // } - // // } - - // c = wm_client_find(e.window); - - // // // dynamic - // // if (cc_sws == 0) { - // // c->x = 0; - // // c->y = 0; - // // c->w = wm_smon->info.width; - // // c->h = wm_smon->info.height; - // // } - // // else { - // // // TODO - // // // c.x = m.h / cc_sws; - - // // } - - // // XConfigureWindow(wm_display, c->window, e.value_mask, &ch); - // - // wm_layout(c->m); + wm_layout(c->m); } void wm_keyrelease_handler(XKeyReleasedEvent e) @@ -284,98 +245,103 @@ void wm_keypress_handler(XKeyPressedEvent e) { DEBUG_PRINT("KeyPressed event, code: %d\n", e.keycode) Client *c; + Keybind k; - // TODO: bad code below: need to implement key structure with keysyms, - // and functions to be ran for clarity and configurabilty - // TODO: fix focusing left from master! - switch (e.state) { - case (Mod4Mask): - DEBUG_PRINT("mod4\n") - // cant use switch - // if (e.keycode == XKeysymToKeycode(e.display, XK_C)) { - // DEBUG_PRINT("Kill key combination\n") - // - // if ((c = wm_client_get_focused()) != NULL) { - // DEBUG_PRINT("kill client: 0x%x\n", c); - // wm_client_kill(c); - // } - // } - switch (XLookupKeysym(&e, 0)) { - case XK_c: - DEBUG_PRINT("Kill key combination\n") - if ((c = wm_client_get_focused()) != NULL) { - DEBUG_PRINT("kill client: 0x%x\n", c); - wm_client_kill(c); - } - break; - case XK_Return: - if (fork() == 0) { - if (wm_display) - close(ConnectionNumber(wm_display)); - setsid(); - //char *arg[] = {"-t", "Terminal", NULL}; - execvp("st", NULL); - exit(0); - } - break; - case XK_h: - wm_client_focus_dir(wm_client_get_focused(), LEFT); - break; - case XK_j: - wm_client_focus_dir(wm_client_get_focused(), DOWN); - break; - case XK_k: - wm_client_focus_dir(wm_client_get_focused(), UP); - break; - case XK_l: - wm_client_focus_dir(wm_client_get_focused(), RIGHT); - break; - case XK_1: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 0) - wm_switch_ws(0); - break; - case XK_2: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 1) - wm_switch_ws(1); - break; - case XK_3: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 2) - wm_switch_ws(2); - break; - case XK_4: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 3) - wm_switch_ws(3); - break; - case XK_5: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 4) - wm_switch_ws(4); - break; - case XK_6: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 5) - wm_switch_ws(5); - break; - case XK_7: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 6) - wm_switch_ws(6); - break; - case XK_8: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 7) - wm_switch_ws(7); - break; - case XK_9: - DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 8) - wm_switch_ws(8); - break; - default: - DEBUG_PRINT("wm_handle_keys default\n") - char *buf; - KeySym k; - XLookupString(&e, buf, 50, &k, NULL); - DEBUG_PRINT("default keysym: %s\n", buf) - DEBUG_PRINT("default keysym i: %d\n", k) - } - break; + for (int i = 0; i < wm_cfg_kb_count; i++) { + k = wm_cfg_keybinds[i]; + if (k.mask == e.state && k.keysym == XLookupKeysym(&e, 0)) + { + (*k.func)(&k.args); + } } + // switch (e.state) { + // case (Mod4Mask): + // DEBUG_PRINT("mod4\n") + // // cant use switch + // // if (e.keycode == XKeysymToKeycode(e.display, XK_C)) { + // // DEBUG_PRINT("Kill key combination\n") + // // + // // if ((c = wm_client_get_focused()) != NULL) { + // // DEBUG_PRINT("kill client: 0x%x\n", c); + // // wm_client_kill(c); + // // } + // // } + // switch (XLookupKeysym(&e, 0)) { + // case XK_c: + // DEBUG_PRINT("Kill key combination\n") + // if ((c = wm_client_get_focused()) != NULL) { + // DEBUG_PRINT("kill client: 0x%x\n", c); + // wm_client_kill(c); + // } + // break; + // case XK_Return: + // if (fork() == 0) { + // if (wm_display) + // close(ConnectionNumber(wm_display)); + // setsid(); + // //char *arg[] = {"-t", "Terminal", NULL}; + // execvp("st", NULL); + // exit(0); + // } + // break; + // case XK_h: + // wm_client_focus_dir(wm_client_get_focused(), LEFT); + // break; + // case XK_j: + // wm_client_focus_dir(wm_client_get_focused(), DOWN); + // break; + // case XK_k: + // wm_client_focus_dir(wm_client_get_focused(), UP); + // break; + // case XK_l: + // wm_client_focus_dir(wm_client_get_focused(), RIGHT); + // break; + // case XK_1: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 0) + // wm_switch_ws(0); + // break; + // case XK_2: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 1) + // wm_switch_ws(1); + // break; + // case XK_3: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 2) + // wm_switch_ws(2); + // break; + // case XK_4: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 3) + // wm_switch_ws(3); + // break; + // case XK_5: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 4) + // wm_switch_ws(4); + // break; + // case XK_6: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 5) + // wm_switch_ws(5); + // break; + // case XK_7: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 6) + // wm_switch_ws(6); + // break; + // case XK_8: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 7) + // wm_switch_ws(7); + // break; + // case XK_9: + // DEBUG_PRINT("wm_switch_ws keycode, ws: %d\n", 8) + // wm_switch_ws(8); + // break; + // default: + // DEBUG_PRINT("wm_handle_keys default\n") + // char *buf; + // KeySym k; + // XLookupString(&e, buf, 50, &k, NULL); + // DEBUG_PRINT("default keysym: %s\n", buf) + // DEBUG_PRINT("default keysym i: %d\n", k) + // } + // break; + // } } void wm_maprequest_handler(XMapRequestEvent e) @@ -404,7 +370,18 @@ void wm_maprequest_handler(XMapRequestEvent e) c = wm_client_create(e.window); RETURN_IF_NULL(c) //XMapWindow(wm_display, c->window); - wm_mstack(c->m); + wm_layout(c->m); +} + +void wm_motion_handler(XMotionEvent e) +{ + Client *c; + + c = wm_client_find(e.window); + RETURN_IF_NULL(c) + + if(!wm_client_is_focused(c) && wm_cfg_focus_on_motion) + wm_client_focus(c); } // TODO @@ -438,6 +415,10 @@ Client* wm_client_create(Window w) { Client *c = NULL; Client *t; + XTextProperty xtp; + int strln; + + XGetWMName(wm_display, w, &xtp); c = malloc(sizeof(Client)); @@ -445,6 +426,14 @@ Client* wm_client_create(Window w) c->m = wm_smon; c->ws = wm_smon->selws; c->hidden = true; + c->is_floating = false; + + if (xtp.value) { + strln = strlen((char*)xtp.value); + DEBUG_PRINT("%s allocating %d bytes for c->name", __func__, strln) + c->name = malloc(strln+1); + strcpy(c->name, (char*)xtp.value); + } if (wm_smon->clients == NULL) { wm_smon->clients = c; @@ -457,7 +446,10 @@ Client* wm_client_create(Window w) c->next = NULL; } - XSelectInput(wm_display, c->window, FocusChangeMask | EnterWindowMask); + XSelectInput(wm_display, c->window, FocusChangeMask | EnterWindowMask | + PointerMotionMask); + + wm_client_set_atom(c, "_NET_WM_DESKTOP", (unsigned char*)&c->ws, XA_CARDINAL, 1); return c; } @@ -549,7 +541,7 @@ void wm_client_kill(Client *c) XDestroyWindow(wm_display, c->window); wm_client_free(c); - wm_mstack(m); + wm_layout(m); } void wm_client_set_atom(Client *c, const char* name, const unsigned char *data, @@ -652,7 +644,7 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) for (r = c->m->clients; r; r = r->next) { if ((x > r->x && x < r->x+r->w) && (y > r->y && y < r->y+r->h)) { DEBUG_PRINT("%s ", __func__) - DEBUG_PRINT("found window %d in direction ", c->window) + DEBUG_PRINT("found window %d in direction ", (int)c->window) DEBUG_PRINT("%d\n", dir) return r; } @@ -678,26 +670,19 @@ Client* wm_client_get_focused() void wm_client_border(Client *c) { - // DEBUG_PRINT("%s\n", __func__); RETURN_IF_NULL(c); - // if (c->has_border) - // return; - - // TODO: color config XVisualInfo vinfo; XColor color; XColor fcolor; Colormap cmap; - char *colorstr = "#555555"; - char *focuscolorstr = "#FF0000"; XMatchVisualInfo(wm_display, DefaultScreen(wm_display), 32, TrueColor, &vinfo); cmap = XCreateColormap(wm_display, c->window, vinfo.visual, AllocNone); - XParseColor(wm_display, cmap, focuscolorstr, &fcolor); - XParseColor(wm_display, cmap, colorstr, &color); + XParseColor(wm_display, cmap, wm_cfg_focused_border_col, &fcolor); + XParseColor(wm_display, cmap, wm_cfg_border_col, &color); XAllocColor(wm_display, cmap, &fcolor); XAllocColor(wm_display, cmap, &color); @@ -707,18 +692,18 @@ void wm_client_border(Client *c) // DEBUG_PRINT("wm_client_border window: %d\n", c->window) } - XSetWindowBorderWidth(wm_display, c->window, wm_border_width); + XSetWindowBorderWidth(wm_display, c->window, wm_cfg_border_width); // DEBUG_PRINT("drawing border for: %d\n", c->window); if (wm_client_is_focused(c)) { - DEBUG_PRINT("drawing focused border for: %d\n", c->window); + DEBUG_PRINT("drawing focused border for: %d\n", (int)c->window); XSetWindowBorder(wm_display, c->window, fcolor.pixel); } else XSetWindowBorder(wm_display, c->window, color.pixel); } -// TODO maybe merge two border functios +// FIXME probably unused void wm_client_border_focused(Client *c) { RETURN_IF_NULL(c); @@ -727,18 +712,17 @@ void wm_client_border_focused(Client *c) XVisualInfo vinfo; XColor fcolor; Colormap cmap; - char *focuscolorstr = "#FF0000"; XMatchVisualInfo(wm_display, DefaultScreen(wm_display), 32, TrueColor, &vinfo); cmap = XCreateColormap(wm_display, c->window, vinfo.visual, AllocNone); - XParseColor(wm_display, cmap, focuscolorstr, &fcolor); + XParseColor(wm_display, cmap, wm_cfg_focused_border_col, &fcolor); XAllocColor(wm_display, cmap, &fcolor); - XSetWindowBorderWidth(wm_display, c->window, wm_border_width); + XSetWindowBorderWidth(wm_display, c->window, wm_cfg_border_width); - DEBUG_PRINT("drawing border for focused window: %d\n", c->window); + DEBUG_PRINT("drawing border for focused window: %d\n", (int)c->window); XSetWindowBorder(wm_display, c->window, fcolor.pixel); } @@ -844,7 +828,7 @@ void wm_switch_ws(int ws) wm_smon->selws = ws; - wm_client_set_atom(c, "_NET_CURRENT_DESKTOP", (unsigned char*) &(ws), + wm_client_set_atom(&wm_root, "_NET_CURRENT_DESKTOP", (unsigned char*) &(ws), XA_CARDINAL, 1); // XChangeProperty(wm_display, wm_root.window, // XInternAtom(wm_display, "_NET_CURRENT_DESKTOP", False), XA_CARDINAL, @@ -873,10 +857,13 @@ void wm_mstack(Monitor *m) int sx = 0; int sy = 0; XTextProperty xt; + XEvent e; unsigned int value_mask = CWX | CWY | CWWidth | CWHeight; // TODO: function + + // FIXME: &wm_root probably wrong if (wm_dock != -1) { XWindowAttributes x; @@ -889,7 +876,7 @@ void wm_mstack(Monitor *m) } for (c = m->clients; c; c = c->next) { - if (c->ws == m->selws && c != &wm_root) { + if (c->ws == m->selws && c != &wm_root && !c->is_floating) { cc_sws++; } } @@ -898,13 +885,13 @@ void wm_mstack(Monitor *m) // dynamic if (cc_sws == 1) { for (c = m->clients; c; c = c->next) { - if (c->ws == m->selws) - break; + if (c->ws == m->selws && c != &wm_root) + break; } c->x = 0; c->y = sy; - c->w = wm_smon->info.width-wm_border_width*2; - c->h = (wm_smon->info.height-wm_border_width*2)-sy; + c->w = wm_smon->info.width-wm_cfg_border_width*2; + c->h = (wm_smon->info.height-wm_cfg_border_width*2)-sy; ch = wm_client_to_xwchanges(*c); // DEBUG_PRINT("mstack client: 0x%x\n", c); // XGetWMName(wm_display, c->window, &xt); @@ -918,26 +905,20 @@ void wm_mstack(Monitor *m) //wm_client_focus(c); } else { - // TODO + // FIXME not working with dock for (c = m->clients; c; c = c->next) { - if (c->ws == m->selws && c != &wm_root) { + if (c->ws == m->selws && c != &wm_root && !c->is_floating) { if (n == 0) { c->x = 0; c->y = sy; - c->w = m->info.width*wm_ms_p-wm_border_width*2; - c->h = (m->info.height-wm_border_width*2)-sy; + c->w = m->info.width*wm_cfg_ms_p-wm_cfg_border_width*2; + c->h = (m->info.height-wm_cfg_border_width*2)-sy; } else { - c->x = (m->info.width*wm_ms_p); + c->x = (m->info.width*wm_cfg_ms_p); c->y = ((n-1)*m->info.height/(cc_sws-1))+sy; - c->w = (m->info.width - m->info.width*wm_ms_p)-wm_border_width*2; - c->h = ((m->info.height-sy)/(cc_sws-1)-wm_border_width*2)+sy/cc_sws; + c->w = (m->info.width - m->info.width*wm_cfg_ms_p)-wm_cfg_border_width*2; + c->h = ((m->info.height)/(cc_sws-1)-wm_cfg_border_width*2); } - // else { - // c->x = (m->info.width*wm_ms_p); - // c->y = ((n-1)*m->info.height/(cc_sws-1)); - // c->w = (m->info.width - m->info.width*wm_ms_p)-wm_border_width*2; - // c->h = (m->info.height/(cc_sws-1)-wm_border_width*2)-sy; - // } n++; ch = wm_client_to_xwchanges(*c); @@ -965,6 +946,9 @@ void wm_mstack(Monitor *m) } } + XSync(wm_display, False); + while(XCheckMaskEvent(wm_display, EnterWindowMask, &e)); + wm_monitor_clients_border(m); } @@ -973,11 +957,12 @@ void wm_set_layout(void(*f)(Monitor*)) wm_active_layout = f; } +// TODO: layout floating window, selected layout func p void wm_layout(Monitor *m) { RETURN_IF_NULL(m); - (*wm_active_layout)(m); + wm_mstack(m); } Client *wm_get_last_client(Monitor m) @@ -1057,24 +1042,22 @@ void wm_mainloop() case KeyPress: wm_keypress_handler(e.xkey); break; + case MotionNotify: + wm_motion_handler(e.xmotion); + break; case FocusIn: - // TODO: draw focus window elsewhere - // DEBUG_PRINT("%d window focus in\n", e.xfocus.window); - // wm_monitor_clients_border(wm_client_find(e.xfocus.window)->m); - // wm_client_border_focused(wm_client_find(e.xfocus.window)); break; case FocusOut: - // DEBUG_PRINT("%d window focus out\n", e.xfocus.window); - //wm_client_border(wm_client_find(e.xfocus.window)); break; case EnterNotify: DEBUG_PRINT("pointer entered window: %d\n", - e.xcrossing.window); - wm_client_focus(wm_client_find(e.xcrossing.window)); + (int)e.xcrossing.window); + if (wm_cfg_focus_on_motion) + wm_client_focus(wm_client_find(e.xcrossing.window)); break; case LeaveNotify: DEBUG_PRINT("pointer left window: %d\n", - e.xcrossing.window); + (int)e.xcrossing.window); break; case ConfigureNotify: DEBUG_PRINT("ConfigureNotify: %d\n", (int)e.xconfigure.window) @@ -1116,39 +1099,13 @@ void wm_init() XChangeWindowAttributes(wm_display, wm_root.window, CWEventMask, &xa); XSelectInput(wm_display, wm_root.window, xa.event_mask); - DEBUG_PRINT("root window id: %d\n", (wm_root.window)) + // DEBUG_PRINT("root window id: %d\n", (wm_root.window)) - // TODO: CONFIG KEYS! - XUngrabKey(wm_display, AnyKey, AnyModifier, wm_root.window); + // XUngrabKey(wm_display, AnyKey, AnyModifier, wm_root.window); - unsigned int modifiers[] = {0, LockMask, 0 | LockMask}; - XGrabKey(wm_display, XK_C, Mod4Mask | LockMask, wm_root.window, True, - GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_C), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XK_C, Mod4Mask | 0, wm_root.window, True, - GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_Return), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - - // focus keys - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_H), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_J), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_K), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_L), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - - // workspace switcher keys - - int wskeys[] = {XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9}; - - for (int i = 0; i < 9; i++) { - XGrabKey(wm_display, XKeysymToKeycode(wm_display, wskeys[i]), Mod4Mask, - wm_root.window, True, GrabModeAsync, GrabModeAsync); - } + // TODO: read config + wm_keybinds_init_def(); + wm_grab_keys(); //XSetErrorHandler(&wm_other_wm_handler); @@ -1162,12 +1119,18 @@ void wm_init() XInternAtom(wm_display, "_NET_NUMBER_OF_DESKTOPS", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &wm_smon->wscount, 1); + char *desktop_names[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + + wm_client_set_atom(&wm_root, "_NET_DESKTOP_NAMES", + (unsigned char*) desktop_names, XA_STRING, 9); + Atom wm_supp[] = { XInternAtom(wm_display, "_NET_NUMBER_OF_DESKTOPS", False), XInternAtom(wm_display, "_NET_DESKTOP_GEOMETRY", False), XInternAtom(wm_display, "_NET_DESKTOP_VIEWPORT", False), XInternAtom(wm_display, "_NET_CURRENT_DESKTOP", False), XInternAtom(wm_display, "_NET_ACTIVE_WINDOW", False), + XInternAtom(wm_display, "_NET_DESKTOP_NAMES", False), }; XChangeProperty(wm_display, wm_root.window, @@ -1176,13 +1139,132 @@ void wm_init() //XSetErrorHandler(&wm_xerror_handler); - // TODO: config - wm_ms_p = 0.5; - wm_mainloop(); } -//TODO: avoid global vars +void wm_grab_keys() +{ + RETURN_IF_NULL(wm_cfg_keybinds) + Keybind k; + + for (int i = 0; i < wm_cfg_kb_count; i++) { + k = wm_cfg_keybinds[i]; + XGrabKey(wm_display, XKeysymToKeycode(wm_display, k.keysym), k.mask, + wm_root.window, True, GrabModeAsync, GrabModeAsync); + } +} + +void wm_kb_spawn(Arg *args) +{ + RETURN_IF_NULL(args) + RETURN_IF_NULL(args->sl) + + DEBUG_PRINT("args sl 1: %d\n", args->sl[args->count-1]) + DEBUG_PRINT("args sl 0: %s\n", args->sl[0]) + DEBUG_PRINT("args count: %d\n", args->count) + + if (args->sl[args->count-1] != NULL) { + fprintf(stderr, "%s recieved non null-terminated args. Returning\n", + __func__); + } + + if (fork() == 0) { + if (wm_display) + close(ConnectionNumber(wm_display)); + setsid(); + execvp(args->sl[0], &(args->sl[1])); + + exit(0); + } +} + +void wm_kb_kill(Arg *args) +{ + Client *c; + + c = wm_client_get_focused(); + RETURN_IF_NULL(c) + + wm_client_kill(c); +} + +void wm_kb_switch_ws(Arg *args) +{ + RETURN_IF_NULL(args) + + wm_switch_ws(args->i); +} + +void wm_kb_focus_dir(Arg *args) +{ + RETURN_IF_NULL(args) + RETURN_IF_NULL(args->c) + + wm_client_focus_dir(args->c, args->i); +} + +void wm_keybinds_init_def() +{ + char *st[] = {"st", NULL}; + char **sth = malloc(sizeof(st)); + memcpy(sth, st, sizeof(st)); + int size; + + Keybind k[] = { + (Keybind) {Mod4Mask, XK_Return, *wm_kb_spawn, + (Arg) {.sl = sth, .count = 2}}, + + (Keybind) {Mod4Mask, XK_c, *wm_kb_kill, + (Arg) {.c = NULL}}, + + (Keybind) {Mod4Mask, XK_1, *wm_kb_switch_ws, + (Arg) {.i = 0}}, + + (Keybind) {Mod4Mask, XK_2, *wm_kb_switch_ws, + (Arg) {.i = 1}}, + + (Keybind) {Mod4Mask, XK_3, *wm_kb_switch_ws, + (Arg) {.i = 2}}, + + (Keybind) {Mod4Mask, XK_4, *wm_kb_switch_ws, + (Arg) {.i = 3}}, + + (Keybind) {Mod4Mask, XK_5, *wm_kb_switch_ws, + (Arg) {.i = 4}}, + + (Keybind) {Mod4Mask, XK_6, *wm_kb_switch_ws, + (Arg) {.i = 5}}, + + (Keybind) {Mod4Mask, XK_7, *wm_kb_switch_ws, + (Arg) {.i = 6}}, + + (Keybind) {Mod4Mask, XK_8, *wm_kb_switch_ws, + (Arg) {.i = 7}}, + + (Keybind) {Mod4Mask, XK_9, *wm_kb_switch_ws, + (Arg) {.i = 8}}, + + (Keybind) {Mod4Mask, XK_h, *wm_kb_focus_dir, + (Arg) {.i = LEFT}}, + + (Keybind) {Mod4Mask, XK_j, *wm_kb_focus_dir, + (Arg) {.i = DOWN}}, + + (Keybind) {Mod4Mask, XK_k, *wm_kb_focus_dir, + (Arg) {.i = UP}}, + + (Keybind) {Mod4Mask, XK_l, *wm_kb_focus_dir, + (Arg) {.i = RIGHT}}, + }; + + + size = sizeof(k); + wm_cfg_kb_count = size / sizeof(Keybind); + DEBUG_PRINT("sizeof k: %d\n", size); + wm_cfg_keybinds = malloc(size); + memcpy(wm_cfg_keybinds, k, size); +} + struct sockaddr wm_socket_init() { struct sockaddr_un sock_addr; @@ -1242,7 +1324,7 @@ void wm_settings_message_parse(char *c, int len) char *token; char tokens[20][50]; char *settings[] = {"border-width", "border-color", "focused-border-color", - "msfact"}; + "msfact", "focus-on-motion"}; while((token = strtok(c, " ")) != NULL) { DEBUG_PRINT("message_parse token: %s\n", token) diff --git a/wm.h b/wm.h index f461719..259a8fa 100644 --- a/wm.h +++ b/wm.h @@ -14,12 +14,12 @@ #include #include +// TODO: when only 1 window on ws it is not focused // TODO: dont draw border on not normal windows, floating dialog window, // window type/name/... atom member variable on Client struct // TODO: get_atom probably not working correctly -// TODO: important: do not lay out non-regular windows // TODO: important: code cleanliness, ewmh!! -// TODO: config command line utility(sockets), avoid global vars +// TODO: config command line utility(sockets), maybe avoid global vars #define RETURN_IF_NULL(c) \ if (c == NULL) \ @@ -35,6 +35,8 @@ if (c == NULL) \ typedef struct Client Client; typedef struct Monitor Monitor; +typedef struct Keybind Keybind; +typedef struct Arg Arg; enum Direction { UP, @@ -63,11 +65,30 @@ struct Client { Window window; Client *prev; Client *next; + char *name; bool has_border; + bool is_floating; // linked list is not sufficent for manual tiling. // will propably need a tree. }; +struct Arg { + int i; + unsigned int ui; + Client *c; + char* s; + char **sl; + + int count; +}; + +struct Keybind { + unsigned int mask; + KeySym keysym; + void (*func)(Arg*); + Arg args; +}; + static Display *wm_display; static Monitor *wm_monitors; static Monitor *wm_smon; @@ -75,11 +96,17 @@ static int wm_mc; static bool wm_other_wm; static Client wm_root; static Window wm_dock = -1; + +/* global configuration variables */ +// TODO: active layout not working static void (*wm_active_layout)(Monitor*); -static float wm_ms_p; -static unsigned int wm_border_col = 0x222222; -static unsigned int wm_focused_border_col = 0x444444; -static unsigned char wm_border_width = 2; +static float wm_cfg_ms_p = 0.5; +static char wm_cfg_border_col[] = "#222222"; +static char wm_cfg_focused_border_col[] = "#444444"; +static unsigned char wm_cfg_border_width = 2; +static Keybind *wm_cfg_keybinds; +static int wm_cfg_kb_count; +static bool wm_cfg_focus_on_motion = true; static int wm_socket_fd; @@ -92,6 +119,7 @@ void wm_configure_handler(XConfigureRequestEvent e); void wm_keyrelease_handler(XKeyReleasedEvent e); void wm_keypress_handler(XKeyPressedEvent e); void wm_maprequest_handler(XMapRequestEvent e); +void wm_motion_handler(XMotionEvent e); Monitor wm_monitor_open(Display *d, XineramaScreenInfo info); void wm_monitors_open_all(Display *d); @@ -125,11 +153,20 @@ bool wm_window_is_dock(Window w); XWindowChanges wm_client_to_xwchanges(Client c); Client* wm_client_find(Window w); +void wm_spawn(char **str); void wm_switch_ws(int ws); void wm_mainloop(); void wm_init(); +void wm_grab_keys(); +void wm_kb_spawn(Arg *args); +void wm_kb_kill(Arg *args); +void wm_kb_switch_ws(Arg *args); +void wm_kb_focus_dir(Arg *args); + +void wm_keybinds_init_def(); + struct sockaddr wm_socket_init(); void wm_socket_cleanup(); void wm_settings_message_parse(char *c, int len);