aewl

annotate client.c @ 23:95ffdfd0a819

some more additions/fixes
author Anselm R. Garbe <garbeam@wmii.de>
date Wed, 12 Jul 2006 00:00:25 +0200
parents bd3a44353916
children e8f627998d6f
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@23 96 discard_events(EnterWindowMask);
garbeam@13 97 XFlush(dpy);
garbeam@13 98 }
garbeam@13 99
garbeam@13 100 void
garbeam@10 101 manage(Window w, XWindowAttributes *wa)
garbeam@5 102 {
garbeam@10 103 Client *c, **l;
garbeam@5 104 XSetWindowAttributes twa;
garbeam@5 105
garbeam@5 106 c = emallocz(sizeof(Client));
garbeam@5 107 c->win = w;
garbeam@22 108 c->tx = c->x = wa->x;
garbeam@22 109 c->ty = c->y = wa->y;
garbeam@22 110 c->tw = c->w = wa->width;
garbeam@20 111 c->h = wa->height;
garbeam@22 112 c->th = barrect.height;
garbeam@20 113 update_size(c);
garbeam@19 114 XSetWindowBorderWidth(dpy, c->win, 1);
garbeam@22 115 XSetWindowBorder(dpy, c->win, brush.border);
garbeam@18 116 XSelectInput(dpy, c->win, CLIENT_MASK);
garbeam@5 117 XGetTransientForHint(dpy, c->win, &c->trans);
garbeam@5 118 twa.override_redirect = 1;
garbeam@5 119 twa.background_pixmap = ParentRelative;
garbeam@23 120 twa.event_mask = ExposureMask;
garbeam@5 121
garbeam@22 122 c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
garbeam@20 123 0, DefaultDepth(dpy, screen), CopyFromParent,
garbeam@5 124 DefaultVisual(dpy, screen),
garbeam@5 125 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
garbeam@21 126 update_name(c);
garbeam@5 127
garbeam@10 128 for(l=&clients; *l; l=&(*l)->next);
garbeam@10 129 c->next = *l; /* *l == nil */
garbeam@10 130 *l = c;
garbeam@13 131 c->snext = stack;
garbeam@13 132 stack = c;
garbeam@13 133 XMapWindow(dpy, c->win);
garbeam@21 134 XMapWindow(dpy, c->title);
garbeam@19 135 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 136 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 137 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 138 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 139 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@18 140 GrabModeAsync, GrabModeSync, None, None);
garbeam@21 141 resize(c);
garbeam@13 142 focus(c);
garbeam@5 143 }
garbeam@9 144
garbeam@18 145 void
garbeam@18 146 resize(Client *c)
garbeam@18 147 {
garbeam@18 148 XConfigureEvent e;
garbeam@18 149
garbeam@20 150 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
garbeam@18 151 e.type = ConfigureNotify;
garbeam@18 152 e.event = c->win;
garbeam@18 153 e.window = c->win;
garbeam@20 154 e.x = c->x;
garbeam@20 155 e.y = c->y;
garbeam@20 156 e.width = c->w;
garbeam@20 157 e.height = c->h;
garbeam@19 158 e.border_width = 0;
garbeam@18 159 e.above = None;
garbeam@18 160 e.override_redirect = False;
garbeam@18 161 XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask);
garbeam@18 162 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
garbeam@18 163 XSelectInput(dpy, c->win, CLIENT_MASK);
garbeam@18 164 XFlush(dpy);
garbeam@18 165 }
garbeam@18 166
garbeam@10 167 static int
garbeam@10 168 dummy_error_handler(Display *dpy, XErrorEvent *error)
garbeam@10 169 {
garbeam@10 170 return 0;
garbeam@10 171 }
garbeam@10 172
garbeam@10 173 void
garbeam@10 174 unmanage(Client *c)
garbeam@10 175 {
garbeam@10 176 Client **l;
garbeam@10 177
garbeam@10 178 XGrabServer(dpy);
garbeam@10 179 XSetErrorHandler(dummy_error_handler);
garbeam@10 180
garbeam@18 181 XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
garbeam@10 182 XDestroyWindow(dpy, c->title);
garbeam@10 183
garbeam@10 184 for(l=&clients; *l && *l != c; l=&(*l)->next);
garbeam@10 185 eassert(*l == c);
garbeam@10 186 *l = c->next;
garbeam@13 187 for(l=&stack; *l && *l != c; l=&(*l)->snext);
garbeam@13 188 eassert(*l == c);
garbeam@13 189 *l = c->snext;
garbeam@10 190 free(c);
garbeam@10 191
garbeam@10 192 XFlush(dpy);
garbeam@10 193 XSetErrorHandler(error_handler);
garbeam@10 194 XUngrabServer(dpy);
garbeam@14 195 if(stack)
garbeam@14 196 focus(stack);
garbeam@10 197 }
garbeam@10 198
garbeam@23 199 Client *
garbeam@23 200 gettitle(Window w)
garbeam@23 201 {
garbeam@23 202 Client *c;
garbeam@23 203 for(c = clients; c; c = c->next)
garbeam@23 204 if(c->title == w)
garbeam@23 205 return c;
garbeam@23 206 return NULL;
garbeam@23 207 }
garbeam@10 208
garbeam@9 209 Client *
garbeam@9 210 getclient(Window w)
garbeam@9 211 {
garbeam@9 212 Client *c;
garbeam@9 213 for(c = clients; c; c = c->next)
garbeam@9 214 if(c->win == w)
garbeam@9 215 return c;
garbeam@9 216 return NULL;
garbeam@9 217 }
garbeam@13 218
garbeam@14 219 void
garbeam@14 220 draw_client(Client *c)
garbeam@14 221 {
garbeam@21 222 if(c == stack)
garbeam@21 223 draw_bar();
garbeam@14 224
garbeam@22 225 c->tw = textwidth(&brush.font, c->name) + labelheight(&brush.font);
garbeam@22 226 c->tx = c->x + c->w - c->tw + 2;
garbeam@22 227 c->ty = c->y;
garbeam@22 228 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
garbeam@22 229
garbeam@21 230 brush.rect.x = brush.rect.y = 0;
garbeam@22 231 brush.rect.width = c->tw;
garbeam@22 232 brush.rect.height = c->th;
garbeam@14 233
garbeam@21 234 draw(dpy, &brush, True, c->name);
garbeam@22 235 XCopyArea(dpy, brush.drawable, c->title, brush.gc,
garbeam@22 236 0, 0, c->tw, c->th, 0, 0);
garbeam@21 237 XFlush(dpy);
garbeam@14 238 }