/* $id */
/*
* BadWM - minimalistic window manager for the X Window System
* Copyright (C) Robert Annessi <robert@annessi.at>
*
* 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 <stdlib.h>
#include <stdio.h>
#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; i<n; i++) if (protocols[i] == xa_wm_delete) found++;
XFree(protocols);
}
if (found) send_xmessage(c->window, 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);
}
syntax highlighted by Code2HTML, v. 0.9.1