/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" void mainloop (int shape_event) { Client *c = 0; ScreenInfo *s = 0; XEvent ev; for (;;) { XNextEvent (dpy, &ev); switch (ev.type) { case KeyPress: keyevent (&ev.xkey); break; case KeyRelease: break; case ButtonPress: button (&ev.xbutton); XAllowEvents (dpy, SyncPointer, ev.xbutton.time); break; case ButtonRelease: break; case MapRequest: mapreq (&ev.xmaprequest); if ((c = getclient (ev.xmaprequest.window, 0)) != 0) { if (normal (c) && ((s = c->screen) != 0)) { if (c == current) { if (c->isnotile) { raise_notile (s); } else { raise_tile (s, 0); } } if (!c->isnotile || c->istool) { tile_all (s); } } } break; case ConfigureRequest: configurereq (&ev.xconfigurerequest); break; case UnmapNotify: unmap (&ev.xunmap); if ((c = getclient (ev.xunmap.window, 0)) != 0) { if ((s = c->screen) != 0) { if (!c->isnotile || c->istool) { tile_all (s); } if (!current) { revert_window (s); } } } break; case PropertyNotify: property (&ev.xproperty); break; case Expose: expose (&ev.xexpose); break; case CreateNotify: newwindow (&ev.xcreatewindow); break; case DestroyNotify: destroy (ev.xdestroywindow.window); break; case ClientMessage: clientmesg (&ev.xclient); break; case ColormapNotify: cmap (&ev.xcolormap); break; case ReparentNotify: reparent (&ev.xreparent); break; case SelectionNotify: break; case EnterNotify: enter (&ev.xcrossing); break; case FocusIn: focusin (&ev.xfocus); break; default: if (shape && ev.type == shape_event) { shapenotify ((XShapeEvent *) & ev); } break; } } } void expose (XExposeEvent * e) { Client *c; ScreenInfo *s; if ((c = getclient (e->window, 0))) draw_border (c, c == current ? 1 : 0); else if ((s = getbarscreen (e->window))) draw_tbar (s); } void configurereq (XConfigureRequestEvent * e) { XWindowChanges wc; Client *c; c = getclient (e->window, 0); e->value_mask &= ~CWSibling; if (c) { gravitate (c, 1); if (e->value_mask & CWX) c->x = e->x; if (e->value_mask & CWY) c->y = e->y; if (e->value_mask & CWWidth) c->dx = e->width; if (e->value_mask & CWHeight) c->dy = e->height; if (e->value_mask & CWBorderWidth) c->border = e->border_width; gravitate (c, 0); if (e->value_mask & CWStackMode) { if (wc.stack_mode == Above) top (c); else e->value_mask &= ~CWStackMode; } if (c->parent != c->screen->root && c->window == e->window) { wc.x = c->x - BORDER; wc.y = c->y - BORDER; wc.width = c->dx + 2 * BORDER; wc.height = c->dy + 2 * BORDER; wc.border_width = 1; wc.sibling = None; wc.stack_mode = e->detail; XConfigureWindow (dpy, c->parent, e->value_mask, &wc); sendconfig (c); } } if (c && c->init) { wc.x = BORDER; wc.y = BORDER; } else { wc.x = e->x; wc.y = e->y; } wc.width = e->width; wc.height = e->height; wc.border_width = 0; wc.sibling = None; wc.stack_mode = Above; e->value_mask &= ~CWStackMode; e->value_mask |= CWBorderWidth; XConfigureWindow (dpy, e->window, e->value_mask, &wc); } void mapreq (XMapRequestEvent * e) { Client *c; c = getclient (e->window, 0); if (c == 0 || c->window != e->window) { return; } switch (c->state) { case WithdrawnState: if (c->parent == c->screen->root) { if (!manage (c, 0)) return; break; } XReparentWindow (dpy, c->window, c->parent, BORDER, BORDER); XAddToSaveSet (dpy, c->window); /* fall through... */ case NormalState: if (c->trans != None) { Client *p = getclient (c->trans, 0); if (p) { c->desktop = p->desktop; } } raise_tbar (c->screen); XMapWindow (dpy, c->window); XMapRaised (dpy, c->parent); top (c); wmsetstate (c, NormalState); if ((mouse_on_screen () == c->screen) || (current && (current->screen == c->screen))) { active (c); } break; case IconicState: unhidec (c, 1); break; } } void unmap (XUnmapEvent * e) { Client *c; c = getclient (e->window, 0); if (c) { switch (c->state) { case IconicState: if (e->send_event) { unhidec (c, 0); withdraw (c); } break; case NormalState: if (c == current) current = 0; if (!c->reparenting) withdraw (c); break; } c->reparenting = 0; } } void newwindow (XCreateWindowEvent * e) { Client *c; ScreenInfo *s; if (e->override_redirect) return; c = getclient (e->window, 1); /* Crashing bug patch by MG has been applied here. */ if (c && c->window == e->window) { c->x = e->x; c->y = e->y; c->dx = e->width; c->dy = e->height; c->border = e->border_width; if (0 != (s = getscreen (e->parent))) c->screen = s; else c->screen = &screens[0]; if (c->parent == None) c->parent = c->screen->root; } } void destroy (Window w) { Client *c; if (!(c = getclient (w, 0))) return; rmclient (c); ignore_badwindow = 1; XSync (dpy, False); ignore_badwindow = 0; } void clientmesg (XClientMessageEvent * e) { Client *c; if (e->message_type == exit_larswm) { cleanup (); exit (0); } else if (e->message_type == restart_larswm) { cleanup (); execvp (myargv[0], myargv); perror ("larswm: exec failed"); exit (1); } else if (e->message_type == wm_change_state) { c = getclient (e->window, 0); if (e->format == 32 && e->data.l[0] == IconicState && c != 0) { if (normal (c)) hide (c); } } } void cmap (XColormapEvent * e) { Client *c; int i; if (e->new) { c = getclient (e->window, 0); if (c) { c->cmap = e->colormap; if (c == current) cmapfocus (c); } else for (c = clients; c; c = c->next) { for (i = 0; i < c->ncmapwins; i++) if (c->cmapwins[i] == e->window) { c->wmcmaps[i] = e->colormap; if (c == current) cmapfocus (c); return; } } } } void property (XPropertyEvent * e) { Client *c; long msize; /* check if text to be displayed on status bar was just changed */ if ((e->atom == bartext_larswm) && (e->window == DefaultRootWindow (dpy))) { update_cmd_output (); return; } if (!(c = getclient (e->window, 0))) return; switch (e->atom) { case XA_WM_ICON_NAME: if (c->iconname != 0) XFree ((char *) c->iconname); c->iconname = (e->state == PropertyDelete) ? 0 : getprop (c->window, e->atom); setlabel (c); renamec (c, c->label); break; case XA_WM_NAME: if (c->name != 0) XFree ((char *) c->name); c->name = (e->state == PropertyDelete) ? 0 : getprop (c->window, e->atom); setlabel (c); renamec (c, c->label); break; case XA_WM_TRANSIENT_FOR: gettrans (c); break; case XA_WM_NORMAL_HINTS: if (XGetWMNormalHints (dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0) { c->size.flags = PSize; } if (c->size.flags & PBaseSize) { c->min_dx = c->size.base_width; c->min_dy = c->size.base_height; } else if (c->size.flags & PMinSize) { c->min_dx = c->size.min_width; c->min_dy = c->size.min_height; } else { c->min_dx = c->min_dy = 1; } break; default: if (e->atom == wm_colormaps) { getcmaps (c); if (c == current) { cmapfocus (c); } } break; } } void reparent (XReparentEvent * e) { Client *c; XWindowAttributes attr; ScreenInfo *s; if (!getscreen (e->event) || e->override_redirect) return; if ((s = getscreen (e->parent)) != 0) { c = getclient (e->window, 1); if (c != 0 && (c->dx == 0 || c->dy == 0)) { XGetWindowAttributes (dpy, c->window, &attr); c->x = attr.x; c->y = attr.y; c->dx = attr.width; c->dy = attr.height; c->border = attr.border_width; c->screen = s; if (c->parent == None) c->parent = c->screen->root; } } else { c = getclient (e->window, 0); if (c != 0 && (c->parent == c->screen->root || withdrawn (c))) rmclient (c); } } void shapenotify (XShapeEvent * e) { Client *c; c = getclient (e->window, 0); if (c == 0) return; setshape (c); } void enter (XCrossingEvent * e) { Client *c; if (e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual) return; c = getclient (e->window, 0); if (c && c->parent && (c != current)) { XMapRaised (dpy, c->parent); active (c); } else { XSetInputFocus (dpy, e->window, RevertToPointerRoot, e->time); } } void focusin (XFocusChangeEvent * e) { Client *c; if (e->detail != NotifyNonlinearVirtual) return; c = getclient (e->window, 0); if (c && c->window && c->parent && (c->window == e->window) && (c != current)) { XMapRaised (dpy, c->parent); active (c); } else { XSetInputFocus (dpy, e->window, RevertToPointerRoot, CurrentTime); } }