xref: /trunk/main/vcl/unx/generic/window/FWS.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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