123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- /*
- * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
- * For license, see COPYING.
- */
- #include <getopt.h>
- #include <X11/keysym.h>
- #include <X11/cursorfont.h>
- #ifdef HAVE_IMLIB2
- #include <Imlib2.h>
- #endif /* HAVE_IMLIB2 */
- #include "wmfs.h"
- #include "event.h"
- #include "ewmh.h"
- #include "screen.h"
- #include "infobar.h"
- #include "util.h"
- #include "config.h"
- #include "client.h"
- #include "fifo.h"
- int
- wmfs_error_handler(Display *d, XErrorEvent *event)
- {
- char mess[256];
- /* Check if there is another WM running */
- if(event->error_code == BadAccess
- && W->root == event->resourceid)
- errl(EXIT_FAILURE, "Another Window Manager is already running.");
- /* Ignore focus change error for unmapped client
- * 42 = X_SetInputFocus
- * 28 = X_GrabButton
- */
- if(client_gb_win(event->resourceid))
- if(event->error_code == BadWindow
- || event->request_code == 42
- || event->request_code == 28)
- return 0;
- if(XGetErrorText(d, event->error_code, mess, 128))
- warnxl("%s(%d) opcodes %d/%d\n resource #%lx\n",
- mess,
- event->error_code,
- event->request_code,
- event->minor_code,
- event->resourceid);
- return 1;
- }
- int
- wmfs_error_handler_dummy(Display *d, XErrorEvent *event)
- {
- (void)d;
- (void)event;
- return 0;
- }
- void
- wmfs_numlockmask(void)
- {
- int i, j;
- XModifierKeymap *mm = XGetModifierMapping(W->dpy);
- for(i = 0; i < 8; i++)
- for(j = 0; j < mm->max_keypermod; ++j)
- if(mm->modifiermap[i * mm->max_keypermod + j]
- == XKeysymToKeycode(W->dpy, XK_Num_Lock))
- W->numlockmask = (1 << i);
- XFreeModifiermap(mm);
- }
- void
- wmfs_init_font(char *font, struct theme *t)
- {
- XFontStruct **xfs = NULL;
- char **misschar, **names, *defstring;
- int d;
- if(!(t->font.fontset = XCreateFontSet(W->dpy, font, &misschar, &d, &defstring)))
- {
- warnxl("Can't load font '%s'", font);
- t->font.fontset = XCreateFontSet(W->dpy, "fixed", &misschar, &d, &defstring);
- }
- XExtentsOfFontSet(t->font.fontset);
- XFontsOfFontSet(t->font.fontset, &xfs, &names);
- t->font.as = xfs[0]->max_bounds.ascent;
- t->font.de = xfs[0]->max_bounds.descent;
- t->font.width = xfs[0]->max_bounds.width;
- t->font.height = t->font.as + t->font.de;
- if(misschar)
- XFreeStringList(misschar);
- }
- static void
- wmfs_xinit(void)
- {
- XGCValues xgc =
- {
- .function = GXinvert,
- .subwindow_mode = IncludeInferiors,
- .line_width = 1
- };
- XSetWindowAttributes at =
- {
- .event_mask = (KeyMask | ButtonMask | MouseMask
- | PropertyChangeMask | SubstructureRedirectMask
- | SubstructureNotifyMask | StructureNotifyMask),
- .cursor = XCreateFontCursor(W->dpy, XC_left_ptr)
- };
- /*
- * X Error handler
- */
- XSetErrorHandler(wmfs_error_handler);
- /*
- * X var
- */
- W->xscreen = DefaultScreen(W->dpy);
- W->xdepth = DefaultDepth(W->dpy, W->xscreen);
- W->gc = DefaultGC(W->dpy, W->xscreen);
- W->xmaxw = DisplayWidth(W->dpy, W->xscreen);
- W->xmaxh = DisplayHeight(W->dpy, W->xscreen);
- /*
- * Keys
- */
- wmfs_numlockmask();
- /*
- * Root window/cursor
- */
- W->root = RootWindow(W->dpy, W->xscreen);
- XChangeWindowAttributes(W->dpy, W->root, CWEventMask | CWCursor, &at);
- W->rgc = XCreateGC(W->dpy, W->root, GCFunction | GCSubwindowMode | GCLineWidth, &xgc);
- /*
- * Locale (font encode)
- */
- setlocale(LC_CTYPE, "");
- /*
- * Barwin linked list
- */
- SLIST_INIT(&W->h.barwin);
- /*
- * Optional dep init
- */
- #ifdef HAVE_IMLIB2
- imlib_context_set_display(W->dpy);
- imlib_context_set_visual(DefaultVisual(W->dpy, W->xscreen));
- imlib_context_set_colormap(DefaultColormap(W->dpy, W->xscreen));
- #endif /* HAVE_IMLIB2 */
- W->flags |= WMFS_RUNNING;
- }
- void
- wmfs_grab_keys(void)
- {
- KeyCode c;
- struct keybind *k;
- wmfs_numlockmask();
- XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root);
- SLIST_FOREACH(k, &W->h.keybind, next)
- if((c = XKeysymToKeycode(W->dpy, k->keysym)))
- {
- XGrabKey(W->dpy, c, k->mod, W->root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(W->dpy, c, k->mod | LockMask, W->root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(W->dpy, c, k->mod | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
- XGrabKey(W->dpy, c, k->mod | LockMask | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
- }
- }
- /** Scan xprops of previous session to set it back
- * Check if there are windows on X (previous sessions windows)
- */
- static void
- wmfs_scan(void)
- {
- struct geo g;
- struct client *c, *cc, *fc;
- struct screen *s;
- int i, n, rf, nscreen = 0;
- int tag = -1, screen = -1, flags = -1;
- unsigned long ir, il;
- long *ret = NULL, *tret;
- bool getg = false;
- XWindowAttributes wa;
- Window usl, usl2, *w = NULL, tm, focus;
- Atom rt;
- SLIST_INIT(&W->h.client);
- W->flags |= WMFS_SCAN;
- /* Get previous selected tag to apply it at the end */
- if(XGetWindowProperty(W->dpy, W->root, W->net_atom[wmfs_current_tag], 0, 32,
- False, XA_CARDINAL, &rt, &rf, &ir, &il,
- (unsigned char**)&tret)
- == Success && ret)
- {
- nscreen = (int)ir;
- }
- /* Previous focused client before reload */
- if(XGetWindowProperty(W->dpy, W->root, W->net_atom[wmfs_focus], 0, 32,
- False, XA_WINDOW, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- focus = *ret;
- XFree(ret);
- }
- if(XQueryTree(W->dpy, W->root, &usl, &usl2, &w, (unsigned int*)&n))
- for(i = n - 1; i != -1; --i)
- {
- XGetWindowAttributes(W->dpy, w[i], &wa);
- if(!wa.override_redirect && wa.map_state == IsViewable)
- {
- if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
- False, XA_CARDINAL, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- tag = *ret;
- XFree(ret);
- }
- if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32,
- False, XA_CARDINAL, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- screen = *ret;
- XFree(ret);
- }
- if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_FLAGS"), 0, 32,
- False, XA_CARDINAL, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- flags = *ret;
- flags &= ~(CLIENT_TABBED | CLIENT_REMOVEALL);
- XFree(ret);
- }
- if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_GEO"), 0, 32,
- False, XA_CARDINAL, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- g.x = ret[0];
- g.y = ret[1];
- g.w = ret[2];
- g.h = ret[3];
- getg = true;
- XFree(ret);
- }
- if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_TABMASTER"), 0, 32,
- False, XA_WINDOW, &rt, &rf, &ir, &il,
- (unsigned char**)&ret)
- == Success && ret)
- {
- tm = *ret;
- XFree(ret);
- }
- c = client_new(w[i], &wa, true);
- if(tm != c->win)
- c->tmp = tm;
- tm = 0;
- if(flags != -1)
- c->flags |= flags;
- if(tag != -1 && screen != -1)
- {
- c->screen = screen_gb_id(screen);
- if(getg)
- c->flags |= CLIENT_IGNORE_LAYOUT;
- client_map(c);
- tag_client(tag_gb_id(c->screen, tag), c);
- if(getg)
- client_moveresize(c, &g);
- client_get_name(c);
- }
- }
- }
- if(!nscreen)
- {
- SLIST_FOREACH(s, &W->h.screen, next)
- if(!TAILQ_EMPTY(&s->tags))
- tag_screen(s, TAILQ_FIRST(&s->tags));
- }
- else
- {
- /* Set back selected tag */
- for(i = 0; i < nscreen; ++i)
- {
- s = screen_gb_id(i);
- tag_screen(s, tag_gb_id(s, tret[i]));
- }
- }
- /* Re-adjust tabbed clients */
- SLIST_FOREACH(c, &W->h.client, next)
- if((cc = client_gb_win(c->tmp)) && cc != c)
- _client_tab(c, cc);
- if((fc = client_gb_win(focus)) && fc != W->client)
- client_focus(fc);
- W->flags &= ~WMFS_SCAN;
- if(tret)
- XFree(tret);
- XFree(w);
- XSync(W->dpy, false);
- }
- static void
- wmfs_loop(void)
- {
- XEvent ev;
- int maxfd, fd = ConnectionNumber(W->dpy);
- fd_set iset;
- while(W->flags & WMFS_RUNNING)
- {
- maxfd = fd + 1;
- FD_ZERO(&iset);
- FD_SET(fd, &iset);
- if(W->fifo.fd > 0)
- {
- maxfd += W->fifo.fd;
- FD_SET(W->fifo.fd, &iset);
- }
- if(select(maxfd, &iset, NULL, NULL, NULL) > 0)
- {
- if(FD_ISSET(fd, &iset))
- {
- while((W->flags & WMFS_RUNNING) && XPending(W->dpy))
- {
- XNextEvent(W->dpy, &ev);
- EVENT_HANDLE(&ev);
- }
- }
- else if(W->fifo.fd > 0 && FD_ISSET(W->fifo.fd, &iset))
- fifo_read();
- }
- }
- }
- static inline void
- wmfs_init(void)
- {
- log_init();
- wmfs_xinit();
- ewmh_init();
- screen_init();
- event_init();
- config_init();
- fifo_init();
- }
- void
- wmfs_quit(void)
- {
- struct keybind *k;
- struct rule *r;
- struct theme *t;
- struct client *c;
- struct mousebind *m;
- /* Will free:
- *
- * Screens -> tags
- * -> Infobars -> Elements
- */
- ewmh_update_wmfs_props();
- screen_free();
- XFreeGC(W->dpy, W->rgc);
- while(!SLIST_EMPTY(&W->h.client))
- {
- c = SLIST_FIRST(&W->h.client);
- client_update_props(c, CPROP_LOC | CPROP_FLAG | CPROP_GEO);
- c->flags |= (CLIENT_IGNORE_LAYOUT | CLIENT_REMOVEALL);
- client_remove(c);
- }
- /* Conf stuffs */
- while(!SLIST_EMPTY(&W->h.theme))
- {
- t = SLIST_FIRST(&W->h.theme);
- SLIST_REMOVE_HEAD(&W->h.theme, next);
- XFreeFontSet(W->dpy, t->font.fontset);
- free(t);
- }
- while(!SLIST_EMPTY(&W->h.rule))
- {
- r = SLIST_FIRST(&W->h.rule);
- SLIST_REMOVE_HEAD(&W->h.rule, next);
- status_free_ctx(&t->tags_n_sl);
- status_free_ctx(&t->tags_s_sl);
- status_free_ctx(&t->tags_o_sl);
- status_free_ctx(&t->client_n_sl);
- status_free_ctx(&t->client_s_sl);
- free(r->class);
- free(r->instance);
- free(r->role);
- free(r->name);
- free(r);
- }
- while(!SLIST_EMPTY(&W->h.keybind))
- {
- k = SLIST_FIRST(&W->h.keybind);
- SLIST_REMOVE_HEAD(&W->h.keybind, next);
- free((void*)k->cmd);
- free(k);
- }
- while(!SLIST_EMPTY(&W->h.mousebind))
- {
- m = SLIST_FIRST(&W->h.mousebind);
- SLIST_REMOVE_HEAD(&W->h.mousebind, globnext);
- free((void*)m->cmd);
- free(m);
- }
- /* FIFO stuffs */
- if(W->fifo.fd > 0)
- {
- close(W->fifo.fd);
- unlink(W->fifo.path);
- }
- /* close log */
- if(W->log)
- fclose(W->log), W->log = NULL;
- W->flags &= ~WMFS_RUNNING;
- XCloseDisplay(W->dpy);
- }
- /** Reload WMFS binary
- */
- void
- uicb_reload(Uicb cmd)
- {
- (void)cmd;
- W->flags &= ~WMFS_RUNNING;
- W->flags |= WMFS_RELOAD;
- }
- void
- uicb_quit(Uicb cmd)
- {
- (void)cmd;
- W->flags &= ~WMFS_RUNNING;
- }
- int
- main(int argc, char **argv)
- {
- int i;
- bool r;
- (void)argc;
- W = (struct wmfs*)xcalloc(1, sizeof(struct wmfs));
- /* Default path ~/.config/wmfs/wmfsrc */
- sprintf(W->confpath, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
- /* Opt */
- while((i = getopt(argc, argv, "hvC:")) != -1)
- {
- switch(i)
- {
- case 'h':
- printf("usage: %s [-hv] [-C <file>]\n"
- " -h Show this page\n"
- " -v Show WMFS version\n"
- " -C <file> Launch WMFS with a specified configuration file\n", argv[0]);
- free(W);
- exit(EXIT_SUCCESS);
- break;
- case 'v':
- printf("wmfs("WMFS_VERSION") 2 beta\n");
- free(W);
- exit(EXIT_SUCCESS);
- break;
- case 'C':
- strncpy(W->confpath, optarg, sizeof(W->confpath));
- break;
- }
- }
- /* Get X display */
- if(!(W->dpy = XOpenDisplay(NULL)))
- {
- fprintf(stderr, "%s: Can't open X server\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- /* Core */
- wmfs_init();
- wmfs_scan();
- wmfs_loop();
- wmfs_quit();
- r = (W->flags & WMFS_RELOAD);
- free(W);
- if(r)
- execvp(argv[0], argv);
- return 1;
- }
|