648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
1 |
/*
|
2 |
* Taking over the screen
|
|
3 |
*/
|
|
4 |
||
5 |
#include "ctwm.h" |
|
6 |
||
7 |
#include <stdio.h> |
|
8 |
#include <X11/Xproto.h> |
|
9 |
#include <X11/Xmu/Error.h> |
|
10 |
||
11 |
#include "ctwm_takeover.h" |
|
12 |
#include "screen.h" |
|
13 |
||
14 |
||
648.1.5
by Matthew Fuller
Minor commenting. |
15 |
/// Flag for "we got an error trying to take over". Set in temporary
|
16 |
/// error handler.
|
|
17 |
static bool RedirectError; |
|
18 |
||
19 |
// Our special during-takeover and normal operating error handlers.
|
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
20 |
static int CatchRedirectError(Display *display, XErrorEvent *event); |
21 |
static int TwmErrorHandler(Display *display, XErrorEvent *event); |
|
22 |
||
23 |
||
24 |
||
25 |
/**
|
|
26 |
* Take over as WM for a screen
|
|
27 |
*/
|
|
28 |
bool
|
|
29 |
takeover_screen(ScreenInfo *scr) |
|
30 |
{
|
|
31 |
unsigned long attrmask; |
|
32 |
||
33 |
#ifdef EWMH
|
|
34 |
// Early EWMH setup. This tries to do the EWMH display takeover.
|
|
35 |
EwmhInitScreenEarly(scr); |
|
36 |
#endif
|
|
37 |
||
38 |
||
39 |
/*
|
|
40 |
* Subscribe to various events on the root window. Because X
|
|
41 |
* only allows a single client to subscribe to
|
|
42 |
* SubstructureRedirect and ButtonPress bits, this also serves to
|
|
43 |
* mutex who is The WM for the root window, and thus (aside from
|
|
44 |
* captive) the Screen.
|
|
45 |
*
|
|
46 |
* To catch whether that failed, we set a special one-shot error
|
|
47 |
* handler to flip a var that we test to find out whether the
|
|
48 |
* redirect failed.
|
|
49 |
*/
|
|
648.1.6
by Matthew Fuller
Comment takeover function a little. |
50 |
// Flush out any previous errors
|
51 |
XSync(dpy, 0); |
|
52 |
||
53 |
// Set our event listening mask
|
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
54 |
RedirectError = false; |
55 |
XSetErrorHandler(CatchRedirectError); |
|
56 |
attrmask = ColormapChangeMask | EnterWindowMask | |
|
57 |
PropertyChangeMask | SubstructureRedirectMask | |
|
58 |
KeyPressMask | ButtonPressMask | ButtonReleaseMask; |
|
59 |
#ifdef EWMH
|
|
60 |
attrmask |= StructureNotifyMask; |
|
61 |
#endif
|
|
692.1.5
by Matthew Fuller
Add ifdef's around references to Screen and CLargs members that are |
62 |
#ifdef CAPTIVE
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
63 |
if(CLarg.is_captive) { |
64 |
attrmask |= StructureNotifyMask; |
|
65 |
}
|
|
692.1.5
by Matthew Fuller
Add ifdef's around references to Screen and CLargs members that are |
66 |
#endif
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
67 |
XSelectInput(dpy, scr->Root, attrmask); |
648.1.6
by Matthew Fuller
Comment takeover function a little. |
68 |
|
69 |
// Make sure we flush out any errors that may have caused. This
|
|
70 |
// ensures our RedirectError flag will be set if the server sent us
|
|
71 |
// one.
|
|
72 |
XSync(dpy, 0); |
|
73 |
||
74 |
// Go ahead and set our normal-operation error handler.
|
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
75 |
XSetErrorHandler(TwmErrorHandler); |
76 |
||
648.1.6
by Matthew Fuller
Comment takeover function a little. |
77 |
// So, did we fail?
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
78 |
if(RedirectError) { |
79 |
fprintf(stderr, "%s: another window manager is already running", |
|
80 |
ProgramName); |
|
81 |
if(CLarg.MultiScreen && NumScreens > 0) { |
|
82 |
fprintf(stderr, " on screen %d?\n", scr->screen); |
|
83 |
}
|
|
84 |
else { |
|
85 |
fprintf(stderr, "?\n"); |
|
86 |
}
|
|
87 |
||
88 |
// XSetErrorHandler() isn't local to the Screen; it's for the
|
|
89 |
// whole connection. We wind up in a slightly weird state
|
|
90 |
// once we've set it up, but decided we aren't taking over
|
|
91 |
// this screen, but resetting it would be a little weird too,
|
|
92 |
// because maybe we have taken over some other screen. So,
|
|
93 |
// just throw up our hands.
|
|
94 |
return false; |
|
95 |
}
|
|
96 |
||
648.1.6
by Matthew Fuller
Comment takeover function a little. |
97 |
// Nope, it's ours!
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
98 |
return true; |
99 |
}
|
|
100 |
||
101 |
||
648.1.4
by Matthew Fuller
Doc and comment error handler funcs. Some logic flow rewritten for |
102 |
|
103 |
/**
|
|
104 |
* Temporary error handler used during startup. We expect an
|
|
105 |
* error if we fail to take over some of the XSelectInput() events
|
|
106 |
* we're trying to (which only 1 thing at a time is allowed to).
|
|
107 |
* Probably that would be a BadAccess error type? But really, any error
|
|
108 |
* means we're in trouble and should skip over the display, so we don't
|
|
109 |
* check any more deeply...
|
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
110 |
*/
|
111 |
static int |
|
112 |
CatchRedirectError(Display *display, XErrorEvent *event) |
|
113 |
{
|
|
648.1.4
by Matthew Fuller
Doc and comment error handler funcs. Some logic flow rewritten for |
114 |
// Set the global flag
|
648.1.2
by Matthew Fuller
Minimal move of these takeover-related funcs to their own file to |
115 |
RedirectError = true; |
116 |
return 0; |
|
117 |
}
|
|
648.1.4
by Matthew Fuller
Doc and comment error handler funcs. Some logic flow rewritten for |
118 |
|
119 |
||
120 |
/**
|
|
121 |
* Error handler used in normal operation. Or, perhaps, error ignorer
|
|
122 |
* used in normal operation. If run with `-v`, we'll print out a lot of
|
|
123 |
* the errors we might get, though we always skip several.
|
|
124 |
*/
|
|
125 |
static int |
|
126 |
TwmErrorHandler(Display *display, XErrorEvent *event) |
|
127 |
{
|
|
128 |
if(!CLarg.PrintErrorMessages) { |
|
129 |
// Not `-v`? Always be silent.
|
|
130 |
return 0; |
|
131 |
}
|
|
132 |
||
133 |
// If a client dies and we try to touch it before we notice, we get a
|
|
134 |
// BadWindow error for most operations, except a few (GetGeometry
|
|
135 |
// being the big one?) where we'll get a BadDrawable. This isn't
|
|
136 |
// really an "error", just a harmless race.
|
|
137 |
if(event->error_code == BadWindow |
|
648.1.7
by Matthew Fuller
make indent |
138 |
|| (event->request_code == X_GetGeometry && event->error_code != BadDrawable)) { |
648.1.4
by Matthew Fuller
Doc and comment error handler funcs. Some logic flow rewritten for |
139 |
return 0; |
140 |
}
|
|
141 |
||
142 |
// Else, we're `-v`'d, and it wasn't one of our 'expected' bits, so
|
|
143 |
// talk about it.
|
|
144 |
XmuPrintDefaultErrorMessage(display, event, stderr); |
|
145 |
return 0; |
|
146 |
}
|