New feature: EWMH Support ! #1

This commit is contained in:
Martin Duquesnoy
2008-12-14 15:43:21 +01:00
parent 199a148689
commit f8d1049240
17 changed files with 410 additions and 107 deletions

View File

@@ -33,6 +33,7 @@ set(wmfs_src
src/config.c src/config.c
src/draw.c src/draw.c
src/event.c src/event.c
src/ewmh.c
src/frame.c src/frame.c
src/infobar.c src/infobar.c
src/init.c src/init.c

View File

@@ -68,10 +68,10 @@ barwin_create(Window parent,
at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask; at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask;
/* Create window */ /* Create window */
bw->win = XCreateWindow(dpy, parent, x, y, w, h, 0, DefaultDepth(dpy, screen), bw->win = XCreateWindow(dpy, parent, x, y, w, h, 0, DefaultDepth(dpy, SCREEN),
CopyFromParent, DefaultVisual(dpy, screen), CopyFromParent, DefaultVisual(dpy, SCREEN),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &at); CWOverrideRedirect | CWBackPixmap | CWEventMask, &at);
bw->dr = XCreatePixmap(dpy, parent, w, h, DefaultDepth(dpy, screen)); bw->dr = XCreatePixmap(dpy, parent, w, h, DefaultDepth(dpy, SCREEN));
/* His border */ /* His border */
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(color), &at); CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(color), &at);
@@ -211,7 +211,7 @@ barwin_resize(BarWindow *bw, uint w, uint h)
XFreePixmap(dpy, bw->dr); XFreePixmap(dpy, bw->dr);
/* Frame */ /* Frame */
bw->dr = XCreatePixmap(dpy, root, w - SHADH, h - SHADH, DefaultDepth(dpy, screen)); bw->dr = XCreatePixmap(dpy, ROOT, w - SHADH, h - SHADH, DefaultDepth(dpy, SCREEN));
XResizeWindow(dpy, bw->win, w, h); XResizeWindow(dpy, bw->win, w, h);
/* Border */ /* Border */

View File

@@ -161,7 +161,7 @@ client_focus(Client *c)
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
} }
else else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, ROOT, RevertToPointerRoot, CurrentTime);
return; return;
} }
@@ -369,7 +369,7 @@ client_manage(Window w, XWindowAttributes *wa)
uint duint; uint duint;
Window dw; Window dw;
XQueryPointer(dpy, root, &dw, &dw, &mx, &my, &dint, &dint, &duint); XQueryPointer(dpy, ROOT, &dw, &dw, &mx, &my, &dint, &dint, &duint);
mx += BORDH; mx += BORDH;
my += TBARH; my += TBARH;
@@ -393,12 +393,11 @@ client_manage(Window w, XWindowAttributes *wa)
my += sgeo[selscreen].y - TBARH - INFOBARH; my += sgeo[selscreen].y - TBARH - INFOBARH;
} }
} }
c->ogeo.x = c->geo.x = mx; c->ogeo.x = c->geo.x = mx;
c->ogeo.y = c->geo.y = my; c->ogeo.y = c->geo.y = my;
c->ogeo.width = c->geo.width = wa->width; c->ogeo.width = c->geo.width = wa->width;
c->ogeo.height = c->geo.height = wa->height; c->ogeo.height = c->geo.height = wa->height;
c->tag = seltag[c->screen]; c->tag = seltag[c->screen];
at.event_mask = PropertyChangeMask; at.event_mask = PropertyChangeMask;
@@ -419,6 +418,7 @@ client_manage(Window w, XWindowAttributes *wa)
client_raise(c); client_raise(c);
client_focus(c); client_focus(c);
setwinstate(c->win, NormalState); setwinstate(c->win, NormalState);
ewmh_manage_window_type(c);
arrange(); arrange();
return; return;
@@ -487,7 +487,7 @@ client_moveresize(Client *c, XRectangle geo, bool r)
|| c->geo.width != geo.width || c->geo.width != geo.width
|| c->geo.height != geo.height) || c->geo.height != geo.height)
{ {
c->geo = geo; c->geo = c->ogeo = geo;
/* Set the client screen */ /* Set the client screen */
c->screen = screen_get_with_geo(geo.x, geo.y); c->screen = screen_get_with_geo(geo.x, geo.y);
@@ -501,6 +501,38 @@ client_moveresize(Client *c, XRectangle geo, bool r)
return; return;
} }
/** Maximize a client
* \param c Client pointer
*/
void
client_maximize(Client *c)
{
CHECK(c);
XRectangle geo;
c->screen = screen_get_with_geo(c->geo.x, c->geo.y);
geo.x = sgeo[c->screen].x;
geo.y = sgeo[c->screen].y;
geo.width = sgeo[c->screen].width - BORDH * 2;
geo.height = sgeo[c->screen].height - BORDH * 2;
if(c->state_fullscreen)
{
geo.y -= TBARH + INFOBARH + BORDH;
geo.height += TBARH + INFOBARH + (BORDH * 2);
client_moveresize(c, geo, False);
XMoveResizeWindow(dpy, c->win, 0, BORDH + TBARH, c->geo.width + BORDH * 2, c->geo.height);
}
else
client_moveresize(c, geo, False);
client_raise(c);
return;
}
/** Get client size hints /** Get client size hints
* \param c Client pointer * \param c Client pointer
*/ */
@@ -580,7 +612,7 @@ client_size_hints(Client *c)
void void
client_raise(Client *c) client_raise(Client *c)
{ {
if(!c || c->max || c->tile) if(!c || c->tile)
return; return;
XRaiseWindow(dpy, c->frame); XRaiseWindow(dpy, c->frame);
@@ -622,7 +654,7 @@ client_unmanage(Client *c)
{ {
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(errorhandlerdummy); XSetErrorHandler(errorhandlerdummy);
XReparentWindow(dpy, c->win, root, c->geo.x, c->geo.y); XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
if(sel == c) if(sel == c)
client_focus(NULL); client_focus(NULL);

View File

@@ -47,17 +47,17 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
XftDraw *xftd; XftDraw *xftd;
/* Transform X Drawable -> Xft Drawable */ /* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
/* Alloc text color */ /* Alloc text color */
XftColorAllocName(dpy, DefaultVisual(dpy, screen), XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, screen), fg, &xftcolor); DefaultColormap(dpy, SCREEN), fg, &xftcolor);
/* Draw the text */ /* Draw the text */
XftDrawStringUtf8(xftd, &xftcolor, font, x, y, (FcChar8 *)str, strlen(str)); XftDrawStringUtf8(xftd, &xftcolor, font, x, y, (FcChar8 *)str, strlen(str));
/* Free the text color and XftDraw */ /* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), &xftcolor); XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
XftDrawDestroy(xftd); XftDrawDestroy(xftd);

View File

@@ -63,7 +63,7 @@ buttonpress(XButtonEvent *ev)
conf.client.mouse[i].func(conf.client.mouse[i].cmd); conf.client.mouse[i].func(conf.client.mouse[i].cmd);
/* Root */ /* Root */
if(ev->window == root) if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i) for(i = 0; i < conf.root.nmouse; ++i)
if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen] if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen]
|| conf.root.mouse[i].tag < 0) || conf.root.mouse[i].tag < 0)
@@ -102,6 +102,45 @@ buttonpress(XButtonEvent *ev)
return; return;
} }
/* ClientMessage handle event
*\param ev XClientMessageEvent pointer
*/
void
clientmessageevent(XClientMessageEvent *ev)
{
Client *c;
int i, mess_t = 0;
if(ev->format != 32)
return;
for(i = 0; i < net_last; ++i)
if(net_atom[i] == ev->message_type)
mess_t = i;
if(ev->window == ROOT)
{
/* Manage _NET_CURRENT_DESKTOP */
if(mess_t == net_current_desktop)
ewmh_get_current_desktop();
/* Manage _NET_ACTIVE_WINDOW */
if(mess_t == net_active_window)
if((c = client_gb_win(ev->data.l[0])))
client_focus(c);
}
if((c = client_gb_win(ev->window)))
{
/* Manage _NET_WM_STATE */
if(mess_t == net_wm_state)
ewmh_manage_net_wm_state(ev->data.l, c);
/* Manage _NET_CLOSE_WINDOW */
if(mess_t == net_close_window)
client_kill(c);
}
return;
}
/** ConfigureRequest & ConfigureNotify handle event /** ConfigureRequest & ConfigureNotify handle event
* \param ev XEvent pointer * \param ev XEvent pointer
*/ */
@@ -246,14 +285,14 @@ grabkeys(void)
uint i; uint i;
KeyCode code; KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root); XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
for(i = 0; i < conf.nkeybind; ++i) for(i = 0; i < conf.nkeybind; ++i)
{ {
code = XKeysymToKeycode(dpy, keys[i].keysym); code = XKeysymToKeycode(dpy, keys[i].keysym);
XGrabKey(dpy, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, code, keys[i].mod|LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, code, keys[i].mod|numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|LockMask|numlockmask, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, code, keys[i].mod|LockMask|numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
} }
return; return;
@@ -368,12 +407,12 @@ unmapnotify(XUnmapEvent *ev)
void void
getevent(XEvent ev) getevent(XEvent ev)
{ {
int st; int st;
switch (ev.type) switch (ev.type)
{ {
case ButtonPress: buttonpress(&ev.xbutton); break; case ButtonPress: buttonpress(&ev.xbutton); break;
case ClientMessage: clientmessageevent(&ev.xclient); break;
case ConfigureRequest: configureevent(&ev); break; case ConfigureRequest: configureevent(&ev); break;
case DestroyNotify: destroynotify(&ev.xdestroywindow); break; case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
case EnterNotify: enternotify(&ev.xcrossing); break; case EnterNotify: enternotify(&ev.xcrossing); break;
@@ -386,6 +425,7 @@ getevent(XEvent ev)
case UnmapNotify: unmapnotify(&ev.xunmap); break; case UnmapNotify: unmapnotify(&ev.xunmap); break;
} }
//ewmh_get_current_desktop();
wait(&st); wait(&st);
return; return;

232
src/ewmh.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* ewmh.c
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
/* Took From standards.freedesktop.org */
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
#define _NET_WM_STATE_ADD 1 /* add/set property */
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
/** Init ewmh atoms
*/
void
ewmh_init_hints(void)
{
net_atom[net_supported] = ATOM("_NET_SUPPORTED");
net_atom[net_number_of_desktops] = ATOM("_NET_NUMBER_OF_DESKTOPS");
net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
net_atom[net_wm_window_type_dialog] = ATOM("_NET_WM_WINDOW_TYPE_DIALOG");
net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
net_atom[net_wm_state_skip_taskbar] = ATOM("_NET_WM_STATE_SKIP_TASKBAR");
net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
XChangeProperty(dpy, ROOT, net_atom[net_supported], XA_ATOM, 32,
PropModeReplace, (uchar*)net_atom, net_last);
return;
}
/** Get the number of desktop (tag)
*/
void
ewmh_get_number_of_desktop(void)
{
int c = 0, i;
for(i = 0; i < screen_count(); ++i)
c += conf.ntag[i];
XChangeProperty(dpy, ROOT, net_atom[net_number_of_desktops], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&c, 1);
return;
}
/** Get the current desktop
*/
void
ewmh_get_current_desktop(void)
{
screen_get_sel();
/* Get current desktop (tag) */
XChangeProperty(dpy, ROOT, net_atom[net_current_desktop], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&seltag[selscreen], 1);
return;
}
/** The desktop names
*/
void
ewmh_get_desktop_names(void)
{
char *str = NULL;
int s, i, len = 0, pos = 0;
for(s = 0 ; s < screen_count(); ++s)
for(i = 1; i < conf.ntag[s] + 1; ++i)
len += strlen(tags[s][i].name);
str = emalloc(len + i + 1, sizeof(char*));
for(s = 0; s < screen_count(); ++s)
for(i = 1; i < conf.ntag[s] + 1; ++i, ++pos)
{
strncpy(str + pos, tags[s][i].name, strlen(tags[s][i].name));
pos += strlen(tags[s][i].name);
str[pos] = '\0';
}
XChangeProperty(dpy, ROOT, net_atom[net_desktop_names], XA_STRING, 8,
PropModeReplace, (uchar*)str, pos);
free(str);
return;
}
/** Manage _NET_WM_STATE_* ewmh
*/
void
ewmh_manage_net_wm_state(long data_l[], Client *c)
{
/* Manage _NET_WM_STATE_FULLSCREEN */
if(data_l[1] == net_atom[net_wm_state_fullscreen])
{
if(data_l[0] == _NET_WM_STATE_ADD && !c->state_fullscreen)
{
c->state_fullscreen = True;
c->tmp_geo = c->geo;
if(c->free)
c->ogeo = c->geo;
client_maximize(c);
}
else if(data_l[0] == _NET_WM_STATE_REMOVE && c->state_fullscreen)
{
c->state_fullscreen = False;
client_moveresize(c, c->tmp_geo, False);
tags[selscreen][seltag[selscreen]].layout.func();
}
}
/* Manage _NET_WM_STATE_DEMANDS_ATTENTION */
else if(data_l[1] == net_atom[net_wm_state_demands_attention])
{
if(data_l[0] == _NET_WM_STATE_ADD)
client_focus(c);
if(data_l[0] == _NET_WM_STATE_REMOVE)
if(c == sel)
client_focus(NULL);
}
return;
}
/** Manage the client hints
*\param c Client pointer
*/
void
ewmh_manage_window_type(Client *c)
{
Atom *atom, rf;
int i, f;
ulong n, il;
uchar *data = NULL;
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
{
atom = (Atom*)data;
for(i = 0; i < n; ++i)
{
/* Manage _NET_WM_WINDOW_TYPE_DOCK & _NET_WM_WINDOW_TYPE_SPLASH */
if(atom[i] == net_atom[net_wm_window_type_dock]
|| atom[i] == net_atom[net_wm_window_type_splash])
{
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
XUnmapSubwindows(dpy, c->frame);
XUnmapWindow(dpy, c->frame);
XRaiseWindow(dpy, c->win);
}
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
else if(atom[i] == net_atom[net_wm_window_type_dialog])
{
c->free = True;
sel->tile = sel->max = sel->lmax = False;
client_moveresize(sel, sel->ogeo, True);
client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func();
}
}
XFree(data);
}
return;
}
/** Get a Window WM State
* \param win Window
* \return The state
*/
long
ewmh_get_wm_state(Window win)
{
Atom rt;
int rf;
long ret = WithdrawnState;
ulong ir, il;
uchar *data;
if(XGetWindowProperty(dpy, win, net_atom[net_wm_state], 0L, 2L,
False, net_atom[net_wm_state], &rt,
&rf, &ir, &il, &data) == Success && ir)
{
ret = *(long *)data;
XFree(data);
}
return ret;
}

View File

@@ -59,7 +59,7 @@ frame_create(Client *c)
c->colors.resizecorner = conf.client.resizecorner_normal; c->colors.resizecorner = conf.client.resizecorner_normal;
/* Create frame window */ /* Create frame window */
CWIN(c->frame, root, CWIN(c->frame, ROOT,
c->frame_geo.x, c->frame_geo.x,
c->frame_geo.y, c->frame_geo.y,
c->frame_geo.width, c->frame_geo.width,

View File

@@ -51,7 +51,7 @@ infobar_init(void)
: sgeo[sc].height - INFOBARH; : sgeo[sc].height - INFOBARH;
/* Create infobar barwindow */ /* Create infobar barwindow */
infobar[sc].bar = barwin_create(root, sgeo[sc].x - BORDH, infobar[sc].geo.y, infobar[sc].bar = barwin_create(ROOT, sgeo[sc].x - BORDH, infobar[sc].geo.y,
sgeo[sc].width, infobar[sc].geo.height, conf.colors.bar, False); sgeo[sc].width, infobar[sc].geo.height, conf.colors.bar, False);
/* Create tags window */ /* Create tags window */

View File

@@ -38,13 +38,13 @@ void
init(void) init(void)
{ {
/* First init */ /* First init */
gc = DefaultGC(dpy, screen); gc = DefaultGC(dpy, SCREEN);
screen = DefaultScreen(dpy);
init_font(); init_font();
init_cursor(); init_cursor();
init_key(); init_key();
init_root(); init_root();
screen_init_geo(); screen_init_geo();
ewmh_init_hints();
infobar_init(); infobar_init();
grabkeys(); grabkeys();
@@ -60,11 +60,11 @@ init(void)
void void
init_font(void) init_font(void)
{ {
font = XftFontOpenName(dpy, screen, conf.font); font = XftFontOpenName(dpy, SCREEN, conf.font);
if(!font) if(!font)
{ {
fprintf(stderr, "WMFS Error: Cannot initialize font\n"); fprintf(stderr, "WMFS Error: Cannot initialize font\n");
font = XftFontOpenName(dpy, screen, "sans-10"); font = XftFontOpenName(dpy, SCREEN, "sans-10");
} }
} }
@@ -105,21 +105,19 @@ void
init_root(void) init_root(void)
{ {
XSetWindowAttributes at; XSetWindowAttributes at;
Atom data[] = { ATOM("_NET_SUPPORTED"), ATOM("_NET_WM_NAME") };
root = RootWindow(dpy, screen);
at.event_mask = KeyMask|ButtonMask|MouseMask at.event_mask = KeyMask|ButtonMask|MouseMask
|SubstructureRedirectMask|SubstructureNotifyMask |SubstructureRedirectMask|SubstructureNotifyMask
|EnterWindowMask|LeaveWindowMask|StructureNotifyMask; |EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
at.cursor = cursor[CurNormal]; at.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &at); XChangeWindowAttributes(dpy, ROOT, CWEventMask | CWCursor, &at);
if(conf.root.background_command) if(conf.root.background_command)
uicb_spawn(conf.root.background_command); uicb_spawn(conf.root.background_command);
XChangeProperty(dpy, root, ATOM("_NET_SUPPORTED"), XA_ATOM, 32, ewmh_init_hints();
PropModeReplace, (uchar*)data, NetLast); ewmh_get_number_of_desktop();
ewmh_get_desktop_names();
return; return;
} }

View File

@@ -137,19 +137,12 @@ void
maxlayout(void) maxlayout(void)
{ {
Client *c; Client *c;
XRectangle geo;
XRectangle sg = sgeo[selscreen];
for(c = nexttiled(clients); c; c = nexttiled(c->next)) for(c = nexttiled(clients); c; c = nexttiled(c->next))
{ {
c->tile = False; c->tile = False;
c->lmax = True; c->lmax = True;
geo.x = sg.x; client_maximize(c);
geo.y = sg.y;
geo.width = sg.width - BORDH * 2;
geo.height = sg.height - BORDH * 2;
client_moveresize(c, geo, False);
} }
return; return;
@@ -163,7 +156,11 @@ maxlayout(void)
Client* Client*
nexttiled(Client *c) nexttiled(Client *c)
{ {
for(; c && (c->max || c->free || c->screen != selscreen || ishide(c)); c = c->next); for(;c && (c->max
|| c->free
|| c->screen != selscreen
|| c->state_fullscreen
|| ishide(c)); c = c->next);
return c; return c;
} }
@@ -449,7 +446,7 @@ uicb_tile_switch(uicb_t cmd)
screen_get_sel(); screen_get_sel();
if(!sel || sel->hint || !sel->tile) if(!sel || sel->hint || !sel->tile || sel->state_fullscreen)
return; return;
if((c = sel) == nexttiled(clients)) if((c = sel) == nexttiled(clients))
CHECK((c = nexttiled(c->next))); CHECK((c = nexttiled(c->next)));
@@ -467,51 +464,44 @@ uicb_tile_switch(uicb_t cmd)
void void
uicb_togglefree(uicb_t cmd) uicb_togglefree(uicb_t cmd)
{ {
CHECK(sel); if(!sel || sel->screen != screen_get_sel() || sel->state_fullscreen)
if(!sel || sel->screen != screen_get_sel())
return; return;
sel->free = !sel->free; sel->free = !sel->free;
sel->tile = False;
sel->max = False; if(sel->free)
sel->lmax = False; {
client_moveresize(sel, sel->ogeo, True); sel->tile = sel->max = sel->lmax = False;
client_moveresize(sel, sel->ogeo, True);
}
else
sel->ogeo = sel->geo;
tags[selscreen][seltag[selscreen]].layout.func(); tags[selscreen][seltag[selscreen]].layout.func();
return; return;
} }
/** Toggle the selected client to max /** Toggle the selected client to max
* \param cmd uicb_t type unused * \param cmd uicb_t type unused
*/ */
void void
uicb_togglemax(uicb_t cmd) uicb_togglemax(uicb_t cmd)
{ {
XRectangle geo; if(!sel || ishide(sel) || sel->hint || sel->state_fullscreen)
XRectangle sg = sgeo[screen_get_sel()];
if(!sel || ishide(sel) || sel->hint)
return; return;
if(!sel->max) if(!sel->max)
{ {
geo.x = sg.x; sel->tile = sel->free = False;
geo.y = sg.y; client_maximize(sel);
geo.width = sg.width - BORDH * 2;
geo.height = sg.height - BORDH * 2;
client_moveresize(sel, geo, False);
client_raise(sel);
sel->max = True; sel->max = True;
} }
else if(sel->max) else if(sel->max)
{ {
geo.x = sel->ogeo.x;
geo.y = sel->ogeo.y;
geo.width = sel->ogeo.width;
geo.height = sel->ogeo.height;
client_moveresize(sel, geo, False);
sel->max = False; sel->max = False;
tags[selscreen][seltag[selscreen]].layout.func();
} }
return; return;

View File

@@ -49,11 +49,11 @@ mouse_move(Client *c)
if(c->max || c->tile || c->lmax) if(c->max || c->tile || c->lmax)
return; return;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess) None, cursor[CurMove], CurrentTime) != GrabSuccess)
return; return;
XQueryPointer(dpy, root, &dw, &dw, &mx, &my, &dint, &dint, &duint); XQueryPointer(dpy, ROOT, &dw, &dw, &mx, &my, &dint, &dint, &duint);
for(;;) for(;;)
{ {
@@ -94,8 +94,8 @@ mouse_resize(Client *c)
if(c->max || c->lmax || c->tile) if(c->max || c->lmax || c->tile)
return; return;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize], CurrentTime) != GrabSuccess) None, cursor[CurResize], CurrentTime) != GrabSuccess)
return; return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width + conf.client.borderheight, c->geo.height); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width + conf.client.borderheight, c->geo.height);

View File

@@ -114,7 +114,7 @@ screen_get_sel(void)
Window w; Window w;
int d, u, x, y; int d, u, x, y;
XQueryPointer(dpy, root, &w, &w, &x, &y, &d, &d, (uint *)&u); XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&u);
selscreen = screen_get_with_geo(x, y); selscreen = screen_get_with_geo(x, y);
} }

View File

@@ -48,8 +48,30 @@ typedef unsigned char uchar;
/* Enum */ /* Enum */
enum { CurNormal, CurResize, CurMove, CurLast }; enum { CurNormal, CurResize, CurMove, CurLast };
enum { WMState, WMProtocols, WMName, WMDelete, WMLast }; /* Ewmh hints list */
enum { NetSupported, NetWMName, NetLast }; enum
{
net_supported,
net_wm_name,
net_number_of_desktops,
net_current_desktop,
net_desktop_names,
net_active_window,
net_close_window,
net_wm_icon_name,
net_wm_window_type,
net_wm_window_type_normal,
net_wm_window_type_dock,
net_wm_window_type_splash,
net_wm_window_type_dialog,
net_wm_icon,
net_wm_state,
net_wm_state_sticky,
net_wm_state_skip_taskbar,
net_wm_state_fullscreen,
net_wm_state_demands_attention,
net_last
};
typedef enum { Top, Bottom, Right, Left, Center, PositionLast } Position; typedef enum { Top, Bottom, Right, Left, Center, PositionLast } Position;
/* /*
@@ -84,6 +106,7 @@ struct Client
int screen; int screen;
/* Window attribute */ /* Window attribute */
XRectangle geo; XRectangle geo;
XRectangle tmp_geo;
XRectangle frame_geo; XRectangle frame_geo;
/* Old window attribute */ /* Old window attribute */
XRectangle ogeo; XRectangle ogeo;
@@ -105,7 +128,7 @@ struct Client
} colors; } colors;
/* Client Layout Information */ /* Client Layout Information */
Bool max, tile, free, hide; Bool max, tile, free, hide;
Bool hint, lmax, unmapped; Bool hint, lmax, unmapped, state_fullscreen;
/* Struct in chains */ /* Struct in chains */
Client *next; Client *next;
Client *prev; Client *prev;

View File

@@ -72,6 +72,7 @@ uicb_tag(uicb_t cmd)
seltag[selscreen] = tmp; seltag[selscreen] = tmp;
} }
} }
ewmh_get_current_desktop();
arrange(); arrange();
client_focus(NULL); client_focus(NULL);

View File

@@ -57,7 +57,7 @@ getcolor(char *color)
{ {
XColor xcolor; XColor xcolor;
if(!XAllocNamedColor(dpy, DefaultColormap(dpy, screen), color, &xcolor, &xcolor)) if(!XAllocNamedColor(dpy, DefaultColormap(dpy, SCREEN), color, &xcolor, &xcolor))
fprintf(stderr,"WMFS Error: cannot allocate color \"%s\"\n", color); fprintf(stderr,"WMFS Error: cannot allocate color \"%s\"\n", color);
return xcolor.pixel; return xcolor.pixel;
} }
@@ -78,30 +78,6 @@ color_enlight(ulong col)
} }
/** Get a Window WM State
* \param win Window
* \return The state
*/
long
getwinstate(Window win)
{
int f;
long ret = -1;
ulong n, e;
uchar *p = NULL;
Atom at;
if(XGetWindowProperty(dpy, win, ATOM("WM_STATE"), 0L, 2L, False,
ATOM("WM_STATE"), &at, &f, &n, &e, (uchar **)&p) != Success)
return -1;
if(n != 0)
ret = *p;
XFree(p);
return ret;
}
/** Round function /** Round function
* \param x double type * \param x double type
* \return the round of x * \return the round of x

View File

@@ -199,7 +199,7 @@ scan(void)
XWindowAttributes wa; XWindowAttributes wa;
Window usl, usl2, *w = NULL; Window usl, usl2, *w = NULL;
if(XQueryTree(dpy, root, &usl, &usl2, &w, &n)) if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n))
for(i = 0; i < n; ++i) for(i = 0; i < n; ++i)
if(XGetWindowAttributes(dpy, w[i], &wa) if(XGetWindowAttributes(dpy, w[i], &wa)
&& !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl)) && !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl))

View File

@@ -48,6 +48,7 @@
#include <confuse.h> #include <confuse.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xmd.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/Xft/Xft.h> #include <X11/Xft/Xft.h>
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
@@ -66,8 +67,10 @@
InputOutput, CopyFromParent, mask, at); \ InputOutput, CopyFromParent, mask, at); \
XSetWindowBackground(dpy, win, col); XSetWindowBackground(dpy, win, col);
#define MAXH DisplayHeight(dpy, screen) #define SCREEN DefaultScreen(dpy)
#define MAXW DisplayWidth(dpy, screen) #define ROOT RootWindow(dpy, SCREEN)
#define MAXH DisplayHeight(dpy, DefaultScreen(dpy))
#define MAXW DisplayWidth(dpy, DefaultScreen(dpy))
#define ATOM(a) XInternAtom(dpy, a, False) #define ATOM(a) XInternAtom(dpy, a, False)
#define INFOBARH font->height * 1.5 #define INFOBARH font->height * 1.5
#define SHADH 1 #define SHADH 1
@@ -126,6 +129,7 @@ Bool ishide(Client *c);
void client_map(Client *c); void client_map(Client *c);
void client_manage(Window w, XWindowAttributes *wa); void client_manage(Window w, XWindowAttributes *wa);
void client_moveresize(Client *c, XRectangle geo, bool r); void client_moveresize(Client *c, XRectangle geo, bool r);
void client_maximize(Client *c);
void client_size_hints(Client *c); void client_size_hints(Client *c);
void client_raise(Client *c); void client_raise(Client *c);
void client_unhide(Client *c); void client_unhide(Client *c);
@@ -136,6 +140,15 @@ void uicb_client_prev(uicb_t);
void uicb_client_next(uicb_t); void uicb_client_next(uicb_t);
void uicb_client_kill(uicb_t); void uicb_client_kill(uicb_t);
/* ewmh.c */
void ewmh_init_hints(void);
void ewmh_get_number_of_desktop(void);
void ewmh_get_current_desktop(void);
void ewmh_get_desktop_names(void);
void ewmh_manage_net_wm_state(long data_l[], Client *c);
void ewmh_manage_window_type(Client *c);
long ewmh_get_wm_state(Window win);
/* frame.c */ /* frame.c */
void frame_create(Client *c); void frame_create(Client *c);
void frame_delete(Client *c); void frame_delete(Client *c);
@@ -178,8 +191,6 @@ void uicb_mouse_resize(uicb_t);
ulong color_enlight(ulong col); ulong color_enlight(ulong col);
void *emalloc(uint element, uint size); void *emalloc(uint element, uint size);
ulong getcolor(char *color); ulong getcolor(char *color);
long getwinstate(Window win);
double round(double x);
void setwinstate(Window win, long state); void setwinstate(Window win, long state);
/* Conf usage {{{ */ /* Conf usage {{{ */
void* name_to_func(char *name, func_name_list_t l[]); void* name_to_func(char *name, func_name_list_t l[]);
@@ -247,8 +258,6 @@ void uicb_reload(uicb_t);
/* Principal */ /* Principal */
Display *dpy; Display *dpy;
GC gc; GC gc;
Window root;
int screen;
int selscreen; int selscreen;
Conf conf; Conf conf;
Key *keys; Key *keys;
@@ -259,6 +268,7 @@ Cursor cursor[CurLast];
/* Fonts */ /* Fonts */
XftFont *font; XftFont *font;
Atom net_atom[net_last];
/* InfoBar */ /* InfoBar */
InfoBar *infobar; InfoBar *infobar;