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