Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
266 lines (231 sloc) 8.1 KB
/* WindowLab - an X11 window manager
* Copyright (c) 2001-2010 Nick Gravgaard
* me at nickgravgaard.com
* http://nickgravgaard.com/windowlab/
*
* 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <signal.h>
#include <X11/cursorfont.h>
#include "windowlab.h"
Display *dsply = NULL;
Window root;
int screen;
XFontStruct *font = NULL;
#ifdef XFT
XftFont *xftfont = NULL;
XftColor xft_detail;
#endif
GC string_gc, border_gc, text_gc, active_gc, depressed_gc, inactive_gc, menu_gc, selected_gc, empty_gc;
XColor border_col, text_col, active_col, depressed_col, inactive_col, menu_col, selected_col, empty_col;
Cursor resize_curs;
Atom wm_state, wm_change_state, wm_protos, wm_delete, wm_cmapwins;
#ifdef MWM_HINTS
Atom mwm_hints;
#endif
Client *head_client = NULL, *focused_client = NULL, *topmost_client = NULL, *fullscreen_client = NULL;
unsigned int in_taskbar = 0; // actually, we don't know yet
unsigned int showing_taskbar = 1;
unsigned int focus_count = 0;
Rect fs_prevdims;
char *opt_font = DEF_FONT;
char *opt_border = DEF_BORDER;
char *opt_text = DEF_TEXT;
char *opt_active = DEF_ACTIVE;
char *opt_inactive = DEF_INACTIVE;
char *opt_menu = DEF_MENU;
char *opt_selected = DEF_SELECTED;
char *opt_empty = DEF_EMPTY;
char *opt_display = NULL;
#ifdef SHAPE
Bool shape;
int shape_event;
#endif
unsigned int numlockmask = 0;
static void scan_wins(void);
static void setup_display(void);
int main(int argc, char **argv)
{
int i;
struct sigaction act;
#define OPT_STR(name, variable) \
if (strcmp(argv[i], name) == 0 && i + 1 < argc) \
{ \
variable = argv[++i]; \
continue; \
}
for (i = 1; i < argc; i++)
{
OPT_STR("-font", opt_font)
OPT_STR("-border", opt_border)
OPT_STR("-text", opt_text)
OPT_STR("-active", opt_active)
OPT_STR("-inactive", opt_inactive)
OPT_STR("-menu", opt_menu)
OPT_STR("-selected", opt_selected)
OPT_STR("-empty", opt_empty)
OPT_STR("-display", opt_display)
if (strcmp(argv[i], "-about") == 0)
{
printf("WindowLab " VERSION " (" RELEASEDATE "), Copyright (c) 2001-2009 Nick Gravgaard\nWindowLab comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; view the LICENCE file for details.\n");
exit(0);
}
// shouldn't get here; must be a bad option
err("usage:\n windowlab [options]\n\noptions are:\n -font <font>\n -border|-text|-active|-inactive|-menu|-selected|-empty <color>\n -about\n -display <display>");
return 2;
}
act.sa_handler = sig_handler;
act.sa_flags = 0;
sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
setup_display();
get_menuitems();
make_taskbar();
scan_wins();
do_event_loop();
return 1; // just another brick in the -Wall
}
static void scan_wins(void)
{
unsigned int nwins, i;
Window dummyw1, dummyw2, *wins;
XWindowAttributes attr;
XQueryTree(dsply, root, &dummyw1, &dummyw2, &wins, &nwins);
for (i = 0; i < nwins; i++)
{
XGetWindowAttributes(dsply, wins[i], &attr);
if (!attr.override_redirect && attr.map_state == IsViewable)
{
make_new_client(wins[i]);
}
}
XFree(wins);
}
static void setup_display(void)
{
XColor dummyc;
XGCValues gv;
XSetWindowAttributes sattr;
XModifierKeymap *modmap;
int i, j;
#ifdef SHAPE
int dummy;
#endif
dsply = XOpenDisplay(opt_display);
if (dsply == NULL)
{
err("can't open display! check your DISPLAY variable.");
exit(1);
}
XSetErrorHandler(handle_xerror);
screen = DefaultScreen(dsply);
root = RootWindow(dsply, screen);
wm_state = XInternAtom(dsply, "WM_STATE", False);
wm_change_state = XInternAtom(dsply, "WM_CHANGE_STATE", False);
wm_protos = XInternAtom(dsply, "WM_PROTOCOLS", False);
wm_delete = XInternAtom(dsply, "WM_DELETE_WINDOW", False);
wm_cmapwins = XInternAtom(dsply, "WM_COLORMAP_WINDOWS", False);
#ifdef MWM_HINTS
mwm_hints = XInternAtom(dsply, _XA_MWM_HINTS, False);
#endif
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_border, &border_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_text, &text_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_active, &active_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_inactive, &inactive_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_menu, &menu_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_selected, &selected_col, &dummyc);
XAllocNamedColor(dsply, DefaultColormap(dsply, screen), opt_empty, &empty_col, &dummyc);
depressed_col.pixel = active_col.pixel;
depressed_col.red = active_col.red - ACTIVE_SHADOW;
depressed_col.green = active_col.green - ACTIVE_SHADOW;
depressed_col.blue = active_col.blue - ACTIVE_SHADOW;
depressed_col.red = depressed_col.red <= (USHRT_MAX - ACTIVE_SHADOW) ? depressed_col.red : 0;
depressed_col.green = depressed_col.green <= (USHRT_MAX - ACTIVE_SHADOW) ? depressed_col.green : 0;
depressed_col.blue = depressed_col.blue <= (USHRT_MAX - ACTIVE_SHADOW) ? depressed_col.blue : 0;
XAllocColor(dsply, DefaultColormap(dsply, screen), &depressed_col);
#ifdef XFT
xft_detail.color.red = text_col.red;
xft_detail.color.green = text_col.green;
xft_detail.color.blue = text_col.blue;
xft_detail.color.alpha = 0xffff;
xft_detail.pixel = text_col.pixel;
xftfont = XftFontOpenXlfd(dsply, DefaultScreen(dsply), opt_font);
if (xftfont == NULL)
{
err("font '%s' not found", opt_font);
exit(1);
}
#else
font = XLoadQueryFont(dsply, opt_font);
if (font == NULL)
{
err("XLoadQueryFont(): font '%s' not found", opt_font);
exit(1);
}
#endif
#ifdef SHAPE
shape = XShapeQueryExtension(dsply, &shape_event, &dummy);
#endif
resize_curs = XCreateFontCursor(dsply, XC_fleur);
/* find out which modifier is NumLock - we'll use this when grabbing every combination of modifiers we can think of */
modmap = XGetModifierMapping(dsply);
for (i = 0; i < 8; i++)
{
for (j = 0; j < modmap->max_keypermod; j++)
{
if (modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dsply, XK_Num_Lock))
{
numlockmask = (1 << i);
#ifdef DEBUG
fprintf(stderr, "setup_display() : XK_Num_Lock is (1<<0x%02x)\n", i);
#endif
}
}
}
XFree(modmap);
gv.function = GXcopy;
gv.foreground = border_col.pixel;
gv.line_width = DEF_BORDERWIDTH;
border_gc = XCreateGC(dsply, root, GCFunction|GCForeground|GCLineWidth, &gv);
gv.foreground = text_col.pixel;
gv.line_width = 1;
#ifdef XFT
text_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
#else
gv.font = font->fid;
text_gc = XCreateGC(dsply, root, GCFunction|GCForeground|GCFont, &gv);
#endif
gv.foreground = active_col.pixel;
active_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
gv.foreground = depressed_col.pixel;
depressed_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
gv.foreground = inactive_col.pixel;
inactive_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
gv.foreground = menu_col.pixel;
menu_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
gv.foreground = selected_col.pixel;
selected_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
gv.foreground = empty_col.pixel;
empty_gc = XCreateGC(dsply, root, GCFunction|GCForeground, &gv);
sattr.event_mask = ChildMask|ColormapChangeMask|ButtonMask;
XChangeWindowAttributes(dsply, root, CWEventMask, &sattr);
grab_keysym(root, MODIFIER, KEY_CYCLEPREV);
grab_keysym(root, MODIFIER, KEY_CYCLENEXT);
grab_keysym(root, MODIFIER, KEY_FULLSCREEN);
grab_keysym(root, MODIFIER, KEY_TOGGLEZ);
}