/* * BadWM - minimalistic window manager for the X Window System * Copyright (C) Robert Annessi * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "include/BadWM.h" #include #include #include #include #include #include #include "include/config.h" Display *dpy; int num_screens; ScreenInfo *screens; ScreenInfo *current_screen; Client *current = NULL; Window initialising = None; XFontStruct *font; Client *head_client; Atom xa_wm_state; Atom xa_wm_change_state; Atom xa_wm_protos; Atom xa_wm_delete; Atom xa_wm_cmapwins; Cursor arrow_curs; Cursor move_curs; Cursor resize_cursors[8]; const char *opt_display = ""; const char *opt_font = DEF_FONT; const char **opt_term = NULL; int opt_bw = DEF_BW; int vdesk = KEY_TO_VDESK(XK_1); int have_shape, shape_event; int quitting = 0; unsigned int numlockmask = 0; static void *xmalloc(size_t size); static void *xmalloc(size_t size) { void *ptr = malloc(size); if (!ptr) { exit(1); } return ptr; } int main(int argc, char *argv[]) { struct sigaction act; XEvent ev; int c; int i; initstr(); while(1) { #ifdef DEBUG c = getopt(argc, argv, "d:vh"); #else c = getopt(argc, argv, "vh"); #endif if (c == -1) break; switch(c) { #ifdef DEBUG case 'd': config.global->debug = is_int(optarg); break; #endif case 'v': printf(PACKAGE_NAME" Version "VERSION"\n"); exit(0); break; case 'h': printf("See the manpage. man 1 "PACKAGE_NAME"\n"); exit(0); break; default: printf("-h for more info!\n"); exit(1); break; } } act.sa_handler = handle_signal; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGHUP, &act, NULL); setconf(); setup_display(); have_shape = XShapeQueryExtension(dpy, &shape_event, &i); /* main event loop here */ for (;;) { XNextEvent(dpy, &ev); switch (ev.type) { case KeyPress: handle_key_event(&ev.xkey); break; case ButtonPress: handle_button_event(&ev.xbutton); break; case ConfigureRequest: handle_configure_request(&ev.xconfigurerequest); break; case MapRequest: handle_map_request(&ev.xmaprequest); break; case ClientMessage: handle_client_message(&ev.xclient); break; case EnterNotify: handle_enter_event(&ev.xcrossing); break; case PropertyNotify: handle_property_change(&ev.xproperty); break; case UnmapNotify: handle_unmap_event(&ev.xunmap); break; default: if (have_shape && ev.type == shape_event) { handle_shape_event((XShapeEvent *)&ev); } break; } } return 1; } void setup_display() { XGCValues gv; XSetWindowAttributes attr; XColor dummy; XModifierKeymap *modmap; KeySym *keysym; /* used in scanning windows (XQueryTree) */ unsigned int i, j, nwins; Window dw1, dw2, *wins; XWindowAttributes winattr; dpy = XOpenDisplay(opt_display); if (!dpy) { fprintf(stderr, "can't open display %s\n", opt_display); exit(2); } XSetErrorHandler(handle_xerror); xa_wm_state = XInternAtom(dpy, "WM_STATE", False); xa_wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); xa_wm_protos = XInternAtom(dpy, "WM_PROTOCOLS", False); xa_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); font = XLoadQueryFont(dpy, opt_font); if (!font) font = XLoadQueryFont(dpy, DEF_FONT); arrow_curs = XCreateFontCursor(dpy, XC_top_left_arrow); move_curs = XCreateFontCursor(dpy, XC_fleur); resize_cursors[NorthWest] = XCreateFontCursor(dpy,XC_top_left_corner); resize_cursors[North] = XCreateFontCursor(dpy,XC_top_side); resize_cursors[NorthEast] = XCreateFontCursor(dpy,XC_top_right_corner); resize_cursors[East] = XCreateFontCursor(dpy,XC_right_side); resize_cursors[SouthEast] = XCreateFontCursor(dpy,XC_bottom_right_corner); resize_cursors[South] = XCreateFontCursor(dpy,XC_bottom_side); resize_cursors[SouthWest] = XCreateFontCursor(dpy,XC_bottom_left_corner); resize_cursors[West] = XCreateFontCursor(dpy,XC_left_side); /* find out which modifier is NumLock - we'll use this when grabbing * every combination of modifiers we can think of */ modmap = XGetModifierMapping(dpy); for (i = 0; i < 8; i++) { for (j = 0; j < modmap->max_keypermod; j++) { if (modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode(dpy, XK_Num_Lock)) { numlockmask = (1<fid; /* set up root window attributes - same for each screen */ attr.event_mask = ChildMask | PropertyChangeMask | EnterWindowMask | LeaveWindowMask | ButtonMask ; /* now set up each screen in turn */ num_screens = ScreenCount(dpy); screens = (ScreenInfo *)xmalloc(num_screens * sizeof(ScreenInfo)); for (i = 0; i < num_screens; i++) { char *ds, *colon, *dot; ds = DisplayString(dpy); /* set up DISPLAY environment variable to use */ colon = rindex(ds, ':'); if (colon && num_screens > 1) { screens[i].display = (char *)xmalloc(14 + strlen(ds)); strcpy(screens[i].display, "DISPLAY="); strcat(screens[i].display, ds); colon = rindex(screens[i].display, ':'); dot = index(colon, '.'); if (!dot) dot = colon + strlen(colon); snprintf(dot, 5, ".%d", i); } else screens[i].display = NULL; screens[i].screen = i; screens[i].root = RootWindow(dpy, i); XAllocNamedColor(dpy, DefaultColormap(dpy, i), config.theme->fgcolor, &screens[i].fg, &dummy); XAllocNamedColor(dpy, DefaultColormap(dpy, i), config.theme->bgcolor, &screens[i].bg, &dummy); XAllocNamedColor(dpy, DefaultColormap(dpy, i), config.theme->fxcolor, &screens[i].fc, &dummy); screens[i].invert_gc = XCreateGC(dpy, screens[i].root, GCFunction | GCSubwindowMode | GCLineWidth | GCFont, &gv); XChangeWindowAttributes(dpy, screens[i].root, CWEventMask, &attr); grab_keysym(screens[i].root, Mod1Mask, *keysym); #ifdef DEBUG /* scan all the windows on this screen */ bad_debug(1,"main:XQueryTree()\n"); #endif XQueryTree(dpy, screens[i].root, &dw1, &dw2, &wins, &nwins); #ifdef DEBUG bad_debug(1,"%d windows\n", nwins); #endif for (j = 0; j < nwins; j++) { XGetWindowAttributes(dpy, wins[j], &winattr); if (!winattr.override_redirect && winattr.map_state == IsViewable) make_new_client(wins[j], &screens[i]); } XFree(wins); XDefineCursor(dpy,screens[i].root,arrow_curs); } current_screen = find_screen(DefaultScreen(dpy)); }