root/main.c

Revision 1, 9.8 KB (checked in by root, 3 years ago)

Initial commit

Line 
1/* evilwm - Minimalist Window Manager for X
2 * Copyright (C) 1999-2006 Ciaran Anscomb <evilwm@6809.org.uk>
3 * see README for license and other details. */
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <signal.h>
9#include <X11/cursorfont.h>
10#include "evilwm.h"
11#include "log.h"
12
13/* Commonly used X information */
14Display     *dpy;
15XFontStruct *font;
16Cursor      move_curs;
17Cursor      resize_curs;
18int         num_screens;
19ScreenInfo  *screens;
20#ifdef SHAPE
21int         have_shape, shape_event;
22#endif
23
24/* Standard X protocol atoms */
25Atom xa_wm_state;
26Atom xa_wm_protos;
27Atom xa_wm_delete;
28Atom xa_wm_cmapwins;
29/* Motif atoms */
30Atom mwm_hints;
31/* EWMH atoms */
32#ifdef VWM
33Atom xa_net_wm_desktop;
34Atom xa_net_wm_state;
35Atom xa_net_wm_state_sticky;
36#endif
37
38/* Things that affect user interaction */
39static const char   *opt_display = "";
40static const char   *opt_font = DEF_FONT;
41static const char   *opt_fg = DEF_FG;
42static const char   *opt_bg = DEF_BG;
43#ifdef VWM
44static const char   *opt_fc = DEF_FC;
45#endif
46unsigned int numlockmask = 0;
47unsigned int grabmask1 = ControlMask|Mod1Mask;
48unsigned int grabmask2 = Mod1Mask;
49unsigned int altmask = ShiftMask;
50const char   *opt_term[3] = { DEF_TERM, DEF_TERM, NULL };
51int          opt_bw = DEF_BW;
52#ifdef SNAP
53int          opt_snap = 0;
54#endif
55#ifdef SOLIDDRAG
56int          solid_drag = 1;  /* use solid drag by default */
57#endif
58Application  *head_app = NULL;
59
60/* Client tracking information */
61Client          *head_client = NULL;
62Client          *current = NULL;
63volatile Window initialising = None;
64
65static void setup_display(void);
66static void *xmalloc(size_t size);
67static unsigned int parse_modifiers(char *s);
68
69int wm_main(int argc, char **argv) {
70        struct sigaction act;
71        int i;
72
73        for (i = 1; i < argc; i++) {
74                if (!strcmp(argv[i], "-fn") && i+1<argc)
75                        opt_font = argv[++i];
76                else if (!strcmp(argv[i], "-display") && i+1<argc) {
77                        opt_display = argv[++i];
78                }
79                else if (!strcmp(argv[i], "-fg") && i+1<argc)
80                        opt_fg = argv[++i];
81                else if (!strcmp(argv[i], "-bg") && i+1<argc)
82                        opt_bg = argv[++i];
83#ifdef VWM
84                else if (!strcmp(argv[i], "-fc") && i+1<argc)
85                        opt_fc = argv[++i];
86#endif
87                else if (!strcmp(argv[i], "-bw") && i+1<argc)
88                        opt_bw = atoi(argv[++i]);
89                else if (!strcmp(argv[i], "-term") && i+1<argc) {
90                        opt_term[0] = argv[++i];
91                        opt_term[1] = opt_term[0];
92#ifdef SNAP
93                } else if (!strcmp(argv[i], "-snap") && i+1<argc) {
94                        opt_snap = atoi(argv[++i]);
95#endif
96                } else if (!strcmp(argv[i], "-app") && i+1<argc) {
97                        Application *new = xmalloc(sizeof(Application));
98                        char *tmp;
99                        i++;
100                        new->res_name = new->res_class = NULL;
101                        new->geometry_mask = 0;
102#ifdef VWM
103                        new->vdesk = -1;
104                        new->sticky = 0;
105#endif
106                        if ((tmp = strchr(argv[i], '/'))) {
107                                *(tmp++) = 0;
108                        }
109                        if (strlen(argv[i]) > 0) {
110                                new->res_name = xmalloc(strlen(argv[i])+1);
111                                strcpy(new->res_name, argv[i]);
112                        }
113                        if (tmp && strlen(tmp) > 0) {
114                                new->res_class = xmalloc(strlen(tmp)+1);
115                                strcpy(new->res_class, tmp);
116                        }
117                        new->next = head_app;
118                        head_app = new;
119                } else if (!strcmp(argv[i], "-g") && i+1<argc) {
120                        i++;
121                        if (!head_app)
122                                continue;
123                        head_app->geometry_mask = XParseGeometry(argv[i],
124                                        &head_app->x, &head_app->y,
125                                        &head_app->width, &head_app->height);
126#ifdef VWM
127                } else if (!strcmp(argv[i], "-v") && i+1<argc) {
128                        int v = atoi(argv[++i]);
129                        if (head_app && valid_vdesk(v))
130                                head_app->vdesk = v;
131                } else if (!strcmp(argv[i], "-s")) {
132                        if (head_app)
133                                head_app->sticky = 1;
134#endif
135                } else if (!strcmp(argv[i], "-mask1") && i+1<argc) {
136                        i++;
137                        grabmask1 = parse_modifiers(argv[i]);
138                } else if (!strcmp(argv[i], "-mask2") && i+1<argc) {
139                        i++;
140                        grabmask2 = parse_modifiers(argv[i]);
141                } else if (!strcmp(argv[i], "-altmask") && i+1<argc) {
142                        i++;
143                        altmask = parse_modifiers(argv[i]);
144#ifdef SOLIDDRAG
145                } else if (!strcmp(argv[i], "-nosoliddrag")) {
146                        solid_drag = 0;
147#endif
148#ifdef STDIO
149                } else if (!strcmp(argv[i], "-V")) {
150                        LOG_INFO("evilwm version " VERSION "\n");
151                        exit(0);
152#endif
153                } else {
154                        LOG_INFO("usage: evilwm [-display display] [-term termprog] [-fn fontname]\n");
155                        LOG_INFO("              [-fg foreground]");
156#ifdef VWM
157                        LOG_INFO(" [-fc fixed]");
158#endif
159                        LOG_INFO(" [-bg background] [-bw borderwidth]\n");
160                        LOG_INFO("              [-mask1 modifiers] [-mask2 modifiers] [-altmask modifiers]\n");
161                        LOG_INFO("              [-snap num]");
162#ifdef VWM
163                        LOG_INFO(" [-app name/class] [-g geometry] [-v vdesk] [-s]");
164#endif
165#ifdef SOLIDDRAG
166                        LOG_INFO("\n              [-nosoliddrag]");
167#endif
168                        LOG_INFO(" [-V]\n");
169                        exit((!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))?0:1);
170                }
171        }
172
173        act.sa_handler = handle_signal;
174        sigemptyset(&act.sa_mask);
175        act.sa_flags = 0;
176        sigaction(SIGTERM, &act, NULL);
177        sigaction(SIGINT, &act, NULL);
178        sigaction(SIGHUP, &act, NULL);
179
180        setup_display();
181
182        event_main_loop();
183
184        return 1;
185}
186
187static void *xmalloc(size_t size) {
188        void *ptr = malloc(size);
189        if (!ptr) {
190                /* C99 defines the 'z' printf modifier for variables of
191                 * type size_t.  Fall back to casting to unsigned long. */
192#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
193                LOG_ERROR("out of memory, looking for %zu bytes\n", size);
194#else
195                LOG_ERROR("out of memory, looking for %lu bytes\n",
196                                (unsigned long)size);
197#endif
198                exit(1);
199        }
200        return ptr;
201}
202
203static void setup_display(void) {
204        XGCValues gv;
205        XSetWindowAttributes attr;
206        XColor dummy;
207        XModifierKeymap *modmap;
208        /* used in scanning windows (XQueryTree) */
209        unsigned int i, j, nwins;
210        Window dw1, dw2, *wins;
211        XWindowAttributes winattr;
212
213        XInitThreads(); //todo ...
214
215        dpy = XOpenDisplay(opt_display);
216        if (!dpy) { 
217                LOG_ERROR("can't open display %s\n", opt_display);
218                exit(1);
219        }
220        XSetErrorHandler(handle_xerror);
221        /* XSynchronize(dpy, True); */
222
223        /* Standard X protocol atoms */
224        xa_wm_state = XInternAtom(dpy, "WM_STATE", False);
225        xa_wm_protos = XInternAtom(dpy, "WM_PROTOCOLS", False);
226        xa_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
227#ifdef COLOURMAP
228        xa_wm_cmapwins = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
229#endif
230        /* Motif atoms */
231        mwm_hints = XInternAtom(dpy, _XA_MWM_HINTS, False);
232        /* EWMH atoms */
233#ifdef VWM
234        xa_net_wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
235        xa_net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
236        xa_net_wm_state_sticky = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False);
237#endif
238
239        font = XLoadQueryFont(dpy, opt_font);
240        if (!font) font = XLoadQueryFont(dpy, DEF_FONT);
241        if (!font) {
242                LOG_ERROR("couldn't find a font to use: try starting with -fn fontname\n");
243                exit(1);
244        }
245
246        move_curs = XCreateFontCursor(dpy, XC_fleur);
247        resize_curs = XCreateFontCursor(dpy, XC_plus);
248
249        /* find out which modifier is NumLock - we'll use this when grabbing
250         * every combination of modifiers we can think of */
251        modmap = XGetModifierMapping(dpy);
252        for (i = 0; i < 8; i++) {
253                for (j = 0; j < (unsigned int)modmap->max_keypermod; j++) {
254                        if (modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode(dpy, XK_Num_Lock)) {
255                                numlockmask = (1<<i);
256                                LOG_DEBUG("setup_display() : XK_Num_Lock is (1<<0x%02x)\n", i);
257                        }
258                }
259        }
260        XFreeModifiermap(modmap);
261
262        /* set up GC parameters - same for each screen */
263        gv.function = GXinvert;
264        gv.subwindow_mode = IncludeInferiors;
265        gv.line_width = 1;  /* opt_bw */
266        gv.font = font->fid;
267
268        /* set up root window attributes - same for each screen */
269#ifdef COLOURMAP
270        attr.event_mask = ChildMask | EnterWindowMask | ColormapChangeMask;
271#else
272        attr.event_mask = ChildMask | EnterWindowMask;
273#endif
274
275        /* SHAPE extension? */
276#ifdef SHAPE
277        {
278                int e_dummy;
279                have_shape = XShapeQueryExtension(dpy, &shape_event, &e_dummy);
280        }
281#endif
282
283        /* now set up each screen in turn */
284        num_screens = ScreenCount(dpy);
285        if (num_screens < 0) {
286                LOG_ERROR("Can't count screens\n");
287                exit(1);
288        }
289        screens = xmalloc(num_screens * sizeof(ScreenInfo));
290        for (i = 0; i < (unsigned int)num_screens; i++) {
291                char *ds, *colon, *dot;
292                ds = DisplayString(dpy);
293                /* set up DISPLAY environment variable to use */
294                colon = strrchr(ds, ':');
295                if (colon && num_screens > 1) {
296                        screens[i].display = xmalloc(14 + strlen(ds));
297                        strcpy(screens[i].display, "DISPLAY=");
298                        strcat(screens[i].display, ds);
299                        colon = strrchr(screens[i].display, ':');
300                        dot = strchr(colon, '.');
301                        if (!dot)
302                                dot = colon + strlen(colon);
303                        snprintf(dot, 5, ".%d", i);
304                } else
305                        screens[i].display = NULL;
306
307                screens[i].screen = i;
308                screens[i].root = RootWindow(dpy, i);
309#ifdef VWM
310                screens[i].vdesk = KEY_TO_VDESK(XK_1);
311#endif
312
313                XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_fg, &screens[i].fg, &dummy);
314                XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_bg, &screens[i].bg, &dummy);
315#ifdef VWM
316                XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_fc, &screens[i].fc, &dummy);
317#endif
318
319                screens[i].invert_gc = XCreateGC(dpy, screens[i].root, GCFunction | GCSubwindowMode | GCLineWidth | GCFont, &gv);
320
321                XChangeWindowAttributes(dpy, screens[i].root, CWEventMask, &attr);
322                grab_keys_for_screen(&screens[i]);
323
324                /* scan all the windows on this screen */
325                LOG_XDEBUG("main:XQueryTree(); ");
326                XQueryTree(dpy, screens[i].root, &dw1, &dw2, &wins, &nwins);
327                LOG_XDEBUG("%d windows\n", nwins);
328                for (j = 0; j < nwins; j++) {
329                        XGetWindowAttributes(dpy, wins[j], &winattr);
330                        if (!winattr.override_redirect && winattr.map_state == IsViewable)
331                                make_new_client(wins[j], &screens[i]);
332                }
333                XFree(wins);
334        }
335}
336
337/* Used for overriding the default WM modifiers */
338static unsigned int parse_modifiers(char *s) {
339        static struct {
340                const char *name;
341                unsigned int mask;
342        } modifiers[9] = {
343                { "shift", ShiftMask },
344                { "lock", LockMask },
345                { "control", ControlMask },
346                { "alt", Mod1Mask },
347                { "mod1", Mod1Mask },
348                { "mod2", Mod2Mask },
349                { "mod3", Mod3Mask },
350                { "mod4", Mod4Mask },
351                { "mod5", Mod5Mask }
352        };
353        char *tmp = strtok(s, ",+");
354        unsigned int ret = 0;
355        int i;
356        if (!tmp)
357                return 0;
358        do {
359                for (i = 0; i < 9; i++) {
360                        if (!strcmp(modifiers[i].name, tmp))
361                                ret |= modifiers[i].mask;
362                }
363                tmp = strtok(NULL, ",+");
364        } while (tmp);
365        return ret;
366}
Note: See TracBrowser for help on using the browser.