aewl

annotate client.c @ 22:bd3a44353916

fixed several other stuff, coming closer to something useful
author Anselm R. Garbe <garbeam@wmii.de>
date Tue, 11 Jul 2006 23:46:39 +0200
parents 3ef108a5ca0a
children 95ffdfd0a819
rev   line source
garbeam@5 1 /*
garbeam@5 2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
garbeam@5 3 * See LICENSE file for license details.
garbeam@5 4 */
garbeam@5 5
garbeam@10 6 #include <stdlib.h>
garbeam@5 7 #include <string.h>
garbeam@5 8 #include <X11/Xatom.h>
garbeam@5 9
garbeam@5 10 #include "util.h"
garbeam@5 11 #include "wm.h"
garbeam@5 12
garbeam@18 13 #define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask | EnterWindowMask)
garbeam@18 14
garbeam@13 15 void
garbeam@13 16 update_name(Client *c)
garbeam@5 17 {
garbeam@5 18 XTextProperty name;
garbeam@5 19 int n;
garbeam@7 20 char **list = NULL;
garbeam@5 21
garbeam@5 22 name.nitems = 0;
garbeam@5 23 c->name[0] = 0;
garbeam@5 24 XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
garbeam@5 25 if(!name.nitems)
garbeam@5 26 XGetWMName(dpy, c->win, &name);
garbeam@5 27 if(!name.nitems)
garbeam@5 28 return;
garbeam@5 29 if(name.encoding == XA_STRING)
garbeam@5 30 strncpy(c->name, (char *)name.value, sizeof(c->name));
garbeam@5 31 else {
garbeam@5 32 if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
garbeam@5 33 && n > 0 && *list)
garbeam@5 34 {
garbeam@5 35 strncpy(c->name, *list, sizeof(c->name));
garbeam@5 36 XFreeStringList(list);
garbeam@5 37 }
garbeam@5 38 }
garbeam@5 39 XFree(name.value);
garbeam@5 40 }
garbeam@5 41
garbeam@10 42 void
garbeam@20 43 update_size(Client *c)
garbeam@20 44 {
garbeam@20 45 XSizeHints size;
garbeam@20 46 long msize;
garbeam@20 47 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
garbeam@20 48 size.flags = PSize;
garbeam@20 49 c->flags = size.flags;
garbeam@21 50 if(c->flags & PBaseSize) {
garbeam@21 51 c->basew = size.base_width;
garbeam@21 52 c->baseh = size.base_height;
garbeam@21 53 }
garbeam@21 54 else
garbeam@21 55 c->basew = c->baseh = 0;
garbeam@21 56 if(c->flags & PResizeInc) {
garbeam@21 57 c->incw = size.width_inc;
garbeam@21 58 c->inch = size.height_inc;
garbeam@21 59 }
garbeam@21 60 else
garbeam@21 61 c->incw = c->inch = 0;
garbeam@21 62 if(c->flags & PMaxSize) {
garbeam@21 63 c->maxw = size.max_width;
garbeam@21 64 c->maxh = size.max_height;
garbeam@21 65 }
garbeam@21 66 else
garbeam@21 67 c->maxw = c->maxh = 0;
garbeam@21 68 if(c->flags & PMinSize) {
garbeam@21 69 c->minw = size.min_width;
garbeam@21 70 c->minh = size.min_height;
garbeam@21 71 }
garbeam@21 72 else
garbeam@21 73 c->minw = c->minh = 0;
garbeam@20 74 }
garbeam@20 75
garbeam@20 76 void
garbeam@13 77 focus(Client *c)
garbeam@13 78 {
garbeam@21 79 Client **l, *old;
garbeam@21 80
garbeam@21 81 old = stack;
garbeam@13 82 for(l=&stack; *l && *l != c; l=&(*l)->snext);
garbeam@13 83 eassert(*l == c);
garbeam@13 84 *l = c->snext;
garbeam@13 85 c->snext = stack;
garbeam@13 86 stack = c;
garbeam@13 87 XRaiseWindow(dpy, c->win);
garbeam@21 88 XRaiseWindow(dpy, c->title);
garbeam@13 89 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
garbeam@21 90 if(old && old != c) {
garbeam@21 91 XMapWindow(dpy, old->title);
garbeam@21 92 draw_client(old);
garbeam@21 93 }
garbeam@21 94 XUnmapWindow(dpy, c->title);
garbeam@21 95 draw_bar();
garbeam@13 96 XFlush(dpy);
garbeam@13 97 }
garbeam@13 98
garbeam@13 99 void
garbeam@10 100 manage(Window w, XWindowAttributes *wa)
garbeam@5 101 {
garbeam@10 102 Client *c, **l;
garbeam@5 103 XSetWindowAttributes twa;
garbeam@5 104
garbeam@5 105 c = emallocz(sizeof(Client));
garbeam@5 106 c->win = w;
garbeam@22 107 c->tx = c->x = wa->x;
garbeam@22 108 c->ty = c->y = wa->y;
garbeam@22 109 c->tw = c->w = wa->width;
garbeam@20 110 c->h = wa->height;
garbeam@22 111 c->th = barrect.height;
garbeam@20 112 update_size(c);
garbeam@19 113 XSetWindowBorderWidth(dpy, c->win, 1);
garbeam@22 114 XSetWindowBorder(dpy, c->win, brush.border);
garbeam@18 115 XSelectInput(dpy, c->win, CLIENT_MASK);
garbeam@5 116 XGetTransientForHint(dpy, c->win, &c->trans);
garbeam@5 117 twa.override_redirect = 1;
garbeam@5 118 twa.background_pixmap = ParentRelative;
garbeam@22 119 twa.event_mask = SubstructureNotifyMask | ExposureMask;
garbeam@5 120
garbeam@22 121 c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
garbeam@20 122 0, DefaultDepth(dpy, screen), CopyFromParent,
garbeam@5 123 DefaultVisual(dpy, screen),
garbeam@5 124 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
garbeam@21 125 update_name(c);
garbeam@5 126
garbeam@10 127 for(l=&clients; *l; l=&(*l)->next);
garbeam@10 128 c->next = *l; /* *l == nil */
garbeam@10 129 *l = c;
garbeam@13 130 c->snext = stack;
garbeam@13 131 stack = c;
garbeam@13 132 XMapWindow(dpy, c->win);
garbeam@21 133 XMapWindow(dpy, c->title);
garbeam@19 134 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 135 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 136 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 137 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 138 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@18 139 GrabModeAsync, GrabModeSync, None, None);
garbeam@21 140 resize(c);
garbeam@13 141 focus(c);
garbeam@5 142 }
garbeam@9 143
garbeam@18 144 void
garbeam@18 145 resize(Client *c)
garbeam@18 146 {
garbeam@18 147 XConfigureEvent e;
garbeam@18 148
garbeam@20 149 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
garbeam@18 150 e.type = ConfigureNotify;
garbeam@18 151 e.event = c->win;
garbeam@18 152 e.window = c->win;
garbeam@20 153 e.x = c->x;
garbeam@20 154 e.y = c->y;
garbeam@20 155 e.width = c->w;
garbeam@20 156 e.height = c->h;
garbeam@19 157 e.border_width = 0;
garbeam@18 158 e.above = None;
garbeam@18 159 e.override_redirect = False;
garbeam@18 160 XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask);
garbeam@18 161 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
garbeam@18 162 XSelectInput(dpy, c->win, CLIENT_MASK);
garbeam@18 163 XFlush(dpy);
garbeam@18 164 }
garbeam@18 165
garbeam@10 166 static int
garbeam@10 167 dummy_error_handler(Display *dpy, XErrorEvent *error)
garbeam@10 168 {
garbeam@10 169 return 0;
garbeam@10 170 }
garbeam@10 171
garbeam@10 172 void
garbeam@10 173 unmanage(Client *c)
garbeam@10 174 {
garbeam@10 175 Client **l;
garbeam@10 176
garbeam@10 177 XGrabServer(dpy);
garbeam@10 178 XSetErrorHandler(dummy_error_handler);
garbeam@10 179
garbeam@18 180 XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
garbeam@10 181 XDestroyWindow(dpy, c->title);
garbeam@10 182
garbeam@10 183 for(l=&clients; *l && *l != c; l=&(*l)->next);
garbeam@10 184 eassert(*l == c);
garbeam@10 185 *l = c->next;
garbeam@13 186 for(l=&stack; *l && *l != c; l=&(*l)->snext);
garbeam@13 187 eassert(*l == c);
garbeam@13 188 *l = c->snext;
garbeam@10 189 free(c);
garbeam@10 190
garbeam@10 191 XFlush(dpy);
garbeam@10 192 XSetErrorHandler(error_handler);
garbeam@10 193 XUngrabServer(dpy);
garbeam@18 194 discard_events(EnterWindowMask);
garbeam@14 195 if(stack)
garbeam@14 196 focus(stack);
garbeam@10 197 }
garbeam@10 198
garbeam@10 199
garbeam@9 200 Client *
garbeam@9 201 getclient(Window w)
garbeam@9 202 {
garbeam@9 203 Client *c;
garbeam@9 204 for(c = clients; c; c = c->next)
garbeam@9 205 if(c->win == w)
garbeam@9 206 return c;
garbeam@9 207 return NULL;
garbeam@9 208 }
garbeam@13 209
garbeam@14 210 void
garbeam@14 211 draw_client(Client *c)
garbeam@14 212 {
garbeam@21 213 if(c == stack)
garbeam@21 214 draw_bar();
garbeam@14 215
garbeam@22 216 c->tw = textwidth(&brush.font, c->name) + labelheight(&brush.font);
garbeam@22 217 c->tx = c->x + c->w - c->tw + 2;
garbeam@22 218 c->ty = c->y;
garbeam@22 219 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
garbeam@22 220
garbeam@21 221 brush.rect.x = brush.rect.y = 0;
garbeam@22 222 brush.rect.width = c->tw;
garbeam@22 223 brush.rect.height = c->th;
garbeam@14 224
garbeam@21 225 draw(dpy, &brush, True, c->name);
garbeam@22 226 XCopyArea(dpy, brush.drawable, c->title, brush.gc,
garbeam@22 227 0, 0, c->tw, c->th, 0, 0);
garbeam@21 228 XFlush(dpy);
garbeam@14 229 }