xref: /trunk/main/vcl/unx/generic/app/wmadaptor.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 <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 #include "sal/alloca.h"
36 #include "rtl/locale.h"
37 
38 #include "osl/thread.h"
39 #include "osl/process.h"
40 
41 #include "vcl/configsettings.hxx"
42 
43 #include "unx/wmadaptor.hxx"
44 #include "unx/saldisp.hxx"
45 #include "unx/saldata.hxx"
46 #include "unx/salframe.h"
47 
48 #include "salgdi.hxx"
49 
50 #include "tools/prex.h"
51 #include <X11/X.h>
52 #include <X11/Xatom.h>
53 #include <X11/Xresource.h>
54 #include "tools/postx.h"
55 
56 #if OSL_DEBUG_LEVEL > 1
57 #include <stdio.h>
58 #endif
59 
60 namespace vcl_sal {
61 
62 class NetWMAdaptor : public WMAdaptor
63 {
64     void setNetWMState( X11SalFrame* pFrame ) const;
65     void initAtoms();
66     virtual bool isValid() const;
67 public:
68     NetWMAdaptor( SalDisplay* );
69     virtual ~NetWMAdaptor();
70 
71     virtual void setWMName( X11SalFrame* pFrame, const String& rWMName ) const;
72     virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const;
73     virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const;
74     virtual void setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pTransientFrame = NULL ) const;
75     virtual bool supportsICCCMPos() const;
76     virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const;
77     virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const;
78     virtual void showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const;
79     virtual void frameIsMapping( X11SalFrame* pFrame ) const;
80     virtual void setFrameStruts( X11SalFrame* pFrame,
81                                  int left, int right, int top, int bottom,
82                                  int left_start_y, int left_end_y,
83                                  int right_start_y, int right_end_y,
84                                  int top_start_x, int top_end_x,
85                                  int bottom_start_x, int bottom_end_x ) const;
86     virtual void setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const;
87     virtual void setFullScreenMonitors( XLIB_Window i_aWindow, sal_Int32 i_nScreen );
88 };
89 
90 class GnomeWMAdaptor : public WMAdaptor
91 {
92     bool m_bValid;
93 
94     void setGnomeWMState( X11SalFrame* pFrame ) const;
95     void initAtoms();
96     virtual bool isValid() const;
97 public:
98     GnomeWMAdaptor( SalDisplay * );
99     virtual ~GnomeWMAdaptor();
100 
101     virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const;
102     virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const;
103     virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const;
104     virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const;
105 };
106 
107 }
108 
109 using namespace vcl_sal;
110 
111 struct WMAdaptorProtocol
112 {
113     const char*	pProtocol;
114     int				nProtocol;
115 };
116 
117 
118 /*
119  *  table must be sorted ascending in strings
120  *  since it is use with bsearch
121  */
122 static const WMAdaptorProtocol aProtocolTab[] =
123 {
124     { "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", WMAdaptor::KDE_NET_WM_WINDOW_TYPE_OVERRIDE },
125     { "_NET_CURRENT_DESKTOP", WMAdaptor::NET_CURRENT_DESKTOP },
126     { "_NET_NUMBER_OF_DESKTOPS", WMAdaptor::NET_NUMBER_OF_DESKTOPS },
127     { "_NET_WM_DESKTOP", WMAdaptor::NET_WM_DESKTOP },
128     { "_NET_WM_FULLSCREEN_MONITORS", WMAdaptor::NET_WM_FULLSCREEN_MONITORS },
129     { "_NET_WM_ICON_NAME", WMAdaptor::NET_WM_ICON_NAME },
130     { "_NET_WM_PING", WMAdaptor::NET_WM_PING },
131     { "_NET_WM_STATE", WMAdaptor::NET_WM_STATE },
132     { "_NET_WM_STATE_ABOVE", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
133     { "_NET_WM_STATE_FULLSCREEN", WMAdaptor::NET_WM_STATE_FULLSCREEN },
134     { "_NET_WM_STATE_MAXIMIZED_HORIZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ }, // common bug in e.g. older kwin and sawfish implementations
135     { "_NET_WM_STATE_MAXIMIZED_HORZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ },
136     { "_NET_WM_STATE_MAXIMIZED_VERT", WMAdaptor::NET_WM_STATE_MAXIMIZED_VERT },
137     { "_NET_WM_STATE_MODAL", WMAdaptor::NET_WM_STATE_MODAL },
138     { "_NET_WM_STATE_SHADED", WMAdaptor::NET_WM_STATE_SHADED },
139     { "_NET_WM_STATE_SKIP_PAGER", WMAdaptor::NET_WM_STATE_SKIP_PAGER },
140     { "_NET_WM_STATE_SKIP_TASKBAR", WMAdaptor::NET_WM_STATE_SKIP_TASKBAR },
141     { "_NET_WM_STATE_STAYS_ON_TOP", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
142     { "_NET_WM_STATE_STICKY", WMAdaptor::NET_WM_STATE_STICKY },
143     { "_NET_WM_STRUT", WMAdaptor::NET_WM_STRUT },
144     { "_NET_WM_STRUT_PARTIAL", WMAdaptor::NET_WM_STRUT_PARTIAL },
145     { "_NET_WM_WINDOW_TYPE", WMAdaptor::NET_WM_WINDOW_TYPE },
146     { "_NET_WM_WINDOW_TYPE_DESKTOP", WMAdaptor::NET_WM_WINDOW_TYPE_DESKTOP },
147     { "_NET_WM_WINDOW_TYPE_DIALOG", WMAdaptor::NET_WM_WINDOW_TYPE_DIALOG },
148     { "_NET_WM_WINDOW_TYPE_DOCK", WMAdaptor::NET_WM_WINDOW_TYPE_DOCK },
149     { "_NET_WM_WINDOW_TYPE_MENU", WMAdaptor::NET_WM_WINDOW_TYPE_MENU },
150     { "_NET_WM_WINDOW_TYPE_NORMAL", WMAdaptor::NET_WM_WINDOW_TYPE_NORMAL },
151     { "_NET_WM_WINDOW_TYPE_SPLASH", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH },
152     { "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH }, // bug in Metacity 2.4.1
153     { "_NET_WM_WINDOW_TYPE_TOOLBAR", WMAdaptor::NET_WM_WINDOW_TYPE_TOOLBAR },
154     { "_NET_WM_WINDOW_TYPE_UTILITY", WMAdaptor::NET_WM_WINDOW_TYPE_UTILITY },
155     { "_NET_WORKAREA", WMAdaptor::NET_WORKAREA },
156     { "_WIN_APP_STATE", WMAdaptor::WIN_APP_STATE },
157     { "_WIN_CLIENT_LIST", WMAdaptor::WIN_CLIENT_LIST },
158     { "_WIN_EXPANDED_SIZE", WMAdaptor::WIN_EXPANDED_SIZE },
159     { "_WIN_HINTS", WMAdaptor::WIN_HINTS },
160     { "_WIN_ICONS", WMAdaptor::WIN_ICONS },
161     { "_WIN_LAYER", WMAdaptor::WIN_LAYER },
162     { "_WIN_STATE", WMAdaptor::WIN_STATE },
163     { "_WIN_WORKSPACE", WMAdaptor::WIN_WORKSPACE },
164     { "_WIN_WORKSPACE_COUNT", WMAdaptor::WIN_WORKSPACE_COUNT }
165 };
166 
167 /*
168  *  table containing atoms to get anyway
169  */
170 
171 static const WMAdaptorProtocol aAtomTab[] =
172 {
173     { "WM_STATE", WMAdaptor::WM_STATE },
174     { "_MOTIF_WM_HINTS", WMAdaptor::MOTIF_WM_HINTS },
175     { "WM_PROTOCOLS", WMAdaptor::WM_PROTOCOLS },
176     { "WM_DELETE_WINDOW", WMAdaptor::WM_DELETE_WINDOW },
177     { "WM_TAKE_FOCUS", WMAdaptor::WM_TAKE_FOCUS },
178     { "WM_SAVE_YOURSELF", WMAdaptor::WM_SAVE_YOURSELF },
179     { "WM_COMMAND", WMAdaptor::WM_COMMAND },
180     { "WM_CLIENT_LEADER", WMAdaptor::WM_CLIENT_LEADER },
181     { "WM_LOCALE_NAME", WMAdaptor::WM_LOCALE_NAME },
182     { "WM_TRANSIENT_FOR", WMAdaptor::WM_TRANSIENT_FOR },
183     { "SAL_QUITEVENT", WMAdaptor::SAL_QUITEVENT },
184     { "SAL_USEREVENT", WMAdaptor::SAL_USEREVENT },
185     { "SAL_EXTTEXTEVENT", WMAdaptor::SAL_EXTTEXTEVENT },
186     { "SAL_GETTIMEEVENT", WMAdaptor::SAL_GETTIMEEVENT },
187     { "VCL_SYSTEM_SETTINGS", WMAdaptor::VCL_SYSTEM_SETTINGS },
188     { "DTWM_IS_RUNNING", WMAdaptor::DTWM_IS_RUNNING },
189     { "_XSETTINGS_SETTINGS", WMAdaptor::XSETTINGS },
190     { "_XEMBED", WMAdaptor::XEMBED },
191     { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO },
192     { "_NET_WM_USER_TIME", WMAdaptor::NET_WM_USER_TIME },
193     { "_NET_WM_PID", WMAdaptor::NET_WM_PID }
194 };
195 
196 extern "C" {
197 static int compareProtocol( const void* pLeft, const void* pRight )
198 {
199     return strcmp( ((const WMAdaptorProtocol*)pLeft)->pProtocol, ((const WMAdaptorProtocol*)pRight)->pProtocol );
200 }
201 }
202 
203 WMAdaptor* WMAdaptor::createWMAdaptor( SalDisplay* pSalDisplay )
204 {
205     WMAdaptor*			pAdaptor	= NULL;
206 
207     // try a NetWM
208     pAdaptor = new NetWMAdaptor( pSalDisplay );
209     if( ! pAdaptor->isValid() )
210         delete pAdaptor, pAdaptor = NULL;
211 #if OSL_DEBUG_LEVEL > 1
212     else
213         fprintf( stderr, "WM supports extended WM hints\n" );
214 #endif
215 
216     // try a GnomeWM
217     if( ! pAdaptor )
218     {
219         pAdaptor = new GnomeWMAdaptor( pSalDisplay );
220         if( ! pAdaptor->isValid() )
221             delete pAdaptor, pAdaptor = NULL;
222 #if OSL_DEBUG_LEVEL > 1
223         else
224             fprintf( stderr, "WM supports GNOME WM hints\n" );
225 #endif
226     }
227 
228     if( ! pAdaptor )
229         pAdaptor = new WMAdaptor( pSalDisplay );
230 
231 #if OSL_DEBUG_LEVEL > 1
232     fprintf( stderr, "Window Manager's name is \"%s\"\n",
233              ByteString( pAdaptor->getWindowManagerName(), RTL_TEXTENCODING_ISO_8859_1 ).GetBuffer() );
234 #endif
235     return pAdaptor;
236 }
237 
238 
239 /*
240  *  WMAdaptor constructor
241  */
242 
243 WMAdaptor::WMAdaptor( SalDisplay* pDisplay ) :
244         m_pSalDisplay( pDisplay ),
245         m_bTransientBehaviour( true ),
246         m_bEnableAlwaysOnTopWorks( false ),
247         m_bLegacyPartialFullscreen( false ),
248         m_nWinGravity( StaticGravity ),
249         m_nInitWinGravity( StaticGravity ),
250         m_bWMshouldSwitchWorkspace( true ),
251         m_bWMshouldSwitchWorkspaceInit( false )
252 {
253     Atom				aRealType	= None;
254     int					nFormat		= 8;
255     unsigned long		nItems		= 0;
256     unsigned long		nBytesLeft	= 0;
257     unsigned char*	pProperty	= NULL;
258 
259     // default desktops
260     m_nDesktops = 1;
261     m_aWMWorkAreas = ::std::vector< Rectangle >
262         ( 1, Rectangle( Point(), m_pSalDisplay->GetScreenSize( m_pSalDisplay->GetDefaultScreenNumber() ) ) );
263     m_bEqualWorkAreas = true;
264 
265     memset( m_aWMAtoms, 0, sizeof( m_aWMAtoms ) );
266     m_pDisplay = m_pSalDisplay->GetDisplay();
267 
268     initAtoms();
269     getNetWmName(); // try to discover e.g. Sawfish
270 
271     // check for dtwm running
272     if( m_aWMAtoms[ DTWM_IS_RUNNING ] )
273     {
274         if (   (XGetWindowProperty( m_pDisplay,
275                                     m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
276                                     m_aWMAtoms[ DTWM_IS_RUNNING ],
277                                     0, 1,
278                                     False,
279                                     XA_INTEGER,
280                                     &aRealType,
281                                     &nFormat,
282                                     &nItems,
283                                     &nBytesLeft,
284                                     &pProperty) == 0
285                 && nItems)
286                || (XGetWindowProperty( m_pDisplay,
287                                        m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
288                                        m_aWMAtoms[ DTWM_IS_RUNNING ],
289                                        0, 1,
290                                        False,
291                                        m_aWMAtoms[ DTWM_IS_RUNNING ],
292                                        &aRealType,
293                                        &nFormat,
294                                        &nItems,
295                                        &nBytesLeft,
296                                        &pProperty) == 0
297                    && nItems))
298         {
299             if (*pProperty)
300             {
301                 m_aWMName = String(RTL_CONSTASCII_USTRINGPARAM("Dtwm"));
302                 m_bTransientBehaviour = false;
303                 m_nWinGravity = CenterGravity;
304             }
305             XFree (pProperty);
306         }
307         else if( pProperty )
308         {
309             XFree( pProperty );
310             pProperty = NULL;
311         }
312     }
313     if( m_aWMName.Len() == 0 )
314     {
315         // check for window maker - needs different gravity
316         Atom aWMakerRunning = XInternAtom( m_pDisplay, "_WINDOWMAKER_WM_PROTOCOLS", True );
317         if( aWMakerRunning != None &&
318 			XGetWindowProperty( m_pDisplay,
319 								m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
320 								aWMakerRunning,
321 								0, 32,
322 								False,
323 								XA_ATOM,
324 								&aRealType,
325 								&nFormat,
326 								&nItems,
327 								&nBytesLeft,
328 								&pProperty ) == 0 )
329 		{
330 			if( aRealType == XA_ATOM )
331 				m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("Windowmaker" ) );
332 			XFree( pProperty );
333             m_nInitWinGravity = NorthWestGravity;
334 		}
335         else if( pProperty )
336         {
337             XFree( pProperty );
338             pProperty = NULL;
339         }
340     }
341     if( m_aWMName.Len() == 0 )
342     {
343         if( XInternAtom( m_pDisplay, "_OL_WIN_ATTR", True ) )
344         {
345             m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM( "Olwm" ) );
346             m_nInitWinGravity = NorthWestGravity;
347         }
348     }
349     if( m_aWMName.Len() == 0 )
350 	{
351 		// check for ReflectionX wm (as it needs a workaround in Windows mode
352 		Atom aRwmRunning = XInternAtom( m_pDisplay, "RWM_RUNNING", True );
353 		if( aRwmRunning != None &&
354 			XGetWindowProperty( m_pDisplay,
355 								m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
356 								aRwmRunning,
357 								0, 32,
358 								False,
359 								aRwmRunning,
360 								&aRealType,
361 								&nFormat,
362 								&nItems,
363 								&nBytesLeft,
364 								&pProperty ) == 0 )
365 		{
366 			if( aRealType == aRwmRunning )
367 				m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("ReflectionX" ) );
368 			XFree( pProperty );
369 		}
370 		else if( (aRwmRunning = XInternAtom( m_pDisplay, "_WRQ_WM_RUNNING", True )) != None &&
371 			XGetWindowProperty( m_pDisplay,
372 								m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
373 								aRwmRunning,
374 								0, 32,
375 								False,
376 								XA_STRING,
377 								&aRealType,
378 								&nFormat,
379 								&nItems,
380 								&nBytesLeft,
381 								&pProperty ) == 0 )
382 		{
383 			if( aRealType == XA_STRING )
384 				m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM( "ReflectionX Windows" ) );
385 			XFree( pProperty );
386 		}
387 	}
388     if( m_aWMName.Len() == 0 )
389     {
390 		Atom aTTAPlatform = XInternAtom( m_pDisplay, "TTA_CLIENT_PLATFORM", True );
391 		if( aTTAPlatform != None &&
392 			XGetWindowProperty( m_pDisplay,
393 								m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
394 								aTTAPlatform,
395 								0, 32,
396 								False,
397 								XA_STRING,
398 								&aRealType,
399 								&nFormat,
400 								&nItems,
401 								&nBytesLeft,
402 								&pProperty ) == 0 )
403 		{
404 			if( aRealType == XA_STRING )
405             {
406 				m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("Tarantella" ) );
407                 // #i62319# pretend that AlwaysOnTop works since
408                 // the alwaysontop workaround in salframe.cxx results
409                 // in a raise/lower loop on a Windows tarantella client
410                 // FIXME: this property contains an identification string that
411                 // in theory should be good enough to recognize running on a
412                 // Windows client; however this string does not seem to be
413                 // documented as well as the property itself.
414                 m_bEnableAlwaysOnTopWorks = true;
415             }
416 			XFree( pProperty );
417 		}
418     }
419 }
420 
421 /*
422  *  WMAdaptor destructor
423  */
424 
425 WMAdaptor::~WMAdaptor()
426 {
427 }
428 
429 /*
430  *  NetWMAdaptor constructor
431  */
432 
433 NetWMAdaptor::NetWMAdaptor( SalDisplay* pSalDisplay ) :
434         WMAdaptor( pSalDisplay )
435 {
436     // currently all _NET WMs do transient like expected
437     m_bTransientBehaviour = true;
438 
439     Atom				aRealType	= None;
440     int					nFormat		= 8;
441     unsigned long		nItems		= 0;
442     unsigned long		nBytesLeft	= 0;
443     unsigned char*	pProperty	= NULL;
444     bool				bNetWM		= false;
445 
446     initAtoms();
447 
448     // check for NetWM
449     bNetWM = getNetWmName();
450     if( bNetWM
451         && XGetWindowProperty( m_pDisplay,
452                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
453                                m_aWMAtoms[ NET_SUPPORTED ],
454                                0, 0,
455                                False,
456                                XA_ATOM,
457                                &aRealType,
458                                &nFormat,
459                                &nItems,
460                                &nBytesLeft,
461                                &pProperty ) == 0
462         && aRealType == XA_ATOM
463         && nFormat == 32
464         )
465     {
466         if( pProperty )
467         {
468             XFree( pProperty );
469             pProperty = NULL;
470         }
471         // collect supported protocols
472         if( XGetWindowProperty( m_pDisplay,
473                                 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
474                                 m_aWMAtoms[ NET_SUPPORTED ],
475                                 0, nBytesLeft/4,
476                                 False,
477                                 XA_ATOM,
478                                 &aRealType,
479                                 &nFormat,
480                                 &nItems,
481                                 &nBytesLeft,
482                                 &pProperty ) == 0
483             && nItems
484             )
485         {
486             Atom* pAtoms = (Atom*)pProperty;
487             char** pAtomNames = (char**)alloca( sizeof(char*)*nItems );
488             if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
489             {
490 #if OSL_DEBUG_LEVEL > 1
491                 fprintf( stderr, "supported protocols:\n" );
492 #endif
493                 for( unsigned int i = 0; i < nItems; i++ )
494                 {
495                     // #i80971# protect against invalid atoms
496                     if( pAtomNames[i] == NULL )
497                         continue;
498 
499                     int nProtocol = -1;
500                     WMAdaptorProtocol aSearch;
501                     aSearch.pProtocol = pAtomNames[i];
502                     WMAdaptorProtocol* pMatch = (WMAdaptorProtocol*)
503                         bsearch( &aSearch,
504                                  aProtocolTab,
505                                  sizeof( aProtocolTab )/sizeof( aProtocolTab[0] ),
506                                  sizeof( struct WMAdaptorProtocol ),
507                                  compareProtocol );
508                     if( pMatch )
509                     {
510                         nProtocol = pMatch->nProtocol;
511                         m_aWMAtoms[ nProtocol ] = pAtoms[ i ];
512                         if( pMatch->nProtocol == NET_WM_STATE_STAYS_ON_TOP )
513                             m_bEnableAlwaysOnTopWorks = true;
514                     }
515 #if OSL_DEBUG_LEVEL > 1
516                     fprintf( stderr, "  %s%s\n", pAtomNames[i], nProtocol != -1 ? "" : " (unsupported)" );
517 #endif
518 
519                     XFree( pAtomNames[i] );
520                 }
521             }
522             XFree( pProperty );
523             pProperty = NULL;
524         }
525         else if( pProperty )
526         {
527             XFree( pProperty );
528             pProperty = NULL;
529         }
530 
531         // get number of desktops
532         if( m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ]
533             && XGetWindowProperty( m_pDisplay,
534                                    m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
535                                    m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ],
536                                    0, 1,
537                                    False,
538                                    XA_CARDINAL,
539                                    &aRealType,
540                                    &nFormat,
541                                    &nItems,
542                                    &nBytesLeft,
543                                    &pProperty ) == 0
544             && pProperty
545             )
546         {
547             m_nDesktops = *(long*)pProperty;
548             XFree( pProperty );
549             pProperty = NULL;
550             // get work areas
551             if( m_aWMAtoms[ NET_WORKAREA ]
552                 && XGetWindowProperty( m_pDisplay,
553                                        m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
554                                        m_aWMAtoms[ NET_WORKAREA ],
555                                        0, 4*m_nDesktops,
556                                        False,
557                                        XA_CARDINAL,
558                                        &aRealType,
559                                        &nFormat,
560                                        &nItems,
561                                        &nBytesLeft,
562                                        &pProperty
563                                        ) == 0
564                 && nItems == 4*(unsigned)m_nDesktops
565                 )
566             {
567                 m_aWMWorkAreas = ::std::vector< Rectangle > ( m_nDesktops );
568                 long* pValues = (long*)pProperty;
569                 for( int i = 0; i < m_nDesktops; i++ )
570                 {
571                     Point aPoint( pValues[4*i],
572                                   pValues[4*i+1] );
573 					Size aSize( pValues[4*i+2],
574                                 pValues[4*i+3] );
575                     Rectangle aWorkArea( aPoint, aSize );
576                     m_aWMWorkAreas[i] = aWorkArea;
577                     if( aWorkArea != m_aWMWorkAreas[0] )
578                         m_bEqualWorkAreas = false;
579 #if OSL_DEBUG_LEVEL > 1
580                     fprintf( stderr, "workarea %d: %ldx%ld+%ld+%ld\n",
581                              i,
582                              m_aWMWorkAreas[i].GetWidth(),
583                              m_aWMWorkAreas[i].GetHeight(),
584                              m_aWMWorkAreas[i].Left(),
585                              m_aWMWorkAreas[i].Top() );
586 #endif
587                 }
588                 XFree( pProperty );
589             }
590             else
591             {
592 #if OSL_DEBUG_LEVEL > 1
593                 fprintf( stderr, "%ld workareas for %d desktops !\n", nItems/4, m_nDesktops );
594 #endif
595                 if( pProperty )
596                 {
597                     XFree(pProperty);
598                     pProperty = NULL;
599                 }
600             }
601         }
602         else if( pProperty )
603         {
604             XFree( pProperty );
605             pProperty = NULL;
606         }
607     }
608     else if( pProperty )
609     {
610         XFree( pProperty );
611         pProperty = NULL;
612     }
613 }
614 
615 /*
616  *  NetWMAdaptor destructor
617  */
618 NetWMAdaptor::~NetWMAdaptor()
619 {
620 }
621 
622 /*
623  *  GnomeWMAdaptor constructor
624  */
625 
626 GnomeWMAdaptor::GnomeWMAdaptor( SalDisplay* pSalDisplay ) :
627         WMAdaptor( pSalDisplay ),
628         m_bValid( false )
629 {
630     // currently all Gnome WMs do transient like expected
631     m_bTransientBehaviour = true;
632 
633     Atom				aRealType	= None;
634     int					nFormat		= 8;
635     unsigned long		nItems		= 0;
636     unsigned long		nBytesLeft	= 0;
637     unsigned char*	pProperty	= NULL;
638 
639 	initAtoms();
640 
641     // check for GnomeWM
642     if( m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ WIN_PROTOCOLS ] )
643     {
644         XLIB_Window			aWMChild	= None;
645         if( XGetWindowProperty( m_pDisplay,
646                                 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
647                                 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
648                                 0, 1,
649                                 False,
650                                 XA_CARDINAL,
651                                 &aRealType,
652                                 &nFormat,
653                                 &nItems,
654                                 &nBytesLeft,
655                                 &pProperty ) == 0
656             && aRealType == XA_CARDINAL
657             && nFormat == 32
658             && nItems != 0
659             )
660         {
661             aWMChild = *(XLIB_Window*)pProperty;
662             XFree( pProperty );
663             pProperty = NULL;
664             XLIB_Window aCheckWindow = None;
665             m_pSalDisplay->GetXLib()->PushXErrorLevel( true );
666             if( XGetWindowProperty( m_pDisplay,
667                                     aWMChild,
668                                     m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
669                                     0, 1,
670                                     False,
671                                     XA_CARDINAL,
672                                     &aRealType,
673                                     &nFormat,
674                                     &nItems,
675                                     &nBytesLeft,
676                                     &pProperty ) == 0
677                 && aRealType == XA_CARDINAL
678                 && nFormat == 32
679                 && nItems != 0
680                 && ! m_pSalDisplay->GetXLib()->HasXErrorOccured()
681                 )
682             {
683                 aCheckWindow =  *(XLIB_Window*)pProperty;
684                 XFree( pProperty );
685                 pProperty = NULL;
686                 if( aCheckWindow == aWMChild )
687                 {
688                     m_bValid = true;
689                     /*
690                      *  get name of WM
691                      *  this is NOT part of the GNOME WM hints, but e.g. Sawfish
692                      *  already supports this part of the extended WM hints
693                      */
694                     m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
695                     getNetWmName();
696                 }
697             }
698             m_pSalDisplay->GetXLib()->PopXErrorLevel();
699         }
700         else if( pProperty )
701         {
702             XFree( pProperty );
703             pProperty = NULL;
704         }
705     }
706     if( m_bValid
707         && XGetWindowProperty( m_pDisplay,
708                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
709                                m_aWMAtoms[ WIN_PROTOCOLS ],
710                                0, 0,
711                                False,
712                                XA_ATOM,
713                                &aRealType,
714                                &nFormat,
715                                &nItems,
716                                &nBytesLeft,
717                                &pProperty ) == 0
718         && aRealType == XA_ATOM
719         && nFormat == 32
720         )
721     {
722         if( pProperty )
723         {
724             XFree( pProperty );
725             pProperty = NULL;
726         }
727         // collect supported protocols
728         if( XGetWindowProperty( m_pDisplay,
729                                 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
730                                 m_aWMAtoms[ WIN_PROTOCOLS ],
731                                 0, nBytesLeft/4,
732                                 False,
733                                 XA_ATOM,
734                                 &aRealType,
735                                 &nFormat,
736                                 &nItems,
737                                 &nBytesLeft,
738                                 &pProperty ) == 0
739             && pProperty
740             )
741         {
742             Atom* pAtoms = (Atom*)pProperty;
743             char** pAtomNames = (char**)alloca( sizeof(char*)*nItems );
744             if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
745             {
746 #if OSL_DEBUG_LEVEL > 1
747                 fprintf( stderr, "supported protocols:\n" );
748 #endif
749                 for( unsigned int i = 0; i < nItems; i++ )
750                 {
751                     // #i80971# protect against invalid atoms
752                     if( pAtomNames[i] == NULL )
753                         continue;
754 
755                     int nProtocol = -1;
756                     WMAdaptorProtocol aSearch;
757                     aSearch.pProtocol = pAtomNames[i];
758                     WMAdaptorProtocol* pMatch = (WMAdaptorProtocol*)
759                         bsearch( &aSearch,
760                                  aProtocolTab,
761                                  sizeof( aProtocolTab )/sizeof( aProtocolTab[0] ),
762                                  sizeof( struct WMAdaptorProtocol ),
763                                  compareProtocol );
764                     if( pMatch )
765                     {
766                         nProtocol = pMatch->nProtocol;
767                         m_aWMAtoms[ nProtocol ] = pAtoms[ i ];
768                         if( pMatch->nProtocol == WIN_LAYER )
769                             m_bEnableAlwaysOnTopWorks = true;
770                     }
771                     if( strncmp( "_ICEWM_TRAY", pAtomNames[i], 11 ) == 0 )
772                     {
773                         m_aWMName = String(RTL_CONSTASCII_USTRINGPARAM("IceWM" ));
774                         m_nWinGravity = NorthWestGravity;
775                         m_nInitWinGravity = NorthWestGravity;
776                     }
777 #if OSL_DEBUG_LEVEL > 1
778                     fprintf( stderr, "  %s%s\n", pAtomNames[i], nProtocol != -1 ? "" : " (unsupported)" );
779 #endif
780 
781                     XFree( pAtomNames[i] );
782                 }
783             }
784             XFree( pProperty );
785             pProperty = NULL;
786         }
787         else if( pProperty )
788         {
789             XFree( pProperty );
790             pProperty = NULL;
791         }
792 
793         // get number of desktops
794         if( m_aWMAtoms[ WIN_WORKSPACE_COUNT ]
795             && XGetWindowProperty( m_pDisplay,
796                                    m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
797                                    m_aWMAtoms[ WIN_WORKSPACE_COUNT ],
798                                    0, 1,
799                                    False,
800                                    XA_CARDINAL,
801                                    &aRealType,
802                                    &nFormat,
803                                    &nItems,
804                                    &nBytesLeft,
805                                    &pProperty ) == 0
806             && pProperty
807             )
808         {
809             m_nDesktops = *(long*)pProperty;
810             XFree( pProperty );
811             pProperty = NULL;
812         }
813         else if( pProperty )
814         {
815             XFree( pProperty );
816             pProperty = NULL;
817         }
818     }
819     else if( pProperty )
820     {
821         XFree( pProperty );
822         pProperty = NULL;
823     }
824 }
825 
826 /*
827  *  GnomeWMAdaptor destructor
828  */
829 GnomeWMAdaptor::~GnomeWMAdaptor()
830 {
831 }
832 
833 /*
834  *  getNetWmName()
835  */
836 bool WMAdaptor::getNetWmName()
837 {
838     Atom				aRealType	= None;
839     int					nFormat		= 8;
840     unsigned long		nItems		= 0;
841     unsigned long		nBytesLeft	= 0;
842     unsigned char*	pProperty	= NULL;
843     bool				bNetWM		= false;
844 
845     if( m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ NET_WM_NAME ] )
846     {
847         XLIB_Window			aWMChild = None;
848         if( XGetWindowProperty( m_pDisplay,
849                                 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
850                                 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
851                                 0, 1,
852                                 False,
853                                 XA_WINDOW,
854                                 &aRealType,
855                                 &nFormat,
856                                 &nItems,
857                                 &nBytesLeft,
858                                 &pProperty ) == 0
859             && aRealType == XA_WINDOW
860             && nFormat == 32
861             && nItems != 0
862             )
863         {
864             aWMChild = *(XLIB_Window*)pProperty;
865             XFree( pProperty );
866             pProperty = NULL;
867             XLIB_Window aCheckWindow = None;
868             m_pSalDisplay->GetXLib()->PushXErrorLevel( true );
869             if( XGetWindowProperty( m_pDisplay,
870                                     aWMChild,
871                                     m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
872                                     0, 1,
873                                     False,
874                                     XA_WINDOW,
875                                     &aRealType,
876                                     &nFormat,
877                                     &nItems,
878                                     &nBytesLeft,
879                                     &pProperty ) == 0
880                 && aRealType == XA_WINDOW
881                 && nFormat == 32
882                 && nItems != 0
883                 && ! m_pSalDisplay->GetXLib()->HasXErrorOccured()
884                 )
885             {
886                 aCheckWindow =  *(XLIB_Window*)pProperty;
887                 XFree( pProperty );
888                 pProperty = NULL;
889                 if( aCheckWindow == aWMChild )
890                 {
891                     bNetWM = true;
892                     // get name of WM
893                     m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
894                     if( XGetWindowProperty( m_pDisplay,
895                                             aWMChild,
896                                             m_aWMAtoms[ NET_WM_NAME ],
897                                             0, 256,
898                                             False,
899                                             AnyPropertyType, /* m_aWMAtoms[ UTF8_STRING ],*/
900                                             &aRealType,
901                                             &nFormat,
902                                             &nItems,
903                                             &nBytesLeft,
904                                             &pProperty ) == 0
905                         && nItems != 0
906                         )
907                     {
908                         if (aRealType == m_aWMAtoms[ UTF8_STRING ])
909                         {
910                             m_aWMName = String( (sal_Char*)pProperty, nItems, RTL_TEXTENCODING_UTF8 );
911                         }
912                         else
913                         if (aRealType == XA_STRING)
914                         {
915                             m_aWMName = String( (sal_Char*)pProperty, nItems, RTL_TEXTENCODING_ISO_8859_1 );
916                         }
917 
918                         XFree( pProperty );
919                         pProperty = NULL;
920                     }
921                     else if( pProperty )
922                     {
923                         XFree( pProperty );
924                         pProperty = NULL;
925                     }
926                     // if this is metacity, check for version to enable a legacy workaround
927                     if( m_aWMName.EqualsAscii( "Metacity" ) )
928                     {
929                         int nVersionMajor = 0, nVersionMinor = 0;
930                         Atom nVersionAtom = XInternAtom( m_pDisplay, "_METACITY_VERSION", True );
931                         if( nVersionAtom )
932                         {
933                             if( XGetWindowProperty( m_pDisplay,
934                                                     aWMChild,
935                                                     nVersionAtom,
936                                                     0, 256,
937                                                     False,
938                                                     m_aWMAtoms[ UTF8_STRING ],
939                                                     &aRealType,
940                                                     &nFormat,
941                                                     &nItems,
942                                                     &nBytesLeft,
943                                                     &pProperty ) == 0
944                                 && nItems != 0
945                                 )
946                             {
947                                 String aMetaVersion( (sal_Char*)pProperty, nItems, RTL_TEXTENCODING_UTF8 );
948                                 nVersionMajor = aMetaVersion.GetToken( 0, '.' ).ToInt32();
949                                 nVersionMinor = aMetaVersion.GetToken( 1, '.' ).ToInt32();
950                             }
951                             if( pProperty )
952                             {
953                                 XFree( pProperty );
954                                 pProperty = NULL;
955                             }
956                         }
957                         if( nVersionMajor < 2 || (nVersionMajor == 2 && nVersionMinor < 12) )
958                             m_bLegacyPartialFullscreen = true;
959                     }
960                 }
961             }
962             else if( pProperty )
963             {
964                 XFree( pProperty );
965                 pProperty = NULL;
966             }
967             m_pSalDisplay->GetXLib()->PopXErrorLevel();
968         }
969         else if( pProperty )
970         {
971             XFree( pProperty );
972             pProperty = NULL;
973         }
974     }
975     return bNetWM;
976 }
977 
978 bool WMAdaptor::getWMshouldSwitchWorkspace() const
979 {
980     if( ! m_bWMshouldSwitchWorkspaceInit )
981     {
982         WMAdaptor * pWMA = const_cast<WMAdaptor*>(this);
983 
984         pWMA->m_bWMshouldSwitchWorkspace = true;
985         vcl::SettingsConfigItem* pItem = vcl::SettingsConfigItem::get();
986         rtl::OUString aSetting( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WM" ) ),
987                                                  rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ShouldSwitchWorkspace" ) ) ) );
988         if( aSetting.getLength() == 0 )
989         {
990             if( m_aWMName.EqualsAscii( "awesome" ) )
991             {
992                 pWMA->m_bWMshouldSwitchWorkspace = false;
993             }
994         }
995         else
996             pWMA->m_bWMshouldSwitchWorkspace = aSetting.toBoolean();
997         pWMA->m_bWMshouldSwitchWorkspaceInit = true;
998     }
999     return m_bWMshouldSwitchWorkspace;
1000 }
1001 
1002 /*
1003  *  WMAdaptor::isValid()
1004  */
1005 bool WMAdaptor::isValid() const
1006 {
1007     return true;
1008 }
1009 
1010 /*
1011  *  NetWMAdaptor::isValid()
1012  */
1013 bool NetWMAdaptor::isValid() const
1014 {
1015     // some necessary sanity checks; there are WMs out there
1016     // which implement some of the WM hints spec without
1017     // real functionality
1018     return
1019         m_aWMAtoms[ NET_SUPPORTED ]
1020         && m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]
1021         && m_aWMAtoms[ NET_WM_NAME ]
1022         && m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ]
1023         && m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ]
1024         ;
1025 }
1026 
1027 /*
1028  *  GnomeWMAdaptor::isValid()
1029  */
1030 bool GnomeWMAdaptor::isValid() const
1031 {
1032     return m_bValid;
1033 }
1034 
1035 /*
1036  *  WMAdaptor::initAtoms
1037  */
1038 
1039 void WMAdaptor::initAtoms()
1040 {
1041     // get basic atoms
1042     for( unsigned int i = 0; i < sizeof( aAtomTab )/sizeof( aAtomTab[0] ); i++ )
1043         m_aWMAtoms[ aAtomTab[i].nProtocol ] = XInternAtom( m_pDisplay, aAtomTab[i].pProtocol, False );
1044     m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]	= XInternAtom( m_pDisplay, "_NET_SUPPORTING_WM_CHECK", True );
1045     m_aWMAtoms[ NET_WM_NAME ]				= XInternAtom( m_pDisplay, "_NET_WM_NAME", True );
1046 }
1047 
1048 /*
1049  *  NetWMAdaptor::initAtoms
1050  */
1051 
1052 void NetWMAdaptor::initAtoms()
1053 {
1054     WMAdaptor::initAtoms();
1055 
1056     m_aWMAtoms[ NET_SUPPORTED ]				= XInternAtom( m_pDisplay, "_NET_SUPPORTED", True );
1057 }
1058 
1059 /*
1060  *  GnomeWMAdaptor::initAtoms
1061  */
1062 
1063 void GnomeWMAdaptor::initAtoms()
1064 {
1065     WMAdaptor::initAtoms();
1066 
1067     m_aWMAtoms[ WIN_PROTOCOLS ]				= XInternAtom( m_pDisplay, "_WIN_PROTOCOLS", True );
1068     m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ]	= XInternAtom( m_pDisplay, "_WIN_SUPPORTING_WM_CHECK", True );
1069 }
1070 
1071 /*
1072  *  WMAdaptor::setWMName
1073  *  sets WM_NAME
1074  *       WM_ICON_NAME
1075  */
1076 
1077 void WMAdaptor::setWMName( X11SalFrame* pFrame, const String& rWMName ) const
1078 {
1079 	ByteString aTitle( rWMName, osl_getThreadTextEncoding() );
1080 
1081     if( ! rWMName.Len() && m_aWMName.EqualsAscii( "Dtwm" ) )
1082         aTitle = " ";
1083 
1084     ::rtl::OString aWMLocale;
1085     rtl_Locale* pLocale = NULL;
1086     osl_getProcessLocale( &pLocale );
1087     if( pLocale )
1088     {
1089         ::rtl::OUString aLocaleString( pLocale->Language );
1090         ::rtl::OUString aCountry( pLocale->Country );
1091         ::rtl::OUString aVariant( pLocale->Variant );
1092 
1093         if( aCountry.getLength() )
1094         {
1095             aLocaleString += ::rtl::OUString::createFromAscii( "_" );
1096             aLocaleString += aCountry;
1097         }
1098         if( aVariant.getLength() )
1099             aLocaleString += aVariant;
1100         aWMLocale = ::rtl::OUStringToOString( aLocaleString, RTL_TEXTENCODING_ISO_8859_1 );
1101     }
1102     else
1103     {
1104         static const char* pLang = getenv( "LANG" );
1105         aWMLocale = pLang ? pLang : "C";
1106     }
1107 
1108     static bool bTrustXmb = true;
1109     #ifdef SOLARIS
1110     /* #i64273# there are some weird cases when using IIIMP on Solaris
1111     *  where for unknown reasons XmbTextListToTextProperty results in
1112     *  garbage. Test one string once to ensure safety.
1113     *
1114     *  FIXME: This must be a bug in xiiimp.so.2 somewhere. However
1115     *  it was not possible to recreate this in a small sample program.
1116     *  This reeks of memory corruption somehow.
1117     */
1118     static bool bOnce = true;
1119     if( bOnce )
1120     {
1121         bOnce = false;
1122         XTextProperty aTestProp = { NULL, None, 0, 0 };
1123         const char *pText = "trustme";
1124         XmbTextListToTextProperty( m_pDisplay,
1125                                    &const_cast<char*>(pText),
1126                                    1,
1127                                    XStdICCTextStyle,
1128                                    &aTestProp );
1129         bTrustXmb = (aTestProp.nitems == 7)                     &&
1130                     (aTestProp.value != NULL )                  &&
1131                     (strncmp( (char*)aTestProp.value, pText, 7 ) == 0) &&
1132                     (aTestProp.encoding == XA_STRING);
1133         if( aTestProp.value )
1134             XFree( aTestProp.value );
1135         #if OSL_DEBUG_LEVEL > 1
1136         fprintf( stderr, "%s\n",
1137                  bTrustXmb ?
1138                  "XmbTextListToTextProperty seems to work" :
1139                  "XmbTextListToTextProperty does not seem to work" );
1140         #endif
1141     }
1142     #endif
1143 
1144     char* pT = const_cast<char*>(aTitle.GetBuffer());
1145     XTextProperty aProp = { NULL, None, 0, 0 };
1146     if( bTrustXmb )
1147     {
1148         XmbTextListToTextProperty( m_pDisplay,
1149                                    &pT,
1150                                    1,
1151                                    XStdICCTextStyle,
1152                                    &aProp );
1153     }
1154 
1155     unsigned char* pData	= aProp.nitems ? aProp.value : (unsigned char*)aTitle.GetBuffer();
1156     Atom nType				= aProp.nitems ? aProp.encoding : XA_STRING;
1157     int nFormat				= aProp.nitems ? aProp.format : 8;
1158     int nBytes				= aProp.nitems ? aProp.nitems : aTitle.Len();
1159     const SystemEnvData* pEnv = pFrame->GetSystemData();
1160     XChangeProperty( m_pDisplay,
1161                      (XLIB_Window)pEnv->aShellWindow,
1162                      XA_WM_NAME,
1163                      nType,
1164                      nFormat,
1165                      PropModeReplace,
1166                      pData,
1167                      nBytes );
1168     XChangeProperty( m_pDisplay,
1169                      (XLIB_Window)pEnv->aShellWindow,
1170                      XA_WM_ICON_NAME,
1171                      nType,
1172                      nFormat,
1173                      PropModeReplace,
1174                      pData,
1175                      nBytes );
1176     XChangeProperty( m_pDisplay,
1177                      (XLIB_Window)pEnv->aShellWindow,
1178                      m_aWMAtoms[ WM_LOCALE_NAME ],
1179                      XA_STRING,
1180                      8,
1181                      PropModeReplace,
1182                      (unsigned char*)aWMLocale.getStr(),
1183                      aWMLocale.getLength() );
1184     if (aProp.value != NULL)
1185         XFree( aProp.value );
1186 }
1187 
1188 /*
1189  *  NetWMAdaptor::setWMName
1190  *  sets WM_NAME
1191  *       _NET_WM_NAME
1192  *       WM_ICON_NAME
1193  *       _NET_WM_ICON_NAME
1194  */
1195 void NetWMAdaptor::setWMName( X11SalFrame* pFrame, const String& rWMName ) const
1196 {
1197     WMAdaptor::setWMName( pFrame, rWMName );
1198 
1199     ByteString aTitle( rWMName, RTL_TEXTENCODING_UTF8 );
1200     const SystemEnvData* pEnv = pFrame->GetSystemData();
1201     if( m_aWMAtoms[ NET_WM_NAME ] )
1202         XChangeProperty( m_pDisplay,
1203                          (XLIB_Window)pEnv->aShellWindow,
1204                          m_aWMAtoms[ NET_WM_NAME ],
1205                          m_aWMAtoms[ UTF8_STRING ],
1206                          8,
1207                          PropModeReplace,
1208                          (unsigned char*)aTitle.GetBuffer(),
1209                          aTitle.Len()+1 );
1210     if( m_aWMAtoms[ NET_WM_ICON_NAME ] )
1211         XChangeProperty( m_pDisplay,
1212                          (XLIB_Window)pEnv->aShellWindow,
1213                          m_aWMAtoms[ NET_WM_ICON_NAME ],
1214                          m_aWMAtoms[ UTF8_STRING ],
1215                          8,
1216                          PropModeReplace,
1217                          (unsigned char*)aTitle.GetBuffer(),
1218                          aTitle.Len()+1 );
1219     // The +1 copies the terminating null byte. Although
1220     // the spec says, this should not be necessary
1221     // at least the kwin implementation seems to depend
1222     // on the null byte
1223 }
1224 
1225 /*
1226  *  NetWMAdaptor::setNetWMState
1227  *  sets _NET_WM_STATE
1228  */
1229 void NetWMAdaptor::setNetWMState( X11SalFrame* pFrame ) const
1230 {
1231     if( m_aWMAtoms[ NET_WM_STATE ] )
1232     {
1233         Atom aStateAtoms[ 10 ];
1234         int nStateAtoms = 0;
1235 
1236         // set NET_WM_STATE_MODAL
1237         if( m_aWMAtoms[ NET_WM_STATE_MODAL ]
1238             && pFrame->meWindowType == windowType_ModalDialogue )
1239         {
1240             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MODAL ];
1241             /*
1242              *  #90998# NET_WM_STATE_SKIP_TASKBAR set on a frame will
1243              *  cause kwin not to give it the focus on map request
1244              *  this seems to be a bug in kwin
1245              *  aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];
1246              */
1247         }
1248         if( pFrame->mbMaximizedVert
1249             && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
1250             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1251         if( pFrame->mbMaximizedHorz
1252             && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
1253             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1254         if( pFrame->bAlwaysOnTop_ && m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
1255             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1256         if( pFrame->mbShaded && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
1257             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SHADED ];
1258         if( pFrame->mbFullScreen && m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
1259             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
1260         if( pFrame->meWindowType == windowType_Utility && m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ] )
1261             aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];
1262 
1263         if( nStateAtoms )
1264         {
1265             XChangeProperty( m_pDisplay,
1266                              pFrame->GetShellWindow(),
1267                              m_aWMAtoms[ NET_WM_STATE ],
1268                              XA_ATOM,
1269                              32,
1270                              PropModeReplace,
1271                              (unsigned char*)aStateAtoms,
1272                              nStateAtoms
1273                              );
1274         }
1275         else
1276             XDeleteProperty( m_pDisplay,
1277                              pFrame->GetShellWindow(),
1278                              m_aWMAtoms[ NET_WM_STATE ] );
1279         if( pFrame->mbMaximizedHorz
1280            && pFrame->mbMaximizedVert
1281            && ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
1282         {
1283             /*
1284              *  for maximizing use NorthWestGravity (including decoration)
1285              */
1286             XSizeHints	hints;
1287             long		supplied;
1288             bool bHint = false;
1289             if( XGetWMNormalHints( m_pDisplay,
1290                                    pFrame->GetShellWindow(),
1291                                    &hints,
1292                                    &supplied ) )
1293             {
1294                 bHint = true;
1295                 hints.flags |= PWinGravity;
1296                 hints.win_gravity = NorthWestGravity;
1297                 XSetWMNormalHints( m_pDisplay,
1298                                    pFrame->GetShellWindow(),
1299                                    &hints );
1300                 XSync( m_pDisplay, False );
1301             }
1302 
1303             // SetPosSize necessary to set width/height, min/max w/h
1304             sal_Int32 nCurrent = 0;
1305             /*
1306              *  get current desktop here if work areas have different size
1307              *  (does this happen on any platform ?)
1308              */
1309             if( ! m_bEqualWorkAreas )
1310             {
1311                 nCurrent = getCurrentWorkArea();
1312                 if( nCurrent < 0 )
1313                     nCurrent = 0;
1314             }
1315             Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1316             const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1317             aPosSize = Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1318                                          aPosSize.Top()  + rGeom.nTopDecoration ),
1319                                   Size( aPosSize.GetWidth()
1320                                         - rGeom.nLeftDecoration
1321                                         - rGeom.nRightDecoration,
1322                                         aPosSize.GetHeight()
1323                                         - rGeom.nTopDecoration
1324                                         - rGeom.nBottomDecoration )
1325                                   );
1326             pFrame->SetPosSize( aPosSize );
1327 
1328             /*
1329              *  reset gravity hint to static gravity
1330              *  (this should not move window according to ICCCM)
1331              */
1332             if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1333             {
1334                 hints.win_gravity = StaticGravity;
1335                 XSetWMNormalHints( m_pDisplay,
1336                                    pFrame->GetShellWindow(),
1337                                    &hints );
1338             }
1339         }
1340     }
1341 }
1342 
1343 /*
1344  *  GnomeWMAdaptor::setNetWMState
1345  *  sets _WIN_STATE
1346  */
1347 void GnomeWMAdaptor::setGnomeWMState( X11SalFrame* pFrame ) const
1348 {
1349     if( m_aWMAtoms[ WIN_STATE ] )
1350     {
1351         sal_uInt32 nWinWMState = 0;
1352 
1353         if( pFrame->mbMaximizedVert )
1354             nWinWMState |= 1 << 2;
1355         if( pFrame->mbMaximizedHorz )
1356             nWinWMState |= 1 << 3;
1357         if( pFrame->mbShaded )
1358             nWinWMState |= 1 << 5;
1359 
1360         XChangeProperty( m_pDisplay,
1361                          pFrame->GetShellWindow(),
1362                          m_aWMAtoms[ WIN_STATE ],
1363                          XA_CARDINAL,
1364                          32,
1365                          PropModeReplace,
1366                          (unsigned char*)&nWinWMState,
1367                          1
1368                          );
1369         if( pFrame->mbMaximizedHorz
1370            && pFrame->mbMaximizedVert
1371            && ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
1372         {
1373             /*
1374              *  for maximizing use NorthWestGravity (including decoration)
1375              */
1376             XSizeHints	hints;
1377             long		supplied;
1378             bool bHint = false;
1379             if( XGetWMNormalHints( m_pDisplay,
1380                                    pFrame->GetShellWindow(),
1381                                    &hints,
1382                                    &supplied ) )
1383             {
1384                 bHint = true;
1385                 hints.flags |= PWinGravity;
1386                 hints.win_gravity = NorthWestGravity;
1387                 XSetWMNormalHints( m_pDisplay,
1388                                    pFrame->GetShellWindow(),
1389                                    &hints );
1390                 XSync( m_pDisplay, False );
1391             }
1392 
1393             // SetPosSize necessary to set width/height, min/max w/h
1394             sal_Int32 nCurrent = 0;
1395             /*
1396              *  get current desktop here if work areas have different size
1397              *  (does this happen on any platform ?)
1398              */
1399             if( ! m_bEqualWorkAreas )
1400             {
1401                 nCurrent = getCurrentWorkArea();
1402                 if( nCurrent < 0 )
1403                     nCurrent = 0;
1404             }
1405             Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1406             const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1407             aPosSize = Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1408                                          aPosSize.Top()  + rGeom.nTopDecoration ),
1409                                   Size( aPosSize.GetWidth()
1410                                         - rGeom.nLeftDecoration
1411                                         - rGeom.nRightDecoration,
1412                                         aPosSize.GetHeight()
1413                                         - rGeom.nTopDecoration
1414                                         - rGeom.nBottomDecoration )
1415                                   );
1416             pFrame->SetPosSize( aPosSize );
1417 
1418             /*
1419              *  reset gravity hint to static gravity
1420              *  (this should not move window according to ICCCM)
1421              */
1422             if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1423             {
1424                 hints.win_gravity = StaticGravity;
1425                 XSetWMNormalHints( m_pDisplay,
1426                                    pFrame->GetShellWindow(),
1427                                    &hints );
1428             }
1429         }
1430     }
1431 }
1432 
1433 /*
1434  *  WMAdaptor::setFrameDecoration
1435  *  sets _MOTIF_WM_HINTS
1436  *		 WM_TRANSIENT_FOR
1437  */
1438 
1439 void WMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1440 {
1441     pFrame->meWindowType		= eType;
1442     pFrame->mnDecorationFlags	= nDecorationFlags;
1443 
1444     if( ! pFrame->mbFullScreen )
1445     {
1446         // set mwm hints
1447         struct _mwmhints {
1448             unsigned long flags, func, deco;
1449             long input_mode;
1450             unsigned long status;
1451         } aHint;
1452 
1453         aHint.flags = 15; /* flags for functions, decoration, input mode and status */
1454         aHint.deco = 0;
1455         aHint.func = 1L << 2;
1456         aHint.status = 0;
1457         aHint.input_mode = 0;
1458 
1459         // evaluate decoration flags
1460         if( nDecorationFlags & decoration_All )
1461             aHint.deco = 1, aHint.func = 1;
1462         else
1463         {
1464             if( nDecorationFlags & decoration_Title )
1465                 aHint.deco |= 1L << 3;
1466             if( nDecorationFlags & decoration_Border )
1467                 aHint.deco |= 1L << 1;
1468             if( nDecorationFlags & decoration_Resize )
1469                 aHint.deco |= 1L << 2, aHint.func |= 1L << 1;
1470             if( nDecorationFlags & decoration_MinimizeBtn )
1471                 aHint.deco |= 1L << 5, aHint.func |= 1L << 3;
1472             if( nDecorationFlags & decoration_MaximizeBtn )
1473                 aHint.deco |= 1L << 6, aHint.func |= 1L << 4;
1474             if( nDecorationFlags & decoration_CloseBtn )
1475                 aHint.deco |= 1L << 4, aHint.func |= 1L << 5;
1476         }
1477         // evaluate window type
1478         switch( eType )
1479         {
1480             case windowType_ModalDialogue:
1481                 aHint.input_mode = 1;
1482                 break;
1483             default:
1484                 break;
1485         }
1486 
1487         // set the hint
1488         XChangeProperty( m_pDisplay,
1489                          pFrame->GetShellWindow(),
1490                          m_aWMAtoms[ MOTIF_WM_HINTS ],
1491                          m_aWMAtoms[ MOTIF_WM_HINTS ],
1492                          32,
1493                          PropModeReplace,
1494                          (unsigned char*)&aHint,
1495                          5 );
1496     }
1497 
1498     // set transientFor hint
1499     /*  #91030# dtwm will not map a dialogue if the transient
1500      *  window is iconified. This is deemed undesireable because
1501      *  message boxes do not get mapped, so use the root as transient
1502      *  instead.
1503      */
1504     if( pReferenceFrame )
1505     {
1506         XSetTransientForHint( m_pDisplay,
1507                               pFrame->GetShellWindow(),
1508                               pReferenceFrame->bMapped_ ?
1509                               pReferenceFrame->GetShellWindow() :
1510                               m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() )
1511                               );
1512         if( ! pReferenceFrame->bMapped_ )
1513             pFrame->mbTransientForRoot = true;
1514     }
1515     // #110333# in case no one ever sets a title prevent
1516     // the Dtwm taking the class instead
1517     if( m_aWMName.EqualsAscii( "Dtwm" ) )
1518         setWMName( pFrame, String() );
1519 }
1520 
1521 /*
1522  *  NetWMAdaptor::setFrameDecoration
1523  *  sets _MOTIF_WM_HINTS
1524  *       _NET_WM_WINDOW_TYPE
1525  *       _NET_WM_STATE
1526  *		 WM_TRANSIENT_FOR
1527  */
1528 
1529 void NetWMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1530 {
1531     WMAdaptor::setFrameTypeAndDecoration( pFrame, eType, nDecorationFlags, pReferenceFrame );
1532 
1533     setNetWMState( pFrame );
1534 
1535     // set NET_WM_WINDOW_TYPE
1536     if( m_aWMAtoms[ NET_WM_WINDOW_TYPE ] )
1537     {
1538         Atom aWindowTypes[4];
1539         int nWindowTypes = 0;
1540         switch( eType )
1541         {
1542             case windowType_Utility:
1543                 aWindowTypes[nWindowTypes++] =
1544                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] ?
1545                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] :
1546                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1547                 break;
1548             case windowType_ModelessDialogue:
1549             case windowType_ModalDialogue:
1550                 aWindowTypes[nWindowTypes++] =
1551                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1552                 break;
1553             case windowType_Splash:
1554                 aWindowTypes[nWindowTypes++] =
1555                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] ?
1556                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] :
1557                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1558                 break;
1559             case windowType_Toolbar:
1560                 if( m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ] )
1561                     aWindowTypes[nWindowTypes++] = m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ];
1562                 aWindowTypes[nWindowTypes++] =
1563                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] ?
1564                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] :
1565                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1566                 break;
1567             case windowType_Dock:
1568                 aWindowTypes[nWindowTypes++] =
1569                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] ?
1570                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] :
1571                     m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1572                 break;
1573             default:
1574                 aWindowTypes[nWindowTypes++] = m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1575                 break;
1576         }
1577         XChangeProperty( m_pDisplay,
1578                          pFrame->GetShellWindow(),
1579                          m_aWMAtoms[ NET_WM_WINDOW_TYPE ],
1580                          XA_ATOM,
1581                          32,
1582                          PropModeReplace,
1583                          (unsigned char*)aWindowTypes,
1584                          nWindowTypes );
1585     }
1586     if( ( eType == windowType_ModalDialogue ||
1587           eType == windowType_ModelessDialogue )
1588         && ! pReferenceFrame )
1589     {
1590         XSetTransientForHint( m_pDisplay,
1591                               pFrame->GetShellWindow(),
1592                               m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ) );
1593         pFrame->mbTransientForRoot = true;
1594     }
1595 }
1596 
1597 /*
1598  *  WMAdaptor::maximizeFrame
1599  */
1600 
1601 void WMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1602 {
1603     pFrame->mbMaximizedVert = bVertical;
1604     pFrame->mbMaximizedHorz = bHorizontal;
1605 
1606     const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1607 
1608     // discard pending configure notifies for this frame
1609     XSync( m_pDisplay, False );
1610     XEvent aDiscard;
1611     while( XCheckTypedWindowEvent( m_pDisplay,
1612                                    pFrame->GetShellWindow(),
1613                                    ConfigureNotify,
1614                                    &aDiscard ) )
1615         ;
1616     while( XCheckTypedWindowEvent( m_pDisplay,
1617                                    pFrame->GetWindow(),
1618                                    ConfigureNotify,
1619                                    &aDiscard ) )
1620         ;
1621 
1622     if( bHorizontal || bVertical )
1623     {
1624         Size aScreenSize( m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() ) );
1625         Point aTL( rGeom.nLeftDecoration, rGeom.nTopDecoration );
1626         if( m_pSalDisplay->IsXinerama() )
1627         {
1628             Point aMed( aTL.X() + rGeom.nWidth/2, aTL.Y() + rGeom.nHeight/2 );
1629             const std::vector< Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
1630             for( unsigned int i = 0; i < rScreens.size(); i++ )
1631                 if( rScreens[i].IsInside( aMed ) )
1632                 {
1633                     aTL += rScreens[i].TopLeft();
1634                     aScreenSize = rScreens[i].GetSize();
1635                     break;
1636                 }
1637         }
1638         Rectangle aTarget( aTL,
1639                            Size( aScreenSize.Width() - rGeom.nLeftDecoration - rGeom.nTopDecoration,
1640                                  aScreenSize.Height() - rGeom.nTopDecoration - rGeom.nBottomDecoration )
1641                            );
1642         if( ! bHorizontal )
1643         {
1644             aTarget.SetSize(
1645                             Size(
1646                                  pFrame->maRestorePosSize.IsEmpty() ?
1647                                  rGeom.nWidth : pFrame->maRestorePosSize.GetWidth(),
1648                                  aTarget.GetHeight()
1649                                  )
1650                             );
1651             aTarget.Left() =
1652                 pFrame->maRestorePosSize.IsEmpty() ?
1653                 rGeom.nX : pFrame->maRestorePosSize.Left();
1654         }
1655         else if( ! bVertical )
1656         {
1657             aTarget.SetSize(
1658                             Size(
1659                                  aTarget.GetWidth(),
1660                                  pFrame->maRestorePosSize.IsEmpty() ?
1661                                  rGeom.nHeight : pFrame->maRestorePosSize.GetHeight()
1662                                  )
1663                             );
1664             aTarget.Top() =
1665                 pFrame->maRestorePosSize.IsEmpty() ?
1666                 rGeom.nY : pFrame->maRestorePosSize.Top();
1667         }
1668 
1669         Rectangle aRestore( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1670         if( pFrame->bMapped_ )
1671         {
1672             XSetInputFocus( m_pDisplay,
1673                             pFrame->GetShellWindow(),
1674                             RevertToNone,
1675                             CurrentTime
1676                             );
1677             if( m_aWMName.EqualsAscii( "Dtwm" ) )
1678             {
1679                 /*
1680                  *  Dtwm will only position  correctly with center gravity
1681                  *  and in this case the request actually changes the frame
1682                  *  not the shell window
1683                  */
1684                 aTarget = Rectangle( Point( 0, 0 ), aScreenSize );
1685                 aRestore.Move( -rGeom.nLeftDecoration, -rGeom.nTopDecoration );
1686             }
1687         }
1688 
1689         if( pFrame->maRestorePosSize.IsEmpty() )
1690             pFrame->maRestorePosSize = aRestore;
1691 
1692         pFrame->SetPosSize( aTarget );
1693         pFrame->nWidth_		= aTarget.GetWidth();
1694         pFrame->nHeight_	= aTarget.GetHeight();
1695         XRaiseWindow( m_pDisplay,
1696                       pFrame->GetShellWindow()
1697                       );
1698         if( pFrame->GetStackingWindow() )
1699             XRaiseWindow( m_pDisplay,
1700                           pFrame->GetStackingWindow()
1701                           );
1702 
1703     }
1704     else
1705     {
1706         pFrame->SetPosSize( pFrame->maRestorePosSize );
1707         pFrame->maRestorePosSize = Rectangle();
1708         pFrame->nWidth_ 			= rGeom.nWidth;
1709         pFrame->nHeight_			= rGeom.nHeight;
1710         if( m_aWMName.EqualsAscii( "Dtwm" ) && pFrame->bMapped_ )
1711         {
1712             pFrame->maGeometry.nX += rGeom.nLeftDecoration;
1713             pFrame->maGeometry.nY += rGeom.nTopDecoration;
1714         }
1715     }
1716 }
1717 
1718 /*
1719  *  NetWMAdaptor::maximizeFrame
1720  *  changes _NET_WM_STATE by sending a client message
1721  */
1722 
1723 void NetWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1724 {
1725     pFrame->mbMaximizedVert = bVertical;
1726     pFrame->mbMaximizedHorz = bHorizontal;
1727 
1728     if( m_aWMAtoms[ NET_WM_STATE ]
1729         && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ]
1730         && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ]
1731         && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
1732         )
1733     {
1734         if( pFrame->bMapped_ )
1735         {
1736             // window already mapped, send WM a message
1737             XEvent aEvent;
1738             aEvent.type					= ClientMessage;
1739             aEvent.xclient.display		= m_pDisplay;
1740             aEvent.xclient.window		= pFrame->GetShellWindow();
1741             aEvent.xclient.message_type	= m_aWMAtoms[ NET_WM_STATE ];
1742             aEvent.xclient.format		= 32;
1743             aEvent.xclient.data.l[0]	= bHorizontal ? 1 : 0;
1744             aEvent.xclient.data.l[1]	= m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1745             aEvent.xclient.data.l[2]	= bHorizontal == bVertical ? m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] : 0;
1746             aEvent.xclient.data.l[3]	= 0;
1747             aEvent.xclient.data.l[4]	= 0;
1748             XSendEvent( m_pDisplay,
1749                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1750                         False,
1751                         SubstructureNotifyMask | SubstructureRedirectMask,
1752                         &aEvent
1753                         );
1754             if( bHorizontal != bVertical )
1755             {
1756                 aEvent.xclient.data.l[0]= bVertical ? 1 : 0;
1757                 aEvent.xclient.data.l[1]= m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1758                 aEvent.xclient.data.l[2]= 0;
1759                 XSendEvent( m_pDisplay,
1760                             m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1761                             False,
1762                             SubstructureNotifyMask | SubstructureRedirectMask,
1763                             &aEvent
1764                             );
1765             }
1766         }
1767         else
1768         {
1769             // window not mapped yet, set _NET_WM_STATE directly
1770             setNetWMState( pFrame );
1771         }
1772         if( !bHorizontal && !bVertical )
1773             pFrame->maRestorePosSize = Rectangle();
1774         else if( pFrame->maRestorePosSize.IsEmpty() )
1775         {
1776             const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1777             pFrame->maRestorePosSize =
1778                 Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1779         }
1780     }
1781     else
1782         WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1783 }
1784 
1785 /*
1786  *  GnomeWMAdaptor::maximizeFrame
1787  *  changes _WIN_STATE by sending a client message
1788  */
1789 
1790 void GnomeWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1791 {
1792     pFrame->mbMaximizedVert = bVertical;
1793     pFrame->mbMaximizedHorz = bHorizontal;
1794 
1795     if( m_aWMAtoms[ WIN_STATE ]
1796         && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
1797         )
1798     {
1799         if( pFrame->bMapped_ )
1800         {
1801              // window already mapped, send WM a message
1802             XEvent aEvent;
1803             aEvent.type					= ClientMessage;
1804             aEvent.xclient.display		= m_pDisplay;
1805             aEvent.xclient.window		= pFrame->GetShellWindow();
1806             aEvent.xclient.message_type	= m_aWMAtoms[ WIN_STATE ];
1807             aEvent.xclient.format		= 32;
1808             aEvent.xclient.data.l[0]	= (1<<2)|(1<<3);
1809             aEvent.xclient.data.l[1]	=
1810                 (bVertical ? (1<<2) : 0)
1811                 | (bHorizontal ? (1<<3) : 0);
1812             aEvent.xclient.data.l[2]	= 0;
1813             aEvent.xclient.data.l[3]	= 0;
1814             aEvent.xclient.data.l[4]	= 0;
1815             XSendEvent( m_pDisplay,
1816                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1817                         False,
1818                         SubstructureNotifyMask,
1819                         &aEvent
1820                         );
1821         }
1822         else
1823             // window not mapped yet, set _WIN_STATE directly
1824             setGnomeWMState( pFrame );
1825 
1826         if( !bHorizontal && !bVertical )
1827             pFrame->maRestorePosSize = Rectangle();
1828         else if( pFrame->maRestorePosSize.IsEmpty() )
1829         {
1830             const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1831             pFrame->maRestorePosSize =
1832                 Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1833         }
1834     }
1835     else
1836         WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1837 }
1838 
1839 /*
1840  *  WMAdaptor::supportsICCCMPos
1841  */
1842 
1843 bool WMAdaptor::supportsICCCMPos() const
1844 {
1845     return
1846         m_aWMName.EqualsAscii( "Sawfish" )
1847         || m_aWMName.EqualsAscii( "Dtwm" );
1848 }
1849 
1850 /*
1851  *  NetWMAdaptor::supportsICCCMPos
1852  */
1853 
1854 bool NetWMAdaptor::supportsICCCMPos() const
1855 {
1856     return true;
1857 }
1858 
1859 
1860 /*
1861  *  WMAdaptor::enableAlwaysOnTop
1862  */
1863 void WMAdaptor::enableAlwaysOnTop( X11SalFrame*, bool /*bEnable*/ ) const
1864 {
1865 }
1866 
1867 /*
1868  *  NetWMAdaptor::enableAlwaysOnTop
1869  */
1870 void NetWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1871 {
1872     pFrame->bAlwaysOnTop_ = bEnable;
1873     if( m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
1874     {
1875         if( pFrame->bMapped_ )
1876         {
1877             // window already mapped, send WM a message
1878             XEvent aEvent;
1879             aEvent.type					= ClientMessage;
1880             aEvent.xclient.display		= m_pDisplay;
1881             aEvent.xclient.window		= pFrame->GetShellWindow();
1882             aEvent.xclient.message_type	= m_aWMAtoms[ NET_WM_STATE ];
1883             aEvent.xclient.format		= 32;
1884             aEvent.xclient.data.l[0]	= bEnable ? 1 : 0;
1885             aEvent.xclient.data.l[1]	= m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1886             aEvent.xclient.data.l[2]	= 0;
1887             aEvent.xclient.data.l[3]	= 0;
1888             aEvent.xclient.data.l[4]	= 0;
1889             XSendEvent( m_pDisplay,
1890                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1891                         False,
1892                         SubstructureNotifyMask | SubstructureRedirectMask,
1893                         &aEvent
1894                         );
1895         }
1896         else
1897             setNetWMState( pFrame );
1898     }
1899 }
1900 
1901 /*
1902  *  GnomeWMAdaptor::enableAlwaysOnTop
1903  */
1904 void GnomeWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1905 {
1906     pFrame->bAlwaysOnTop_ = bEnable;
1907     if( m_aWMAtoms[ WIN_LAYER ] )
1908     {
1909         if( pFrame->bMapped_ )
1910         {
1911             // window already mapped, send WM a message
1912             XEvent aEvent;
1913             aEvent.type					= ClientMessage;
1914             aEvent.xclient.display		= m_pDisplay;
1915             aEvent.xclient.window		= pFrame->GetShellWindow();
1916             aEvent.xclient.message_type	= m_aWMAtoms[ WIN_LAYER ];
1917             aEvent.xclient.format		= 32;
1918             aEvent.xclient.data.l[0]	= bEnable ? 6 : 4;
1919             aEvent.xclient.data.l[1]	= 0;
1920             aEvent.xclient.data.l[2]	= 0;
1921             aEvent.xclient.data.l[3]	= 0;
1922             aEvent.xclient.data.l[4]	= 0;
1923             XSendEvent( m_pDisplay,
1924                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1925                         False,
1926                         SubstructureNotifyMask | SubstructureRedirectMask,
1927                         &aEvent
1928                         );
1929         }
1930         else
1931         {
1932             sal_uInt32 nNewLayer = bEnable ? 6 : 4;
1933             XChangeProperty( m_pDisplay,
1934                              pFrame->GetShellWindow(),
1935                              m_aWMAtoms[ WIN_LAYER ],
1936                              XA_CARDINAL,
1937                              32,
1938                              PropModeReplace,
1939                              (unsigned char*)&nNewLayer,
1940                              1
1941                              );
1942         }
1943     }
1944 }
1945 
1946 /*
1947  *  WMAdaptor::changeReferenceFrame
1948  */
1949 void WMAdaptor::changeReferenceFrame( X11SalFrame* pFrame, X11SalFrame* pReferenceFrame ) const
1950 {
1951     if( ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG )
1952         && ! pFrame->IsOverrideRedirect()
1953         && ! pFrame->IsFloatGrabWindow()
1954         )
1955     {
1956         XLIB_Window aTransient = pFrame->pDisplay_->GetRootWindow( pFrame->GetScreenNumber() );
1957         pFrame->mbTransientForRoot = true;
1958         if( pReferenceFrame )
1959         {
1960             aTransient = pReferenceFrame->GetShellWindow();
1961             pFrame->mbTransientForRoot = false;
1962         }
1963         XSetTransientForHint( m_pDisplay,
1964                               pFrame->GetShellWindow(),
1965                               aTransient );
1966     }
1967 }
1968 
1969 /*
1970  *  WMAdaptor::handlePropertyNotify
1971  */
1972 int WMAdaptor::handlePropertyNotify( X11SalFrame*, XPropertyEvent* ) const
1973 {
1974     return 0;
1975 }
1976 
1977 /*
1978  *  NetWMAdaptor::handlePropertyNotify
1979  */
1980 int NetWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
1981 {
1982     int nHandled = 1;
1983     if( pEvent->atom == m_aWMAtoms[ NET_WM_STATE ] )
1984     {
1985         pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
1986         pFrame->mbShaded = false;
1987 
1988         if( pEvent->state == PropertyNewValue )
1989         {
1990             Atom nType, *pStates;
1991             int nFormat;
1992             unsigned long nItems, nBytesLeft;
1993             unsigned char* pData = NULL;
1994             long nOffset = 0;
1995             do
1996             {
1997                 XGetWindowProperty( m_pDisplay,
1998                                     pEvent->window,
1999                                     m_aWMAtoms[ NET_WM_STATE ],
2000                                     nOffset, 64,
2001                                     False,
2002                                     XA_ATOM,
2003                                     &nType,
2004                                     &nFormat,
2005                                     &nItems, &nBytesLeft,
2006                                     &pData );
2007                 if( pData )
2008                 {
2009                     if( nType == XA_ATOM && nFormat == 32 && nItems > 0 )
2010                     {
2011                         pStates = (Atom*)pData;
2012                         for( unsigned long i = 0; i < nItems; i++ )
2013                         {
2014                             if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
2015                                 pFrame->mbMaximizedVert = true;
2016                             else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
2017                                 pFrame->mbMaximizedHorz = true;
2018                             else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_SHADED ] && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
2019                                 pFrame->mbShaded = true;
2020                         }
2021                     }
2022                     XFree( pData );
2023                     pData = NULL;
2024                     nOffset += nItems * nFormat / 32;
2025                 }
2026                 else
2027                     break;
2028             } while( nBytesLeft > 0 );
2029         }
2030 
2031         if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
2032             pFrame->maRestorePosSize = Rectangle();
2033         else
2034         {
2035             const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
2036             // the current geometry may already be changed by the corresponding
2037             // ConfigureNotify, but this cannot be helped
2038             pFrame->maRestorePosSize =
2039                 Rectangle( Point( rGeom.nX, rGeom.nY ),
2040                            Size( rGeom.nWidth, rGeom.nHeight ) );
2041         }
2042     }
2043     else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
2044     {
2045         pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
2046     }
2047     else
2048         nHandled = 0;
2049 
2050     return nHandled;
2051 }
2052 
2053 /*
2054  *  GnomeWMAdaptor::handlePropertyNotify
2055  */
2056 int GnomeWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
2057 {
2058     int nHandled = 1;
2059     if( pEvent->atom == m_aWMAtoms[ WIN_STATE ] )
2060     {
2061         pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
2062         pFrame->mbShaded = false;
2063 
2064         if( pEvent->state == PropertyNewValue )
2065         {
2066             Atom nType;
2067             int nFormat = 0;
2068             unsigned long nItems = 0;
2069             unsigned long nBytesLeft = 0;
2070             unsigned char* pData = 0;
2071             XGetWindowProperty( m_pDisplay,
2072                                 pEvent->window,
2073                                 m_aWMAtoms[ WIN_STATE ],
2074                                 0, 1,
2075                                 False,
2076                                 XA_CARDINAL,
2077                                 &nType,
2078                                 &nFormat,
2079                                 &nItems, &nBytesLeft,
2080                                 &pData );
2081             if( pData )
2082             {
2083                 if( nType == XA_CARDINAL && nFormat == 32 && nItems == 1 )
2084                 {
2085                     sal_uInt32 nWinState = *(sal_uInt32*)pData;
2086                     if( nWinState & (1<<2) )
2087                         pFrame->mbMaximizedVert = true;
2088                     if( nWinState & (1<<3) )
2089                         pFrame->mbMaximizedHorz = true;
2090                     if( nWinState & (1<<5) )
2091                         pFrame->mbShaded = true;
2092                 }
2093                 XFree( pData );
2094             }
2095         }
2096 
2097         if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
2098             pFrame->maRestorePosSize = Rectangle();
2099         else
2100         {
2101             const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
2102             // the current geometry may already be changed by the corresponding
2103             // ConfigureNotify, but this cannot be helped
2104             pFrame->maRestorePosSize =
2105                 Rectangle( Point( rGeom.nX, rGeom.nY ),
2106                            Size( rGeom.nWidth, rGeom.nHeight ) );
2107         }
2108     }
2109     else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
2110     {
2111         pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
2112     }
2113     else
2114         nHandled = 0;
2115 
2116     return nHandled;
2117 }
2118 
2119 /*
2120  * WMAdaptor::shade
2121  */
2122 void WMAdaptor::shade( X11SalFrame*, bool /*bToShaded*/ ) const
2123 {
2124 }
2125 
2126 /*
2127  * NetWMAdaptor::shade
2128  */
2129 void NetWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
2130 {
2131     if( m_aWMAtoms[ NET_WM_STATE ]
2132         && m_aWMAtoms[ NET_WM_STATE_SHADED ]
2133         && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
2134         )
2135     {
2136         pFrame->mbShaded = bToShaded;
2137         if( pFrame->bMapped_ )
2138         {
2139             // window already mapped, send WM a message
2140             XEvent aEvent;
2141             aEvent.type					= ClientMessage;
2142             aEvent.xclient.display		= m_pDisplay;
2143             aEvent.xclient.window		= pFrame->GetShellWindow();
2144             aEvent.xclient.message_type	= m_aWMAtoms[ NET_WM_STATE ];
2145             aEvent.xclient.format		= 32;
2146             aEvent.xclient.data.l[0]	= bToShaded ? 1 : 0;
2147             aEvent.xclient.data.l[1]	= m_aWMAtoms[ NET_WM_STATE_SHADED ];
2148             aEvent.xclient.data.l[2]	= 0;
2149             aEvent.xclient.data.l[3]	= 0;
2150             aEvent.xclient.data.l[4]	= 0;
2151             XSendEvent( m_pDisplay,
2152                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2153                         False,
2154                         SubstructureNotifyMask | SubstructureRedirectMask,
2155                         &aEvent
2156                         );
2157         }
2158         else
2159         {
2160             // window not mapped yet, set _NET_WM_STATE directly
2161             setNetWMState( pFrame );
2162         }
2163     }
2164 }
2165 
2166 /*
2167  *  GnomeWMAdaptor::shade
2168  */
2169 void GnomeWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
2170 {
2171     if( m_aWMAtoms[ WIN_STATE ] )
2172     {
2173         pFrame->mbShaded = bToShaded;
2174         if( pFrame->bMapped_ )
2175         {
2176             // window already mapped, send WM a message
2177             XEvent aEvent;
2178             aEvent.type					= ClientMessage;
2179             aEvent.xclient.display		= m_pDisplay;
2180             aEvent.xclient.window		= pFrame->GetShellWindow();
2181             aEvent.xclient.message_type	= m_aWMAtoms[ WIN_STATE ];
2182             aEvent.xclient.format		= 32;
2183             aEvent.xclient.data.l[0]	= (1<<5);
2184             aEvent.xclient.data.l[1]	= bToShaded ? (1<<5) : 0;
2185             aEvent.xclient.data.l[2]	= 0;
2186             aEvent.xclient.data.l[3]	= 0;
2187             aEvent.xclient.data.l[4]	= 0;
2188             XSendEvent( m_pDisplay,
2189                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2190                         False,
2191                         SubstructureNotifyMask | SubstructureRedirectMask,
2192                         &aEvent
2193                         );
2194         }
2195         else
2196             setGnomeWMState( pFrame );
2197     }
2198 }
2199 
2200 /*
2201  *  WMAdaptor::showFullScreen
2202  */
2203 void WMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
2204 {
2205     pFrame->mbFullScreen = bFullScreen;
2206     maximizeFrame( pFrame, bFullScreen, bFullScreen );
2207 }
2208 
2209 /*
2210  *  NetWMAdaptor::showFullScreen
2211  */
2212 void NetWMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
2213 {
2214     if( m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
2215     {
2216         pFrame->mbFullScreen = bFullScreen;
2217         if( bFullScreen )
2218         {
2219             if( m_aWMAtoms[ MOTIF_WM_HINTS ] )
2220             {
2221                 XDeleteProperty( m_pDisplay,
2222                                  pFrame->GetShellWindow(),
2223                                 m_aWMAtoms[ MOTIF_WM_HINTS ] );
2224             }
2225         }
2226         if( pFrame->bMapped_ )
2227         {
2228             // window already mapped, send WM a message
2229             XEvent aEvent;
2230             aEvent.type					= ClientMessage;
2231             aEvent.xclient.display		= m_pDisplay;
2232             aEvent.xclient.window		= pFrame->GetShellWindow();
2233             aEvent.xclient.message_type	= m_aWMAtoms[ NET_WM_STATE ];
2234             aEvent.xclient.format		= 32;
2235             aEvent.xclient.data.l[0]	= bFullScreen ? 1 : 0;
2236             aEvent.xclient.data.l[1]	= m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
2237             aEvent.xclient.data.l[2]	= 0;
2238             aEvent.xclient.data.l[3]	= 0;
2239             aEvent.xclient.data.l[4]	= 0;
2240             XSendEvent( m_pDisplay,
2241                         m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2242                         False,
2243                         SubstructureNotifyMask | SubstructureRedirectMask,
2244                         &aEvent
2245                         );
2246         }
2247         else
2248         {
2249             // window not mapped yet, set _NET_WM_STATE directly
2250             setNetWMState( pFrame );
2251         }
2252         // #i42750# guess size before resize event shows up
2253         if( bFullScreen )
2254         {
2255             if( m_pSalDisplay->IsXinerama() )
2256             {
2257                 XLIB_Window aRoot, aChild;
2258                 int root_x = 0, root_y = 0, lx, ly;
2259                 unsigned int mask;
2260                 XQueryPointer( m_pDisplay,
2261                 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2262                 &aRoot, &aChild,
2263                 &root_x, &root_y, &lx, &ly, &mask );
2264                 const std::vector< Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
2265                 Point aMousePoint( root_x, root_y );
2266                 for( unsigned int i = 0; i < rScreens.size(); i++ )
2267                 {
2268                     if( rScreens[i].IsInside( aMousePoint ) )
2269                     {
2270                         pFrame->maGeometry.nX       = rScreens[i].Left();
2271                         pFrame->maGeometry.nY       = rScreens[i].Top();
2272                         pFrame->maGeometry.nWidth   = rScreens[i].GetWidth();
2273                         pFrame->maGeometry.nHeight  = rScreens[i].GetHeight();
2274                         break;
2275                     }
2276                 }
2277             }
2278             else
2279             {
2280                 Size aSize = m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() );
2281                 pFrame->maGeometry.nX       = 0;
2282                 pFrame->maGeometry.nY       = 0;
2283                 pFrame->maGeometry.nWidth   = aSize.Width();
2284                 pFrame->maGeometry.nHeight  = aSize.Height();
2285             }
2286             pFrame->CallCallback( SALEVENT_MOVERESIZE, NULL );
2287         }
2288     }
2289     else WMAdaptor::showFullScreen( pFrame, bFullScreen );
2290 }
2291 
2292 /*
2293  *  WMAdaptor::getCurrentWorkArea
2294  */
2295 // FIXME: multiscreen case
2296 int WMAdaptor::getCurrentWorkArea() const
2297 {
2298     int nCurrent = -1;
2299     if( m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2300     {
2301         Atom				aRealType	= None;
2302         int					nFormat		= 8;
2303         unsigned long		nItems		= 0;
2304         unsigned long		nBytesLeft	= 0;
2305         unsigned char*	pProperty	= NULL;
2306         if( XGetWindowProperty( m_pDisplay,
2307                                 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
2308                                 m_aWMAtoms[ NET_CURRENT_DESKTOP ],
2309                                 0, 1,
2310                                 False,
2311                                 XA_CARDINAL,
2312                                 &aRealType,
2313                                 &nFormat,
2314                                 &nItems,
2315                                 &nBytesLeft,
2316                                 &pProperty ) == 0
2317                                 && pProperty
2318         )
2319         {
2320             nCurrent = int(*(sal_Int32*)pProperty);
2321             XFree( pProperty );
2322         }
2323         else if( pProperty )
2324         {
2325             XFree( pProperty );
2326             pProperty = NULL;
2327         }
2328     }
2329     return nCurrent;
2330 }
2331 
2332 /*
2333  *  WMAdaptor::getWindowWorkArea
2334  */
2335 int WMAdaptor::getWindowWorkArea( XLIB_Window aWindow ) const
2336 {
2337     int nCurrent = -1;
2338     if( m_aWMAtoms[ NET_WM_DESKTOP ] )
2339     {
2340         Atom				aRealType	= None;
2341         int					nFormat		= 8;
2342         unsigned long		nItems		= 0;
2343         unsigned long		nBytesLeft	= 0;
2344         unsigned char*	pProperty	= NULL;
2345         if( XGetWindowProperty( m_pDisplay,
2346                                 aWindow,
2347                                 m_aWMAtoms[ NET_WM_DESKTOP ],
2348                                 0, 1,
2349                                 False,
2350                                 XA_CARDINAL,
2351                                 &aRealType,
2352                                 &nFormat,
2353                                 &nItems,
2354                                 &nBytesLeft,
2355                                 &pProperty ) == 0
2356                                 && pProperty
2357         )
2358         {
2359             nCurrent = int(*(sal_Int32*)pProperty);
2360             XFree( pProperty );
2361         }
2362         else if( pProperty )
2363         {
2364             XFree( pProperty );
2365             pProperty = NULL;
2366         }
2367     }
2368     return nCurrent;
2369 }
2370 
2371 /*
2372  *  WMAdaptor::getCurrentWorkArea
2373  */
2374 // fixme: multi screen case
2375 void WMAdaptor::switchToWorkArea( int nWorkArea, bool bConsiderWM ) const
2376 {
2377     if( bConsiderWM && ! getWMshouldSwitchWorkspace() )
2378         return;
2379 
2380     if( m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2381     {
2382         XEvent aEvent;
2383         aEvent.type					= ClientMessage;
2384         aEvent.xclient.display		= m_pDisplay;
2385         aEvent.xclient.window		= m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() );
2386         aEvent.xclient.message_type	= m_aWMAtoms[ NET_CURRENT_DESKTOP ];
2387         aEvent.xclient.format		= 32;
2388         aEvent.xclient.data.l[0]	= nWorkArea;
2389         aEvent.xclient.data.l[1]	= 0;
2390         aEvent.xclient.data.l[2]	= 0;
2391         aEvent.xclient.data.l[3]	= 0;
2392         aEvent.xclient.data.l[4]	= 0;
2393         XSendEvent( m_pDisplay,
2394                     m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
2395                     False,
2396                     SubstructureNotifyMask | SubstructureRedirectMask,
2397                     &aEvent
2398                     );
2399     }
2400 }
2401 
2402 /*
2403  * WMAdaptor::frameIsMapping
2404  */
2405 void WMAdaptor::frameIsMapping( X11SalFrame* ) const
2406 {
2407 }
2408 
2409 /*
2410  * NetWMAdaptor::frameIsMapping
2411  */
2412 void NetWMAdaptor::frameIsMapping( X11SalFrame* pFrame ) const
2413 {
2414     setNetWMState( pFrame );
2415 }
2416 
2417 /*
2418  * WMAdaptor::setFrameStruts
2419  */
2420 void WMAdaptor::setFrameStruts( X11SalFrame*,
2421                                 int, int, int, int,
2422                                 int, int, int, int,
2423                                 int, int, int, int ) const
2424 {
2425 }
2426 
2427 /*
2428  * NetWMAdaptor::setFrameStruts
2429  */
2430 void NetWMAdaptor::setFrameStruts( X11SalFrame* pFrame,
2431                                    int left, int right, int top, int bottom,
2432                                    int left_start_y, int left_end_y,
2433                                    int right_start_y, int right_end_y,
2434                                    int top_start_x, int top_end_x,
2435                                    int bottom_start_x, int bottom_end_x ) const
2436 {
2437     long nData[12];
2438     nData[0] = left;
2439     nData[1] = right;
2440     nData[2] = top;
2441     nData[3] = bottom;
2442     nData[4] = left_start_y;
2443     nData[5] = left_end_y;
2444     nData[6] = right_start_y;
2445     nData[7] = right_end_y;
2446     nData[8] = top_start_x;
2447     nData[9] = top_end_x;
2448     nData[10]= bottom_start_x;
2449     nData[11]= bottom_end_x;
2450     Atom aProperty = None;
2451     int nSetData = 0;
2452 
2453     if( m_aWMAtoms[NET_WM_STRUT_PARTIAL] )
2454     {
2455         aProperty = m_aWMAtoms[NET_WM_STRUT_PARTIAL];
2456         nSetData = 12;
2457     }
2458     else if( m_aWMAtoms[NET_WM_STRUT] )
2459     {
2460         aProperty = m_aWMAtoms[NET_WM_STRUT];
2461         nSetData = 4;
2462     }
2463     if( nSetData )
2464     {
2465             XChangeProperty( m_pDisplay,
2466                              pFrame->GetShellWindow(),
2467                              aProperty,
2468                              XA_CARDINAL,
2469                              32,
2470                              PropModeReplace,
2471                              (unsigned char*)&nData,
2472                              nSetData
2473                              );
2474     }
2475 }
2476 
2477 /*
2478  * WMAdaptor::setUserTime
2479  */
2480 void WMAdaptor::setUserTime( X11SalFrame*, long ) const
2481 {
2482 }
2483 
2484 /*
2485  * NetWMAdaptor::setUserTime
2486  */
2487 void NetWMAdaptor::setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const
2488 {
2489     if( m_aWMAtoms[NET_WM_USER_TIME] )
2490     {
2491         XChangeProperty( m_pDisplay,
2492                          i_pFrame->GetShellWindow(),
2493                          m_aWMAtoms[NET_WM_USER_TIME],
2494                          XA_CARDINAL,
2495                          32,
2496                          PropModeReplace,
2497                          (unsigned char*)&i_nUserTime,
2498                          1
2499                          );
2500     }
2501 }
2502 
2503 /*
2504  * WMAdaptor::setPID
2505  */
2506 void WMAdaptor::setPID( X11SalFrame* i_pFrame ) const
2507 {
2508     if( m_aWMAtoms[NET_WM_PID] )
2509     {
2510         long nPID = (long)getpid();
2511         XChangeProperty( m_pDisplay,
2512                          i_pFrame->GetShellWindow(),
2513                          m_aWMAtoms[NET_WM_PID],
2514                          XA_CARDINAL,
2515                          32,
2516                          PropModeReplace,
2517                          (unsigned char*)&nPID,
2518                          1
2519                          );
2520     }
2521 }
2522 
2523 /*
2524 * WMAdaptor::setClientMachine
2525 */
2526 void WMAdaptor::setClientMachine( X11SalFrame* i_pFrame ) const
2527 {
2528     rtl::OString aWmClient( rtl::OUStringToOString( GetX11SalData()->GetLocalHostName(), RTL_TEXTENCODING_ASCII_US ) );
2529     XTextProperty aClientProp = { (unsigned char*)aWmClient.getStr(), XA_STRING, 8, aWmClient.getLength() };
2530     XSetWMClientMachine( m_pDisplay, i_pFrame->GetShellWindow(), &aClientProp );
2531 }
2532 
2533 void WMAdaptor::answerPing( X11SalFrame* i_pFrame, XClientMessageEvent* i_pEvent ) const
2534 {
2535     if( m_aWMAtoms[NET_WM_PING] &&
2536         i_pEvent->message_type == m_aWMAtoms[ WM_PROTOCOLS ] &&
2537         (Atom)i_pEvent->data.l[0] == m_aWMAtoms[ NET_WM_PING ] )
2538     {
2539         XEvent aEvent;
2540         aEvent.xclient = *i_pEvent;
2541         aEvent.xclient.window = m_pSalDisplay->GetRootWindow( i_pFrame->GetScreenNumber() );
2542         XSendEvent( m_pDisplay,
2543                     m_pSalDisplay->GetRootWindow( i_pFrame->GetScreenNumber() ),
2544                     False,
2545                     SubstructureNotifyMask | SubstructureRedirectMask,
2546                     &aEvent
2547                     );
2548         XFlush( m_pDisplay );
2549     }
2550 }
2551 
2552 /*
2553 * WMAdaptor::setFullScreenMonitors
2554 */
2555 void WMAdaptor::setFullScreenMonitors( XLIB_Window, sal_Int32 )
2556 {
2557 }
2558 
2559 /*
2560 * NetWMAdaptor::setFullScreenMonitors
2561 */
2562 void NetWMAdaptor::setFullScreenMonitors( XLIB_Window i_aWindow, sal_Int32 i_nScreen )
2563 {
2564     if( m_aWMAtoms[ NET_WM_FULLSCREEN_MONITORS ] )
2565     {
2566         const std::vector< Rectangle >& rScreens( m_pSalDisplay->GetXineramaScreens() );
2567         if( m_pSalDisplay->IsXinerama() && rScreens.size() > 1 )
2568         {
2569             long nSpannedMonitors[4] = {0,0,0,0};
2570             if( i_nScreen == -1 ) // all screens
2571             {
2572                 long nLeft   = rScreens.front().Left();
2573                 long nRight  = rScreens.front().Right();
2574                 long nTop    = rScreens.front().Top();
2575                 long nBottom = rScreens.front().Bottom();
2576                 for( long i = 1; i < long(rScreens.size()); ++ i )
2577                 {
2578                     if( rScreens[i].Left() < nLeft )
2579                     {
2580                         nLeft = rScreens[i].Left();
2581                         nSpannedMonitors[2] = i;
2582                     }
2583                     if( rScreens[i].Top() < nTop )
2584                     {
2585                         nTop = rScreens[i].Top();
2586                         nSpannedMonitors[0] = i;
2587                     }
2588                     if( rScreens[i].Bottom() > nBottom )
2589                     {
2590                         nBottom = rScreens[i].Bottom();
2591                         nSpannedMonitors[1] = i;
2592                     }
2593                     if( rScreens[i].Right() > nRight )
2594                     {
2595                         nRight = rScreens[i].Right();
2596                         nSpannedMonitors[3] = i;
2597                     }
2598                 }
2599             }
2600             else
2601             {
2602                 if( i_nScreen < 0 || i_nScreen >= sal_Int32(rScreens.size()) )
2603                     i_nScreen = 0;
2604                 nSpannedMonitors[0] = nSpannedMonitors[1] = nSpannedMonitors[2] = nSpannedMonitors[3] = i_nScreen;
2605             }
2606             XChangeProperty( m_pDisplay, i_aWindow,
2607                              m_aWMAtoms[ NET_WM_FULLSCREEN_MONITORS ],
2608                              XA_CARDINAL, 32,
2609                              PropModeReplace, (unsigned char*)nSpannedMonitors, 4 );
2610 
2611         }
2612     }
2613 }
2614 
2615