/* The GPLv3 License (GPLv3) Copyright (c) 2022 Akos Horvath This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "handler.h" #include "wm.h" #include "client.h" /* global configuration variables */ // TODO: active layout not working static int wm_xerror_handler(Wm *wm, Display *display, XErrorEvent *e) { printf("wm: Error occured. id: %d req_code: %d\n", e->error_code, e->request_code); char etext[200]; XGetErrorText(wm->display, e->error_code, etext, 200); printf("%s\n", etext); if (e->error_code == BadAccess) { wm->other_wm = true; } return 0; } static int wm_other_wm_handler(Display *display, XErrorEvent *e) { return 0; } // maybe need to handle non-normal windows too void wm_create_handler(Wm *wm, XCreateWindowEvent e) { DEBUG_PRINT("CreateNotify event\n"); // Client *nc; // Client *c; // Client t; // unsigned char *prop_ret; // unsigned long nitems_ret; // Atom type; // bool is_normal = false; // t.window = e.window; // t.m = wm->smon; // t.ws = wm->smon->selws; // t.hidden = true; // //wm_client_is_dock(&t); // /* // _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) // is_normal = true; // // if (!is_normal) { // DEBUG_PRINT("Create handler: window %d is not normal, returning", // (int)e.window) // return; // } // nc = malloc(sizeof(Client*)); // *nc = t; // if (wm->smon->clients == NULL) { // wm->smon->clients = nc; // nc->prev = NULL; // } else { // c = wm_get_last_client(*nc->m); // //c = &wm_root; // c->next = nc; // nc->prev = c; // nc->next = NULL; // } // // XSelectInput(wm->display, nc->window, FocusChangeMask | EnterWindowMask); // DEBUG_PRINT("%d window created,", nc->window); // DEBUG_PRINT("client ws: %d\n", nc->ws); // // wm_client_is_dock(nc); // wm_mstack(nc->m); //wm_client_focus(c); } // TODO void wm_destroy_handler(Wm *wm, XDestroyWindowEvent e) { DEBUG_PRINT("DestroyNotify event\n"); Client *c; // TODO: make function for linked list management for (c = wm->smon->clients; c; c = c->next) { if (e.window == c->window) { if (c == wm->smon->clients) { if (c->next) wm->smon->clients = c->next; else wm->smon->clients = NULL; } else { if (!c->next) c->prev->next = NULL; else { c->prev->next = c->next; c->next->prev = c->prev; } } free(c); } } } void wm_reparent_handler(XReparentEvent e) { DEBUG_PRINT("ReparentNotify event\n"); } void wm_keyrelease_handler(XKeyReleasedEvent e) { DEBUG_PRINT("KeyReleased event, code: %d\n", e.keycode) } void wm_keypress_handler(Wm *wm, XKeyPressedEvent e) { DEBUG_PRINT("KeyPressed event, code: %d\n", e.keycode) Client *c; Keybind k; DEBUG_PRINT("wm->cfg_kb_count: %d\n", wm->cfg_kb_count); 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)(wm, &k.args); } } } void wm_maprequest_handler(Wm *wm, XMapRequestEvent e) { DEBUG_PRINT("MapRequest event\n") if (e.window == wm->root.window) fprintf(stderr, "%s e.window was root\n", __func__); Client *c; c = wm_client_find(wm, e.window); if (c) { DEBUG_PRINT("%s: client found, mapping window\n", __func__) XMapWindow(wm->display, e.window); c->hidden = false; return; } if (wm_window_is_dock(wm, e.window)) { DEBUG_PRINT("%s: window is dock, mapping window\n", __func__) XMapWindow(wm->display, e.window); return; } DEBUG_PRINT("%s: client not found, creating client\n", __func__) c = wm_client_create(wm, e.window); RETURN_IF_NULL(c) //XMapWindow(wm->display, c->window); wm_layout(wm, c->m); } void wm_motion_handler(Wm *wm, XMotionEvent e) { Client *c; c = wm_client_find(wm, e.window); RETURN_IF_NULL(c) if(!wm_client_is_focused(wm, c) && wm->cfg_focus_on_motion) wm_client_focus(wm, c); } // TODO void wm_configure_handler(Wm *wm, XConfigureRequestEvent e) { DEBUG_PRINT("ConfigureRequest event\n"); Client *c; unsigned char *prop_ret; unsigned long nitems_ret; Atom type; bool is_normal = false; XTextProperty xtp; c = wm_client_create(wm, e.window); XGetWMName(wm->display, e.window, &xtp); DEBUG_PRINT("%s: created window %d name: %s\n", __func__, (int)e.window, xtp.value); //XFree(xtp); char *name = "_NET_WM_WINDOW_TYPE"; type = wm_client_get_atom(wm, c, "_NET_WM_WINDOW_TYPE", &prop_ret, &nitems_ret); if (type == -1) { fprintf(stderr, "wm_client_get_atom failed\n"); return; } for (int i = 0; i < nitems_ret; i++) { 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) { is_normal = true; } else if (strcmp(XGetAtomName(wm->display, ((Atom*)prop_ret)[i]), "_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; } } if (!is_normal) { DEBUG_PRINT("configure handler: window %d is not normal, returning\n", (int)e.window) wm_client_free(wm, c); return; } wm_layout(wm, c->m); }