Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <stdio.h>
22 : : #include <stdlib.h>
23 : : #include <string.h>
24 : : #include <unistd.h>
25 : :
26 : : #include <X11/Xlib.h>
27 : : #include <X11/Xutil.h>
28 : : #include <X11/Xatom.h>
29 : : #include "FWS.hxx"
30 : :
31 : : static Atom fwsIconAtom;
32 : :
33 : : static Atom FWS_CLIENT;
34 : : static Atom FWS_COMM_WINDOW;
35 : : static Atom FWS_PROTOCOLS;
36 : : static Atom FWS_STACK_UNDER;
37 : : static Atom FWS_PARK_ICONS;
38 : : static Atom FWS_PASS_ALL_INPUT;
39 : : static Atom FWS_PASSES_INPUT;
40 : : static Atom FWS_HANDLES_FOCUS;
41 : :
42 : : static Atom FWS_REGISTER_WINDOW;
43 : : static Atom FWS_STATE_CHANGE;
44 : : static Atom FWS_UNSEEN_STATE;
45 : : static Atom FWS_NORMAL_STATE;
46 : : static Atom WM_PROTOCOLS;
47 : : static Atom WM_CHANGE_STATE;
48 : :
49 : : static Bool fwsStackUnder;
50 : : static Bool fwsParkIcons;
51 : : static Bool fwsPassesInput;
52 : : static Bool fwsHandlesFocus;
53 : :
54 : : static Window fwsCommWindow;
55 : :
56 : : /*************************************<->***********************************
57 : : *
58 : : * WMSupportsFWS() -
59 : : *
60 : : * Initialize our atoms and determine if the current window manager is
61 : : * providing FWS extension support.
62 : : *
63 : : *************************************<->***********************************/
64 : :
65 : : Bool
66 : 0 : WMSupportsFWS (Display *display, int screen)
67 : : {
68 : : unsigned int i;
69 : : Atom protocol;
70 : : Atom propType;
71 : : int propFormat;
72 : : unsigned long propItems;
73 : : unsigned long propBytesAfter;
74 : : unsigned char *propData;
75 : : char propName[64];
76 : :
77 : 0 : FWS_CLIENT = XInternAtom(display, "_SUN_FWS_CLIENT", False);
78 : 0 : FWS_COMM_WINDOW = XInternAtom(display, "_SUN_FWS_COMM_WINDOW", False);
79 : 0 : FWS_PROTOCOLS = XInternAtom(display, "_SUN_FWS_PROTOCOLS", False);
80 : 0 : FWS_STACK_UNDER = XInternAtom(display, "_SUN_FWS_STACK_UNDER", False);
81 : 0 : FWS_PARK_ICONS = XInternAtom(display, "_SUN_FWS_PARK_ICONS", False);
82 : 0 : FWS_PASS_ALL_INPUT = XInternAtom(display, "_SUN_FWS_PASS_ALL_INPUT", False);
83 : 0 : FWS_PASSES_INPUT = XInternAtom(display, "_SUN_FWS_PASSES_INPUT", False);
84 : 0 : FWS_HANDLES_FOCUS = XInternAtom(display, "_SUN_FWS_HANDLES_FOCUS", False);
85 : 0 : FWS_REGISTER_WINDOW= XInternAtom(display, "_SUN_FWS_REGISTER_WINDOW",False);
86 : 0 : FWS_STATE_CHANGE = XInternAtom(display, "_SUN_FWS_STATE_CHANGE", False);
87 : 0 : FWS_UNSEEN_STATE = XInternAtom(display, "_SUN_FWS_UNSEEN_STATE", False);
88 : 0 : FWS_NORMAL_STATE = XInternAtom(display, "_SUN_FWS_NORMAL_STATE", False);
89 : 0 : WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", False);
90 : 0 : WM_CHANGE_STATE = XInternAtom(display, "WM_CHANGE_STATE", False);
91 : :
92 : 0 : snprintf (propName, sizeof(propName), "_SUN_FWS_NEXT_ICON_%d", screen);
93 : 0 : fwsIconAtom = XInternAtom(display, propName, False);
94 : :
95 : 0 : if (XGetWindowProperty (display, DefaultRootWindow (display),
96 : : FWS_COMM_WINDOW, 0, 1,
97 : : False, AnyPropertyType, &propType,
98 : : &propFormat, &propItems,
99 : 0 : &propBytesAfter, &propData) != Success)
100 : 0 : return False;
101 : :
102 : 0 : if (propFormat != 32 ||
103 : : propItems != 1 ||
104 : : propBytesAfter != 0)
105 : : {
106 : : #if OSL_DEBUG_LEVEL > 1
107 : : fprintf (stderr, "Bad FWS_COMM_WINDOW property on root window.\n");
108 : : #endif
109 : 0 : XFree (propData);
110 : 0 : return False;
111 : : }
112 : :
113 : 0 : fwsCommWindow = *(Window *) propData;
114 : : #if OSL_DEBUG_LEVEL > 1
115 : : fprintf (stderr, "Using fwsCommWindow = 0x%lx.\n", fwsCommWindow);
116 : : #endif
117 : 0 : XFree (propData);
118 : :
119 : :
120 : 0 : if (XGetWindowProperty (display, DefaultRootWindow (display),
121 : : FWS_PROTOCOLS, 0, 10,
122 : : False, AnyPropertyType, &propType,
123 : : &propFormat, &propItems,
124 : 0 : &propBytesAfter, &propData) != Success)
125 : : {
126 : 0 : return False;
127 : : }
128 : :
129 : 0 : if (propFormat != 32 ||
130 : : propBytesAfter != 0)
131 : : {
132 : : #if OSL_DEBUG_LEVEL > 1
133 : : fprintf (stderr, "Bad FWS_PROTOCOLS property on root window.\n");
134 : : #endif
135 : 0 : XFree (propData);
136 : 0 : return False;
137 : : }
138 : :
139 : 0 : for (i = 0; i < propItems; ++i)
140 : : {
141 : 0 : protocol = ((Atom *) propData)[i];
142 : 0 : if (protocol == FWS_STACK_UNDER)
143 : : {
144 : 0 : fwsStackUnder = True;
145 : : #if OSL_DEBUG_LEVEL > 1
146 : : fprintf (stderr, "Using fwsStackUnder.\n");
147 : : #endif
148 : : }
149 : : else
150 : 0 : if (protocol == FWS_PARK_ICONS)
151 : : {
152 : 0 : fwsParkIcons = True;
153 : : #if OSL_DEBUG_LEVEL > 1
154 : : fprintf (stderr, "Using fwsParkIcons.\n");
155 : : #endif
156 : : }
157 : : else
158 : 0 : if (protocol == FWS_PASSES_INPUT)
159 : : {
160 : 0 : fwsPassesInput = True;
161 : : #if OSL_DEBUG_LEVEL > 1
162 : : fprintf (stderr, "Using fwsPassesInput.\n");
163 : : #endif
164 : : }
165 : : else
166 : 0 : if (protocol == FWS_HANDLES_FOCUS)
167 : : {
168 : 0 : fwsHandlesFocus = True;
169 : : #if OSL_DEBUG_LEVEL > 1
170 : : fprintf (stderr, "Using fwsHandlesFocus.\n");
171 : : #endif
172 : : }
173 : : }
174 : :
175 : 0 : XFree (propData);
176 : 0 : return True;
177 : : }
178 : :
179 : : /*************************************<->***********************************
180 : : *
181 : : * newHandler() -
182 : : *
183 : : * Handle X errors (temporarily) to record the occurrence of BadWindow
184 : : * errors without crashing. Used to detect the FWS_COMM_WINDOW root window
185 : : * property containing an old or obsolete window id.
186 : : *
187 : : *************************************<->***********************************/
188 : :
189 : : extern "C" {
190 : :
191 : : static Bool badWindowFound;
192 : : static int (* oldHandler) (Display *, XErrorEvent *);
193 : :
194 : : static int
195 : 0 : newHandler (Display *display, XErrorEvent *xerror)
196 : : {
197 : 0 : if (xerror->error_code != BadWindow)
198 : 0 : (*oldHandler)(display, xerror);
199 : : else
200 : 0 : badWindowFound = True;
201 : :
202 : 0 : return 0;
203 : : }
204 : :
205 : : }
206 : :
207 : : /*************************************<->***********************************
208 : : *
209 : : * RegisterFwsWindow() -
210 : : *
211 : : * Send a client message to the FWS_COMM_WINDOW indicating the existance
212 : : * of a new FWS client window. Be careful to avoid BadWindow errors on
213 : : * the XSendEvent in case the FWS_COMM_WINDOW root window property had
214 : : * old/obsolete junk in it.
215 : : *
216 : : *************************************<->***********************************/
217 : :
218 : : Bool
219 : 0 : RegisterFwsWindow (Display *display, Window window)
220 : : {
221 : : XClientMessageEvent msg;
222 : :
223 : 0 : msg.type = ClientMessage;
224 : 0 : msg.window = fwsCommWindow;
225 : 0 : msg.message_type = FWS_REGISTER_WINDOW;
226 : 0 : msg.format = 32;
227 : 0 : msg.data.l[0] = window;
228 : :
229 : 0 : XSync (display, False);
230 : 0 : badWindowFound = False;
231 : 0 : oldHandler = XSetErrorHandler (newHandler);
232 : :
233 : : XSendEvent (display, fwsCommWindow, False, NoEventMask,
234 : 0 : (XEvent *) &msg);
235 : 0 : XSync (display, False);
236 : :
237 : 0 : XSetErrorHandler (oldHandler);
238 : : #if OSL_DEBUG_LEVEL > 1
239 : : if (badWindowFound)
240 : : fprintf (stderr, "No FWS client window to register with.\n");
241 : : #endif
242 : :
243 : 0 : return !badWindowFound;
244 : : }
245 : :
246 : : /*************************************<->***********************************
247 : : *
248 : : * AddFwsProtocols -
249 : : *
250 : : * Add the FWS protocol atoms to the WMProtocols property for the window.
251 : : *
252 : : *************************************<->***********************************/
253 : :
254 : : void
255 : 0 : AddFwsProtocols (Display *display, Window window)
256 : : {
257 : : #define MAX_FWS_PROTOS 10
258 : :
259 : : Atom fwsProtocols[ MAX_FWS_PROTOS ];
260 : 0 : int nProtos = 0;
261 : :
262 : 0 : fwsProtocols[ nProtos++ ] = FWS_CLIENT;
263 : 0 : fwsProtocols[ nProtos++ ] = FWS_STACK_UNDER;
264 : 0 : fwsProtocols[ nProtos++ ] = FWS_STATE_CHANGE;
265 : 0 : fwsProtocols[ nProtos++ ] = FWS_PASS_ALL_INPUT;
266 : : XChangeProperty (display, window, WM_PROTOCOLS,
267 : : XA_ATOM, 32, PropModeAppend,
268 : 0 : (unsigned char *) fwsProtocols, nProtos);
269 : 0 : }
270 : :
271 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|