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