xref: /trunk/main/vcl/unx/generic/window/FWS.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 #include <X11/Xlib.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xatom.h>
39 #include "FWS.hxx"
40 
41 static Atom fwsIconAtom;
42 
43 static Atom FWS_CLIENT;
44 static Atom FWS_COMM_WINDOW;
45 static Atom FWS_PROTOCOLS;
46 static Atom FWS_STACK_UNDER;
47 static Atom FWS_PARK_ICONS;
48 static Atom FWS_PASS_ALL_INPUT;
49 static Atom FWS_PASSES_INPUT;
50 static Atom FWS_HANDLES_FOCUS;
51 
52 static Atom FWS_REGISTER_WINDOW;
53 static Atom FWS_STATE_CHANGE;
54 static Atom FWS_UNSEEN_STATE;
55 static Atom FWS_NORMAL_STATE;
56 static Atom WM_PROTOCOLS;
57 static Atom WM_CHANGE_STATE;
58 
59 static Bool fwsStackUnder;
60 static Bool fwsParkIcons;
61 static Bool fwsPassesInput;
62 static Bool fwsHandlesFocus;
63 
64 static Window fwsCommWindow;
65 
66 /*************************************<->***********************************
67  *
68  * WMSupportsFWS() -
69  *
70  * Initialize our atoms and determine if the current window manager is
71  * providing FWS extension support.
72  *
73  *************************************<->***********************************/
74 
75 Bool
76 WMSupportsFWS (Display *display, int screen)
77 {
78 	unsigned int    i;
79 	Atom            protocol;
80 	Atom            propType;
81 	int             propFormat;
82 	unsigned long   propItems;
83 	unsigned long   propBytesAfter;
84 	unsigned char   *propData;
85 	char            propName[64];
86 
87 	FWS_CLIENT         = XInternAtom(display, "_SUN_FWS_CLIENT",         False);
88 	FWS_COMM_WINDOW    = XInternAtom(display, "_SUN_FWS_COMM_WINDOW",    False);
89 	FWS_PROTOCOLS      = XInternAtom(display, "_SUN_FWS_PROTOCOLS",      False);
90 	FWS_STACK_UNDER    = XInternAtom(display, "_SUN_FWS_STACK_UNDER",    False);
91 	FWS_PARK_ICONS     = XInternAtom(display, "_SUN_FWS_PARK_ICONS",     False);
92 	FWS_PASS_ALL_INPUT = XInternAtom(display, "_SUN_FWS_PASS_ALL_INPUT", False);
93 	FWS_PASSES_INPUT   = XInternAtom(display, "_SUN_FWS_PASSES_INPUT",   False);
94 	FWS_HANDLES_FOCUS  = XInternAtom(display, "_SUN_FWS_HANDLES_FOCUS",  False);
95 	FWS_REGISTER_WINDOW= XInternAtom(display, "_SUN_FWS_REGISTER_WINDOW",False);
96 	FWS_STATE_CHANGE   = XInternAtom(display, "_SUN_FWS_STATE_CHANGE",   False);
97 	FWS_UNSEEN_STATE   = XInternAtom(display, "_SUN_FWS_UNSEEN_STATE",   False);
98 	FWS_NORMAL_STATE   = XInternAtom(display, "_SUN_FWS_NORMAL_STATE",   False);
99 	WM_PROTOCOLS       = XInternAtom(display, "WM_PROTOCOLS",            False);
100 	WM_CHANGE_STATE    = XInternAtom(display, "WM_CHANGE_STATE",         False);
101 
102 	snprintf (propName, sizeof(propName), "_SUN_FWS_NEXT_ICON_%d", screen);
103 	fwsIconAtom        = XInternAtom(display, propName, False);
104 
105 	if (XGetWindowProperty (display, DefaultRootWindow (display),
106 				FWS_COMM_WINDOW, 0, 1,
107 				False, AnyPropertyType, &propType,
108 				&propFormat, &propItems,
109 				&propBytesAfter, &propData) != Success)
110 		return False;
111 
112 	if (propFormat != 32 ||
113 	    propItems != 1 ||
114 	    propBytesAfter != 0)
115 	{
116         #if OSL_DEBUG_LEVEL > 1
117 		fprintf (stderr, "Bad FWS_COMM_WINDOW property on root window.\n");
118 		#endif
119 		XFree (propData);
120 		return False;
121 	}
122 
123 	fwsCommWindow = *(Window *) propData;
124     #if OSL_DEBUG_LEVEL > 1
125 	fprintf (stderr, "Using fwsCommWindow = 0x%lx.\n", fwsCommWindow);
126 	#endif
127 	XFree (propData);
128 
129 
130 	if (XGetWindowProperty (display, DefaultRootWindow (display),
131 			FWS_PROTOCOLS, 0, 10,
132 			False, AnyPropertyType, &propType,
133 			&propFormat, &propItems,
134 			&propBytesAfter, &propData) != Success)
135 	{
136 		return False;
137 	}
138 
139 	if (propFormat     != 32 ||
140 	    propBytesAfter != 0)
141 	{
142         #if OSL_DEBUG_LEVEL > 1
143 		fprintf (stderr, "Bad FWS_PROTOCOLS property on root window.\n");
144 		#endif
145 		XFree (propData);
146 		return False;
147 	}
148 
149 	for (i = 0; i < propItems; ++i)
150 	{
151 		protocol = ((Atom *) propData)[i];
152 		if (protocol == FWS_STACK_UNDER)
153 		{
154 			fwsStackUnder = True;
155             #if OSL_DEBUG_LEVEL > 1
156 			fprintf (stderr, "Using fwsStackUnder.\n");
157 			#endif
158 		}
159 		else
160 		if (protocol == FWS_PARK_ICONS)
161 		{
162 			fwsParkIcons = True;
163             #if OSL_DEBUG_LEVEL > 1
164 			fprintf (stderr, "Using fwsParkIcons.\n");
165 			#endif
166 		}
167 		else
168 		if (protocol == FWS_PASSES_INPUT)
169 		{
170 			fwsPassesInput = True;
171             #if OSL_DEBUG_LEVEL > 1
172 			fprintf (stderr, "Using fwsPassesInput.\n");
173 			#endif
174 		}
175 		else
176 		if (protocol == FWS_HANDLES_FOCUS)
177 		{
178 			fwsHandlesFocus = True;
179             #if OSL_DEBUG_LEVEL > 1
180 			fprintf (stderr, "Using fwsHandlesFocus.\n");
181 			#endif
182 		}
183 	}
184 
185 	XFree (propData);
186 	return True;
187 }
188 
189 /*************************************<->***********************************
190  *
191  * newHandler() -
192  *
193  * Handle X errors (temporarily) to record the occurance of BadWindow
194  * errors without crashing.  Used to detect the FWS_COMM_WINDOW root window
195  * property containing an old or obsolete window id.
196  *
197  *************************************<->***********************************/
198 
199 extern "C" {
200 
201 static Bool badWindowFound;
202 static int (* oldHandler) (Display *, XErrorEvent *);
203 
204 static int
205 newHandler (Display *display, XErrorEvent *xerror)
206 {
207 	if (xerror->error_code != BadWindow)
208 		(*oldHandler)(display, xerror);
209 	else
210 		badWindowFound = True;
211 
212 	return 0;
213 }
214 
215 }
216 
217 /*************************************<->***********************************
218  *
219  * RegisterFwsWindow() -
220  *
221  * Send a client message to the FWS_COMM_WINDOW indicating the existance
222  * of a new FWS client window.  Be careful to avoid BadWindow errors on
223  * the XSendEvent in case the FWS_COMM_WINDOW root window property had
224  * old/obsolete junk in it.
225  *
226  *************************************<->***********************************/
227 
228 Bool
229 RegisterFwsWindow (Display *display, Window window)
230 {
231 	XClientMessageEvent  msg;
232 
233 	msg.type         = ClientMessage;
234 	msg.window       = fwsCommWindow;
235 	msg.message_type = FWS_REGISTER_WINDOW;
236 	msg.format       = 32;
237 	msg.data.l[0]    = window;
238 
239 	XSync (display, False);
240 	badWindowFound = False;
241 	oldHandler = XSetErrorHandler (newHandler);
242 
243 	XSendEvent (display, fwsCommWindow, False, NoEventMask,
244 		    (XEvent *) &msg);
245 	XSync (display, False);
246 
247 	XSetErrorHandler (oldHandler);
248     #if OSL_DEBUG_LEVEL > 1
249 	if (badWindowFound)
250 		fprintf (stderr, "No FWS client window to register with.\n");
251 	#endif
252 
253 	return !badWindowFound;
254 }
255 
256 /*************************************<->***********************************
257  *
258  * AddFwsProtocols -
259  *
260  * Add the FWS protocol atoms to the WMProtocols property for the window.
261  *
262  *************************************<->***********************************/
263 
264 void
265 AddFwsProtocols (Display *display, Window window)
266 {
267 	#define MAX_FWS_PROTOS 10
268 
269 	Atom fwsProtocols[ MAX_FWS_PROTOS ];
270 	int  nProtos = 0;
271 
272 	fwsProtocols[ nProtos++ ] = FWS_CLIENT;
273 	fwsProtocols[ nProtos++ ] = FWS_STACK_UNDER;
274 	fwsProtocols[ nProtos++ ] = FWS_STATE_CHANGE;
275 	fwsProtocols[ nProtos++ ] = FWS_PASS_ALL_INPUT;
276 	XChangeProperty (display, window, WM_PROTOCOLS,
277 			XA_ATOM, 32, PropModeAppend,
278 			(unsigned char *) fwsProtocols, nProtos);
279 }
280 
281