fixed several stuff (gridwm gets better and better)
16c67f32
10 file(s) · +59 −141
| 2 | 2 | ------ |
|
| 3 | 3 | ||
| 4 | 4 | gridwm is an automatic X11 window manager which arranges all windows in a grid. |
|
| 5 | + | One goal is not to exceed 3kSLOC. |
|
| 5 | 6 | ||
| 6 | 7 | ||
| 7 | 8 | Requirements |
| 51 | 51 | c->r[RFloat].height = wa->height; |
|
| 52 | 52 | c->border = wa->border_width; |
|
| 53 | 53 | XSetWindowBorderWidth(dpy, c->win, 0); |
|
| 54 | - | c->proto = win_proto(c->win); |
|
| 55 | 54 | XGetTransientForHint(dpy, c->win, &c->trans); |
|
| 56 | 55 | if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags) |
|
| 57 | 56 | c->size.flags = PSize; |
|
| 59 | 58 | (c->size.flags & PMinSize && c->size.flags & PMaxSize |
|
| 60 | 59 | && c->size.min_width == c->size.max_width |
|
| 61 | 60 | && c->size.min_height == c->size.max_height); |
|
| 62 | - | XAddToSaveSet(dpy, c->win); |
|
| 63 | 61 | update_client_name(c); |
|
| 64 | 62 | twa.override_redirect = 1; |
|
| 65 | 63 | twa.background_pixmap = ParentRelative; |
|
| 87 | 85 | XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
|
| 88 | 86 | XFlush(dpy); |
|
| 89 | 87 | } |
|
| 88 | + | ||
| 89 | + | Client * |
|
| 90 | + | getclient(Window w) |
|
| 91 | + | { |
|
| 92 | + | Client *c; |
|
| 93 | + | for(c = clients; c; c = c->next) |
|
| 94 | + | if(c->win == w) |
|
| 95 | + | return c; |
|
| 96 | + | return NULL; |
|
| 97 | + | } |
|
| 10 | 10 | #define STATUSCMD "echo -n `date` `uptime | sed 's/.*://; s/,//g'`" \ |
|
| 11 | 11 | " `acpi | awk '{print $4}' | sed 's/,//'`" |
|
| 12 | 12 | #define KEYS \ |
|
| 13 | - | { Mod1Mask, XK_Return, run, "xterm -u8 -bg black -fg white -fn -*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*" }, |
|
| 13 | + | { Mod1Mask, XK_Return, run, "xterm -u8 -bg black -fg white -fn '-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*'" }, \ |
|
| 14 | + | { Mod1Mask | ShiftMask, XK_q, quit, NULL}, |
|
| 15 | + |
| 16 | 16 | static void enternotify(XEvent *e); |
|
| 17 | 17 | static void leavenotify(XEvent *e); |
|
| 18 | 18 | static void expose(XEvent *e); |
|
| 19 | - | static void keypress(XEvent *e); |
|
| 20 | 19 | static void keymapnotify(XEvent *e); |
|
| 21 | 20 | static void maprequest(XEvent *e); |
|
| 22 | 21 | static void propertynotify(XEvent *e); |
|
| 47 | 46 | static void |
|
| 48 | 47 | configurerequest(XEvent *e) |
|
| 49 | 48 | { |
|
| 50 | - | #if 0 |
|
| 51 | 49 | XConfigureRequestEvent *ev = &e->xconfigurerequest; |
|
| 52 | 50 | XWindowChanges wc; |
|
| 53 | - | XRectangle *frect; |
|
| 54 | 51 | Client *c; |
|
| 55 | 52 | ||
| 56 | - | c = client_of_win(ev->window); |
|
| 53 | + | c = getclient(ev->window); |
|
| 57 | 54 | ev->value_mask &= ~CWSibling; |
|
| 58 | 55 | if(c) { |
|
| 59 | - | gravitate_client(c, True); |
|
| 60 | - | ||
| 61 | 56 | if(ev->value_mask & CWX) |
|
| 62 | - | c->rect.x = ev->x; |
|
| 57 | + | c->r[RFloat].x = ev->x; |
|
| 63 | 58 | if(ev->value_mask & CWY) |
|
| 64 | - | c->rect.y = ev->y; |
|
| 59 | + | c->r[RFloat].y = ev->y; |
|
| 65 | 60 | if(ev->value_mask & CWWidth) |
|
| 66 | - | c->rect.width = ev->width; |
|
| 61 | + | c->r[RFloat].width = ev->width; |
|
| 67 | 62 | if(ev->value_mask & CWHeight) |
|
| 68 | - | c->rect.height = ev->height; |
|
| 63 | + | c->r[RFloat].height = ev->height; |
|
| 69 | 64 | if(ev->value_mask & CWBorderWidth) |
|
| 70 | 65 | c->border = ev->border_width; |
|
| 71 | - | ||
| 72 | - | gravitate_client(c, False); |
|
| 73 | - | ||
| 74 | - | if(c->frame) { |
|
| 75 | - | if(c->sel->area->floating) |
|
| 76 | - | frect=&c->sel->rect; |
|
| 77 | - | else |
|
| 78 | - | frect=&c->sel->revert; |
|
| 79 | - | ||
| 80 | - | if(c->rect.width >= screen->rect.width && c->rect.height >= screen->rect.height) { |
|
| 81 | - | frect->y = wc.y = -height_of_bar(); |
|
| 82 | - | frect->x = wc.x = -def.border; |
|
| 83 | - | } |
|
| 84 | - | else { |
|
| 85 | - | frect->y = wc.y = c->rect.y - height_of_bar(); |
|
| 86 | - | frect->x = wc.x = c->rect.x - def.border; |
|
| 87 | - | } |
|
| 88 | - | frect->width = wc.width = c->rect.width + 2 * def.border; |
|
| 89 | - | frect->height = wc.height = c->rect.height + def.border |
|
| 90 | - | + height_of_bar(); |
|
| 91 | - | wc.border_width = 1; |
|
| 92 | - | wc.sibling = None; |
|
| 93 | - | wc.stack_mode = ev->detail; |
|
| 94 | - | if(c->sel->area->view != screen->sel) |
|
| 95 | - | wc.x += 2 * screen->rect.width; |
|
| 96 | - | if(c->sel->area->floating) { |
|
| 97 | - | XConfigureWindow(dpy, c->framewin, ev->value_mask, &wc); |
|
| 98 | - | configure_client(c); |
|
| 99 | - | } |
|
| 100 | - | } |
|
| 101 | 66 | } |
|
| 102 | 67 | ||
| 103 | 68 | wc.x = ev->x; |
|
| 104 | 69 | wc.y = ev->y; |
|
| 105 | 70 | wc.width = ev->width; |
|
| 106 | 71 | wc.height = ev->height; |
|
| 107 | - | ||
| 108 | - | if(c && c->frame) { |
|
| 109 | - | wc.x = def.border; |
|
| 110 | - | wc.y = height_of_bar(); |
|
| 111 | - | wc.width = c->sel->rect.width - 2 * def.border; |
|
| 112 | - | wc.height = c->sel->rect.height - def.border - height_of_bar(); |
|
| 113 | - | } |
|
| 114 | - | ||
| 115 | 72 | wc.border_width = 0; |
|
| 116 | 73 | wc.sibling = None; |
|
| 117 | 74 | wc.stack_mode = Above; |
|
| 118 | 75 | ev->value_mask &= ~CWStackMode; |
|
| 119 | 76 | ev->value_mask |= CWBorderWidth; |
|
| 120 | 77 | XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); |
|
| 121 | - | ||
| 122 | 78 | XFlush(dpy); |
|
| 123 | - | #endif |
|
| 124 | 79 | } |
|
| 125 | 80 | ||
| 126 | 81 | static void |
|
| 182 | 137 | } |
|
| 183 | 138 | ||
| 184 | 139 | static void |
|
| 185 | - | keypress(XEvent *e) |
|
| 186 | - | { |
|
| 187 | - | #if 0 |
|
| 188 | - | XKeyEvent *ev = &e->xkey; |
|
| 189 | - | KeySym k = 0; |
|
| 190 | - | char buf[32]; |
|
| 191 | - | int n; |
|
| 192 | - | static Frame *f; |
|
| 193 | - | ||
| 194 | - | ||
| 195 | - | ev->state &= valid_mask; |
|
| 196 | - | if((f = frame_of_win(ev->window))) { |
|
| 197 | - | buf[0] = 0; |
|
| 198 | - | n = XLookupString(ev, buf, sizeof(buf), &k, 0); |
|
| 199 | - | if(IsFunctionKey(k) || IsKeypadKey(k) || IsMiscFunctionKey(k) |
|
| 200 | - | || IsPFKey(k) || IsPrivateKeypadKey(k)) |
|
| 201 | - | return; |
|
| 202 | - | buf[n] = 0; |
|
| 203 | - | blitz_kpress_input(&f->tagbar, ev->state, k, buf); |
|
| 204 | - | } |
|
| 205 | - | else |
|
| 206 | - | key(root, ev->state, (KeyCode) ev->keycode); |
|
| 207 | - | #endif |
|
| 208 | - | } |
|
| 209 | - | ||
| 210 | - | static void |
|
| 211 | 140 | keymapnotify(XEvent *e) |
|
| 212 | 141 | { |
|
| 213 | 142 | #if 0 |
|
| 231 | 160 | } |
|
| 232 | 161 | ||
| 233 | 162 | /*if(!client_of_win(ev->window))*/ |
|
| 234 | - | manage(create_client(ev->window, &wa)); |
|
| 163 | + | /*manage(create_client(ev->window, &wa));*/ |
|
| 164 | + | XMapRaised(dpy, ev->window); |
|
| 165 | + | XMoveResizeWindow(dpy, ev->window, rect.x, rect.y, rect.width, rect.height - barrect.height); |
|
| 166 | + | XSetInputFocus(dpy, ev->window, RevertToPointerRoot, CurrentTime); |
|
| 167 | + | XFlush(dpy); |
|
| 235 | 168 | } |
|
| 236 | 169 | ||
| 237 | 170 | static void |
|
| 38 | 38 | font->set = XCreateFontSet(blitz->dpy, fontname, &missing, &n, &def); |
|
| 39 | 39 | if(missing) { |
|
| 40 | 40 | while(n--) |
|
| 41 | - | fprintf(stderr, "liblitz: missing fontset: %s\n", missing[n]); |
|
| 41 | + | fprintf(stderr, "missing fontset: %s\n", missing[n]); |
|
| 42 | 42 | XFreeStringList(missing); |
|
| 43 | 43 | if(font->set) { |
|
| 44 | 44 | XFreeFontSet(blitz->dpy, font->set); |
|
| 72 | 72 | font->xfont = XLoadQueryFont(blitz->dpy, fontname); |
|
| 73 | 73 | } |
|
| 74 | 74 | if (!font->xfont) { |
|
| 75 | - | fprintf(stderr, "%s", "liblitz: error, cannot load 'fixed' font\n"); |
|
| 75 | + | fprintf(stderr, "%s", "error, cannot load 'fixed' font\n"); |
|
| 76 | 76 | exit(1); |
|
| 77 | 77 | } |
|
| 78 | 78 | font->ascent = font->xfont->ascent; |
|
| 24 | 24 | XGrabKey(dpy, code, key[i].mod, root, True, GrabModeAsync, GrabModeAsync); |
|
| 25 | 25 | } |
|
| 26 | 26 | } |
|
| 27 | + | ||
| 28 | + | void |
|
| 29 | + | keypress(XEvent *e) |
|
| 30 | + | { |
|
| 31 | + | XKeyEvent *ev = &e->xkey; |
|
| 32 | + | unsigned int i, len; |
|
| 33 | + | KeySym keysym; |
|
| 34 | + | ||
| 35 | + | keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); |
|
| 36 | + | len = sizeof(key) / sizeof(key[0]); |
|
| 37 | + | for(i = 0; i < len; i++) |
|
| 38 | + | if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { |
|
| 39 | + | if(key[i].func) |
|
| 40 | + | key[i].func(key[i].arg); |
|
| 41 | + | return; |
|
| 42 | + | } |
|
| 43 | + | } |
| 358 | 358 | ||
| 359 | 359 | char buf[256]; |
|
| 360 | 360 | ||
| 361 | - | fputs(STATUSCMD, stdout); |
|
| 362 | - | fputs("\n", stdout); |
|
| 363 | 361 | pipe_spawn(buf, sizeof(buf), NULL, STATUSCMD); |
|
| 364 | 362 | fputs(buf, stderr); |
|
| 365 | 363 |
| 93 | 93 | return; |
|
| 94 | 94 | if(fork() == 0) { |
|
| 95 | 95 | if(fork() == 0) { |
|
| 96 | - | setsid(); |
|
| 97 | 96 | if(dpy) |
|
| 98 | 97 | close(ConnectionNumber(dpy)); |
|
| 99 | - | execlp(shell, "shell", "-c", cmd, NULL); |
|
| 100 | - | fprintf(stderr, "gridwm: execvp %s", cmd); |
|
| 98 | + | setsid(); |
|
| 99 | + | fprintf(stderr, "gridwm: execlp %s %s -c %s", shell, shell, cmd); |
|
| 100 | + | execlp(shell, shell, "-c", cmd, NULL); |
|
| 101 | + | fprintf(stderr, "gridwm: execlp %s", cmd); |
|
| 101 | 102 | perror(" failed"); |
|
| 102 | 103 | } |
|
| 103 | 104 | exit (0); |
|
| 123 | 124 | } |
|
| 124 | 125 | ||
| 125 | 126 | if(fork() == 0) { |
|
| 126 | - | setsid(); |
|
| 127 | 127 | if(dpy) |
|
| 128 | 128 | close(ConnectionNumber(dpy)); |
|
| 129 | + | setsid(); |
|
| 129 | 130 | dup2(pfd[1], STDOUT_FILENO); |
|
| 130 | 131 | close(pfd[0]); |
|
| 131 | 132 | close(pfd[1]); |
|
| 132 | - | execlp(shell, "shell", "-c", cmd, NULL); |
|
| 133 | - | fprintf(stderr, "gridwm: execvp %s", cmd); |
|
| 133 | + | execlp(shell, shell, "-c", cmd, NULL); |
|
| 134 | + | fprintf(stderr, "gridwm: execlp %s", cmd); |
|
| 134 | 135 | perror(" failed"); |
|
| 135 | 136 | } |
|
| 136 | 137 | else { |
|
| 16 | 16 | /* X structs */ |
|
| 17 | 17 | Display *dpy; |
|
| 18 | 18 | Window root, barwin; |
|
| 19 | - | Atom wm_atom[WMLast], net_atom[NetLast]; |
|
| 19 | + | Atom net_atom[NetLast]; |
|
| 20 | 20 | Cursor cursor[CurLast]; |
|
| 21 | 21 | XRectangle rect, barrect; |
|
| 22 | 22 | Bool running = True; |
|
| 23 | - | Client *client = NULL; |
|
| 23 | + | Client *clients = NULL; |
|
| 24 | 24 | ||
| 25 | 25 | char *bartext, tag[256]; |
|
| 26 | 26 | int screen, sel_screen; |
|
| 63 | 63 | XFree(wins); |
|
| 64 | 64 | } |
|
| 65 | 65 | ||
| 66 | - | static int |
|
| 67 | - | win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) |
|
| 68 | - | { |
|
| 69 | - | Atom real; |
|
| 70 | - | int format; |
|
| 71 | - | unsigned long res, extra; |
|
| 72 | - | int status; |
|
| 73 | - | ||
| 74 | - | status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, |
|
| 75 | - | &res, &extra, prop); |
|
| 76 | - | ||
| 77 | - | if(status != Success || *prop == NULL) { |
|
| 78 | - | return 0; |
|
| 79 | - | } |
|
| 80 | - | if(res == 0) |
|
| 81 | - | free((void *) *prop); |
|
| 82 | - | return res; |
|
| 83 | - | } |
|
| 84 | - | ||
| 85 | - | int |
|
| 86 | - | win_proto(Window w) |
|
| 87 | - | { |
|
| 88 | - | Atom *protocols; |
|
| 89 | - | long res; |
|
| 90 | - | int protos = 0; |
|
| 91 | - | int i; |
|
| 92 | - | ||
| 93 | - | res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, |
|
| 94 | - | ((unsigned char **) &protocols)); |
|
| 95 | - | if(res <= 0) { |
|
| 96 | - | return protos; |
|
| 97 | - | } |
|
| 98 | - | for(i = 0; i < res; i++) { |
|
| 99 | - | if(protocols[i] == wm_atom[WMDelete]) |
|
| 100 | - | protos |= WM_PROTOCOL_DELWIN; |
|
| 101 | - | } |
|
| 102 | - | free((char *) protocols); |
|
| 103 | - | return protos; |
|
| 104 | - | } |
|
| 105 | - | ||
| 106 | 66 | /* |
|
| 107 | 67 | * There's no way to check accesses to destroyed windows, thus |
|
| 108 | 68 | * those cases are ignored (especially on UnmapNotify's). |
|
| 201 | 161 | x_error_handler = XSetErrorHandler(error_handler); |
|
| 202 | 162 | ||
| 203 | 163 | /* init atoms */ |
|
| 204 | - | wm_atom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
|
| 205 | - | wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
|
| 206 | - | wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
|
| 207 | 164 | net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
|
| 208 | 165 | net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
|
| 209 | 166 | ||
| 242 | 199 | XMapRaised(dpy, barwin); |
|
| 243 | 200 | draw_bar(); |
|
| 244 | 201 | ||
| 245 | - | wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask; |
|
| 202 | + | wa.event_mask = SubstructureRedirectMask | EnterWindowMask \ |
|
| 203 | + | | LeaveWindowMask; |
|
| 246 | 204 | wa.cursor = cursor[CurNormal]; |
|
| 247 | 205 | XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |
|
| 248 | 206 | ||
| 10 | 10 | #include <X11/Xutil.h> |
|
| 11 | 11 | ||
| 12 | 12 | /* atoms */ |
|
| 13 | - | enum { WMState, WMProtocols, WMDelete, WMLast }; |
|
| 14 | 13 | enum { NetSupported, NetWMName, NetLast }; |
|
| 15 | 14 | ||
| 16 | 15 | /* cursor */ |
|
| 25 | 24 | struct Client { |
|
| 26 | 25 | char name[256]; |
|
| 27 | 26 | char tag[256]; |
|
| 28 | - | int proto; |
|
| 29 | 27 | unsigned int border; |
|
| 30 | 28 | Bool fixedsize; |
|
| 31 | 29 | Window win; |
|
| 46 | 44 | ||
| 47 | 45 | extern Display *dpy; |
|
| 48 | 46 | extern Window root, barwin; |
|
| 49 | - | extern Atom wm_atom[WMLast], net_atom[NetLast]; |
|
| 47 | + | extern Atom net_atom[NetLast]; |
|
| 50 | 48 | extern Cursor cursor[CurLast]; |
|
| 51 | 49 | extern XRectangle rect, barrect; |
|
| 52 | 50 | extern Bool running; |
|
| 57 | 55 | extern char *bartext, tag[256]; |
|
| 58 | 56 | ||
| 59 | 57 | extern Brush brush; |
|
| 60 | - | extern Client *client; |
|
| 58 | + | extern Client *clients; |
|
| 61 | 59 | ||
| 62 | 60 | /* bar.c */ |
|
| 63 | 61 | extern void draw_bar(); |
|
| 64 | 62 | ||
| 65 | 63 | /* cmd.c */ |
|
| 66 | 64 | extern void run(char *arg); |
|
| 65 | + | extern void quit(char *arg); |
|
| 67 | 66 | ||
| 68 | 67 | /* client.c */ |
|
| 69 | 68 | extern Client *create_client(Window w, XWindowAttributes *wa); |
|
| 70 | 69 | extern void manage(Client *c); |
|
| 70 | + | extern Client * getclient(Window w); |
|
| 71 | 71 | ||
| 72 | 72 | /* key.c */ |
|
| 73 | 73 | extern void update_keys(); |
|
| 74 | + | extern void keypress(XEvent *e); |
|
| 74 | 75 | ||
| 75 | 76 | /* wm.c */ |
|
| 76 | - | extern int win_proto(Window w); |
|