/* $id */ /* * 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/config.h" static int send_xmessage(Window w, Atom a, long x); Client *find_client(Window w) { Client *c; /* maybe little enhanced - but current is first often*/ if ( current != NULL && (w == current->parent || w == current->window) ) return current; for (c = head_client; c; c = c->next) if (w == c->parent || w == c->window) return c; return NULL; } static void __set_wm_state(const Window win, const Atom a, int state, long vis) { long data[2]; data[0] = (long) state; data[1] = vis; XChangeProperty(dpy, win, a, a, 32, PropModeReplace, (unsigned char *)data, 2); } void set_wm_state(Client *c, int state) { /* iconify window and set state */ __set_wm_state(c->window, xa_wm_state, state, None); } static long * _g_wm_state(const Window win, const Atom where) { Atom real_type; int real_format; unsigned long n, extra; unsigned char *data; if ((XGetWindowProperty(dpy, win, where, 0L, 2L, False, AnyPropertyType, &real_type, &real_format, &n, &extra, &data) == Success) && n) { return (long *)data; } return NULL; } static int __wm_state(const Window win, const Atom where) { long *data, state = WithdrawnState; data = _g_wm_state(win, where); if (data) { state = *data; XFree(data); } return state; } int wm_state(Client *c) { return __wm_state(c->window, xa_wm_state); } void send_config(Client *c) { XConfigureEvent ce; ce.type = ConfigureNotify; ce.event = c->window; ce.window = c->window; ce.x = c->x; ce.y = c->y; ce.width = c->width; ce.height = c->height; ce.border_width = 0; ce.above = None; ce.override_redirect = 0; XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent *)&ce); } void remove_client(Client *c) { Client *p; #ifdef DEBUG bad_debug(1,"remove_client() : Removing...\n"); #endif XGrabServer(dpy); XSetErrorHandler(ignore_xerror); if (!quitting) { #ifdef DEBUG bad_debug(1,"setting WithdrawnState\n"); #endif set_wm_state(c, WithdrawnState); XRemoveFromSaveSet(dpy, c->window); } change_gravity(c,(opt_bw*-1)); XSetWindowBorderWidth(dpy, c->window, opt_bw); XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y); if (c->parent) XDestroyWindow(dpy, c->parent); if (head_client == c) head_client = c->next; else for (p = head_client; p && p->next; p = p->next) if (p->next == c) p->next = c->next; /* removing from fix_next list */ for (p = head_client; p && p->next; p = p->next) if (p->fix_next == c) p->fix_next = c->fix_next; if (c->size) XFree(c->size); if (current == c) current = NULL; /* an enter event should set this up again */ free(c); XSync(dpy, False); XSetErrorHandler(handle_xerror); XUngrabServer(dpy); if (!current) next(); } void change_gravity(Client *c, int multiplier) { int dx = 0, dy = 0; int gravity = (c->size->flags & PWinGravity) ? c->size->win_gravity : NorthWestGravity; switch (gravity) { case NorthWestGravity: case SouthWestGravity: case NorthEastGravity: case StaticGravity: dx = c->border; case NorthGravity: dy = c->border; break; } c->x += multiplier * dx; c->y += multiplier * dy; #ifdef DEBUG if (dx || dy) { bad_debug(1,"window adjustment of %d,%d for ", multiplier * dx, multiplier * dy); switch (gravity) { case NorthWestGravity: bad_debug(1,"NorthWestGravity\n"); break; case SouthWestGravity: bad_debug(1,"SouthWestGravity\n"); break; case NorthEastGravity: bad_debug(1,"NorthEastGravity\n"); break; case NorthGravity: bad_debug(1,"NorthGravity\n"); break; case StaticGravity: bad_debug(1,"StaticGravity\n"); break; default: bad_debug(1,"unhandled gravity %d\n", gravity); break; } } #endif } void send_wm_delete(Client *c) { int i, n, found = 0; Atom *protocols; if (c) { if (XGetWMProtocols(dpy, c->window, &protocols, &n)) { for (i=0; iwindow, xa_wm_protos, xa_wm_delete); else XKillClient(dpy, c->window); } } static int send_xmessage(Window w, Atom a, long x) { XEvent ev; ev.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = a; ev.xclient.format = 32; ev.xclient.data.l[0] = x; ev.xclient.data.l[1] = CurrentTime; return XSendEvent(dpy, w, False, NoEventMask, &ev); } void set_shape(Client *c) { int n, order; XRectangle *rect; rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order); if (n > 1) XShapeCombineShape(dpy, c->parent, ShapeBounding, c->border, c->border, c->window, ShapeBounding, ShapeSet); XFree((void*)rect); } void client_update_current(Client *c, Client *newcurrent) { if (c) { if (c->vdesk == STICKY) XSetWindowBackground(dpy, c->parent, c == newcurrent ? c->screen->fc.pixel : c->screen->bg.pixel); else XSetWindowBackground(dpy, c->parent, c == newcurrent ? c->screen->fg.pixel : c->screen->bg.pixel); XClearWindow(dpy, c->parent); } current = newcurrent; } void focus_client( Client *c ) { int wdesk; wdesk = c->vdesk; if (wdesk != vdesk && wdesk != STICKY) return; client_update_current(current, c); client_update_current(c, current); XSetInputFocus(dpy, c->window, RevertToPointerRoot, CurrentTime); grab_button(c->parent, Mod1Mask, AnyButton); }