nss: upgrade to release 3.73
[LibreOffice.git] / vcl / unx / generic / app / wmadaptor.cxx
blobec853e26acccde6bfba31ea69e72fe3c1cc9d1f2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <string.h>
21 #include <stdlib.h>
23 #include <i18nlangtag/languagetag.hxx>
24 #include <rtl/locale.h>
26 #include <osl/thread.h>
27 #include <osl/process.h>
28 #include <sal/macros.h>
29 #include <sal/log.hxx>
30 #include <configsettings.hxx>
32 #include <unx/wmadaptor.hxx>
33 #include <unx/saldisp.hxx>
34 #include <unx/salframe.h>
36 #include <X11/Xlib.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xatom.h>
40 namespace vcl_sal {
42 class NetWMAdaptor : public WMAdaptor
44 void setNetWMState( X11SalFrame* pFrame ) const;
45 void initAtoms();
46 virtual bool isValid() const override;
47 public:
48 explicit NetWMAdaptor( SalDisplay* );
50 virtual void setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const override;
51 virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const override;
52 virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const override;
53 virtual void setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pTransientFrame ) const override;
54 virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const override;
55 virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const override;
56 virtual void showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const override;
57 virtual void frameIsMapping( X11SalFrame* pFrame ) const override;
58 virtual void setUserTime( X11SalFrame* i_pFrame, tools::Long i_nUserTime ) const override;
61 class GnomeWMAdaptor : public WMAdaptor
63 bool m_bValid;
65 void setGnomeWMState( X11SalFrame* pFrame ) const;
66 void initAtoms();
67 virtual bool isValid() const override;
68 public:
69 explicit GnomeWMAdaptor( SalDisplay * );
71 virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const override;
72 virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const override;
73 virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const override;
74 virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const override;
79 using namespace vcl_sal;
81 namespace {
83 struct WMAdaptorProtocol
85 const char* pProtocol;
86 int nProtocol;
92 * table must be sorted ascending in strings
93 * since it is use with bsearch
95 const WMAdaptorProtocol aProtocolTab[] =
97 { "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", WMAdaptor::KDE_NET_WM_WINDOW_TYPE_OVERRIDE },
98 { "_NET_ACTIVE_WINDOW", WMAdaptor::NET_ACTIVE_WINDOW },
99 { "_NET_CURRENT_DESKTOP", WMAdaptor::NET_CURRENT_DESKTOP },
100 { "_NET_NUMBER_OF_DESKTOPS", WMAdaptor::NET_NUMBER_OF_DESKTOPS },
101 { "_NET_WM_DESKTOP", WMAdaptor::NET_WM_DESKTOP },
102 { "_NET_WM_ICON", WMAdaptor::NET_WM_ICON },
103 { "_NET_WM_ICON_NAME", WMAdaptor::NET_WM_ICON_NAME },
104 { "_NET_WM_PING", WMAdaptor::NET_WM_PING },
105 { "_NET_WM_STATE", WMAdaptor::NET_WM_STATE },
106 { "_NET_WM_STATE_ABOVE", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
107 { "_NET_WM_STATE_FULLSCREEN", WMAdaptor::NET_WM_STATE_FULLSCREEN },
108 { "_NET_WM_STATE_MAXIMIZED_HORIZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ }, // common bug in e.g. older kwin and sawfish implementations
109 { "_NET_WM_STATE_MAXIMIZED_HORZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ },
110 { "_NET_WM_STATE_MAXIMIZED_VERT", WMAdaptor::NET_WM_STATE_MAXIMIZED_VERT },
111 { "_NET_WM_STATE_MODAL", WMAdaptor::NET_WM_STATE_MODAL },
112 { "_NET_WM_STATE_SHADED", WMAdaptor::NET_WM_STATE_SHADED },
113 { "_NET_WM_STATE_SKIP_PAGER", WMAdaptor::NET_WM_STATE_SKIP_PAGER },
114 { "_NET_WM_STATE_SKIP_TASKBAR", WMAdaptor::NET_WM_STATE_SKIP_TASKBAR },
115 { "_NET_WM_STATE_STAYS_ON_TOP", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
116 { "_NET_WM_STATE_STICKY", WMAdaptor::NET_WM_STATE_STICKY },
117 { "_NET_WM_STRUT", WMAdaptor::NET_WM_STRUT },
118 { "_NET_WM_STRUT_PARTIAL", WMAdaptor::NET_WM_STRUT_PARTIAL },
119 { "_NET_WM_WINDOW_TYPE", WMAdaptor::NET_WM_WINDOW_TYPE },
120 { "_NET_WM_WINDOW_TYPE_DESKTOP", WMAdaptor::NET_WM_WINDOW_TYPE_DESKTOP },
121 { "_NET_WM_WINDOW_TYPE_DIALOG", WMAdaptor::NET_WM_WINDOW_TYPE_DIALOG },
122 { "_NET_WM_WINDOW_TYPE_DOCK", WMAdaptor::NET_WM_WINDOW_TYPE_DOCK },
123 { "_NET_WM_WINDOW_TYPE_MENU", WMAdaptor::NET_WM_WINDOW_TYPE_MENU },
124 { "_NET_WM_WINDOW_TYPE_NORMAL", WMAdaptor::NET_WM_WINDOW_TYPE_NORMAL },
125 { "_NET_WM_WINDOW_TYPE_SPLASH", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH },
126 { "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH }, // bug in Metacity 2.4.1
127 { "_NET_WM_WINDOW_TYPE_TOOLBAR", WMAdaptor::NET_WM_WINDOW_TYPE_TOOLBAR },
128 { "_NET_WM_WINDOW_TYPE_UTILITY", WMAdaptor::NET_WM_WINDOW_TYPE_UTILITY },
129 { "_NET_WORKAREA", WMAdaptor::NET_WORKAREA },
130 { "_WIN_APP_STATE", WMAdaptor::WIN_APP_STATE },
131 { "_WIN_CLIENT_LIST", WMAdaptor::WIN_CLIENT_LIST },
132 { "_WIN_EXPANDED_SIZE", WMAdaptor::WIN_EXPANDED_SIZE },
133 { "_WIN_HINTS", WMAdaptor::WIN_HINTS },
134 { "_WIN_ICONS", WMAdaptor::WIN_ICONS },
135 { "_WIN_LAYER", WMAdaptor::WIN_LAYER },
136 { "_WIN_STATE", WMAdaptor::WIN_STATE },
137 { "_WIN_WORKSPACE", WMAdaptor::WIN_WORKSPACE },
138 { "_WIN_WORKSPACE_COUNT", WMAdaptor::WIN_WORKSPACE_COUNT }
142 * table containing atoms to get anyway
145 const WMAdaptorProtocol aAtomTab[] =
147 { "WM_STATE", WMAdaptor::WM_STATE },
148 { "_MOTIF_WM_HINTS", WMAdaptor::MOTIF_WM_HINTS },
149 { "WM_PROTOCOLS", WMAdaptor::WM_PROTOCOLS },
150 { "WM_DELETE_WINDOW", WMAdaptor::WM_DELETE_WINDOW },
151 { "WM_TAKE_FOCUS", WMAdaptor::WM_TAKE_FOCUS },
152 { "WM_COMMAND", WMAdaptor::WM_COMMAND },
153 { "WM_CLIENT_LEADER", WMAdaptor::WM_CLIENT_LEADER },
154 { "WM_LOCALE_NAME", WMAdaptor::WM_LOCALE_NAME },
155 { "WM_TRANSIENT_FOR", WMAdaptor::WM_TRANSIENT_FOR },
156 { "SAL_QUITEVENT", WMAdaptor::SAL_QUITEVENT },
157 { "SAL_USEREVENT", WMAdaptor::SAL_USEREVENT },
158 { "SAL_EXTTEXTEVENT", WMAdaptor::SAL_EXTTEXTEVENT },
159 { "SAL_GETTIMEEVENT", WMAdaptor::SAL_GETTIMEEVENT },
160 { "VCL_SYSTEM_SETTINGS", WMAdaptor::VCL_SYSTEM_SETTINGS },
161 { "_XSETTINGS_SETTINGS", WMAdaptor::XSETTINGS },
162 { "_XEMBED", WMAdaptor::XEMBED },
163 { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO },
164 { "_NET_WM_USER_TIME", WMAdaptor::NET_WM_USER_TIME },
165 { "_NET_WM_PID", WMAdaptor::NET_WM_PID }
168 extern "C" {
169 static int compareProtocol( const void* pLeft, const void* pRight )
171 return strcmp( static_cast<const WMAdaptorProtocol*>(pLeft)->pProtocol, static_cast<const WMAdaptorProtocol*>(pRight)->pProtocol );
175 std::unique_ptr<WMAdaptor> WMAdaptor::createWMAdaptor( SalDisplay* pSalDisplay )
177 std::unique_ptr<WMAdaptor> pAdaptor;
179 // try a NetWM
180 pAdaptor.reset(new NetWMAdaptor( pSalDisplay ));
181 if( ! pAdaptor->isValid() )
183 pAdaptor.reset();
185 #if OSL_DEBUG_LEVEL > 1
186 else
187 SAL_INFO("vcl.app", "WM supports extended WM hints.");
188 #endif
190 // try a GnomeWM
191 if( ! pAdaptor )
193 pAdaptor.reset(new GnomeWMAdaptor( pSalDisplay ));
194 if( ! pAdaptor->isValid() )
196 pAdaptor.reset();
198 #if OSL_DEBUG_LEVEL > 1
199 else
200 SAL_INFO("vcl.app", "WM supports GNOME WM hints.");
201 #endif
204 if( ! pAdaptor )
205 pAdaptor.reset(new WMAdaptor( pSalDisplay ));
207 #if OSL_DEBUG_LEVEL > 1
208 SAL_INFO("vcl.app", "Window Manager's name is \""
209 << pAdaptor->getWindowManagerName()
210 << "\".");
211 #endif
212 return pAdaptor;
216 * WMAdaptor constructor
219 WMAdaptor::WMAdaptor( SalDisplay* pDisplay ) :
220 m_pSalDisplay( pDisplay ),
221 m_bEnableAlwaysOnTopWorks( false ),
222 m_bLegacyPartialFullscreen( false ),
223 m_nWinGravity( StaticGravity ),
224 m_nInitWinGravity( StaticGravity ),
225 m_bWMshouldSwitchWorkspace( true ),
226 m_bWMshouldSwitchWorkspaceInit( false )
228 Atom aRealType = None;
229 int nFormat = 8;
230 unsigned long nItems = 0;
231 unsigned long nBytesLeft = 0;
232 unsigned char* pProperty = nullptr;
234 // default desktops
235 m_nDesktops = 1;
236 m_aWMWorkAreas = ::std::vector< tools::Rectangle >
237 ( 1, tools::Rectangle( Point(), m_pSalDisplay->GetScreenSize( m_pSalDisplay->GetDefaultXScreen() ) ) );
238 m_bEqualWorkAreas = true;
240 memset( m_aWMAtoms, 0, sizeof( m_aWMAtoms ) );
241 m_pDisplay = m_pSalDisplay->GetDisplay();
243 initAtoms();
244 getNetWmName(); // try to discover e.g. Sawfish
246 if( m_aWMName.isEmpty() )
248 // check for ReflectionX wm (as it needs a workaround in Windows mode
249 Atom aRwmRunning = XInternAtom( m_pDisplay, "RWM_RUNNING", True );
250 if( aRwmRunning != None &&
251 XGetWindowProperty( m_pDisplay,
252 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
253 aRwmRunning,
254 0, 32,
255 False,
256 aRwmRunning,
257 &aRealType,
258 &nFormat,
259 &nItems,
260 &nBytesLeft,
261 &pProperty ) == 0 )
263 if( aRealType == aRwmRunning )
264 m_aWMName = "ReflectionX";
265 XFree( pProperty );
267 else
269 aRwmRunning = XInternAtom( m_pDisplay, "_WRQ_WM_RUNNING", True );
270 if( aRwmRunning != None &&
271 XGetWindowProperty( m_pDisplay,
272 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
273 aRwmRunning,
274 0, 32,
275 False,
276 XA_STRING,
277 &aRealType,
278 &nFormat,
279 &nItems,
280 &nBytesLeft,
281 &pProperty ) == 0 )
283 if( aRealType == XA_STRING )
284 m_aWMName = "ReflectionX Windows";
285 XFree( pProperty );
289 if( !m_aWMName.isEmpty() )
290 return;
292 Atom aTTAPlatform = XInternAtom( m_pDisplay, "TTA_CLIENT_PLATFORM", True );
293 if( aTTAPlatform == None ||
294 XGetWindowProperty( m_pDisplay,
295 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
296 aTTAPlatform,
297 0, 32,
298 False,
299 XA_STRING,
300 &aRealType,
301 &nFormat,
302 &nItems,
303 &nBytesLeft,
304 &pProperty ) != 0 )
305 return;
307 if( aRealType == XA_STRING )
309 m_aWMName = "Tarantella";
310 // #i62319# pretend that AlwaysOnTop works since
311 // the alwaysontop workaround in salframe.cxx results
312 // in a raise/lower loop on a Windows tarantella client
313 // FIXME: this property contains an identification string that
314 // in theory should be good enough to recognize running on a
315 // Windows client; however this string does not seem to be
316 // documented as well as the property itself.
317 m_bEnableAlwaysOnTopWorks = true;
319 XFree( pProperty );
323 * WMAdaptor destructor
326 WMAdaptor::~WMAdaptor()
331 * NetWMAdaptor constructor
334 NetWMAdaptor::NetWMAdaptor( SalDisplay* pSalDisplay ) :
335 WMAdaptor( pSalDisplay )
337 // currently all _NET WMs do transient like expected
339 Atom aRealType = None;
340 int nFormat = 8;
341 unsigned long nItems = 0;
342 unsigned long nBytesLeft = 0;
343 unsigned char* pProperty = nullptr;
345 initAtoms();
347 // check for NetWM
348 bool bNetWM = getNetWmName();
349 if( bNetWM
350 && XGetWindowProperty( m_pDisplay,
351 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
352 m_aWMAtoms[ NET_SUPPORTED ],
353 0, 0,
354 False,
355 XA_ATOM,
356 &aRealType,
357 &nFormat,
358 &nItems,
359 &nBytesLeft,
360 &pProperty ) == 0
361 && aRealType == XA_ATOM
362 && nFormat == 32
365 if( pProperty )
367 XFree( pProperty );
368 pProperty = nullptr;
370 // collect supported protocols
371 if( XGetWindowProperty( m_pDisplay,
372 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
373 m_aWMAtoms[ NET_SUPPORTED ],
374 0, nBytesLeft/4,
375 False,
376 XA_ATOM,
377 &aRealType,
378 &nFormat,
379 &nItems,
380 &nBytesLeft,
381 &pProperty ) == 0
382 && nItems
385 Atom* pAtoms = reinterpret_cast<Atom*>(pProperty);
386 char** pAtomNames = static_cast<char**>(alloca( sizeof(char*)*nItems ));
387 if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
389 #if OSL_DEBUG_LEVEL > 1
390 SAL_INFO("vcl.app", "supported protocols:");
391 #endif
392 for( unsigned long i = 0; i < nItems; i++ )
394 // #i80971# protect against invalid atoms
395 if( pAtomNames[i] == nullptr )
396 continue;
398 WMAdaptorProtocol aSearch;
399 aSearch.pProtocol = pAtomNames[i];
400 WMAdaptorProtocol* pMatch = static_cast<WMAdaptorProtocol*>(
401 bsearch( &aSearch,
402 aProtocolTab,
403 SAL_N_ELEMENTS( aProtocolTab ),
404 sizeof( struct WMAdaptorProtocol ),
405 compareProtocol ));
406 if( pMatch )
408 m_aWMAtoms[ pMatch->nProtocol ] = pAtoms[ i ];
409 if( pMatch->nProtocol == NET_WM_STATE_STAYS_ON_TOP )
410 m_bEnableAlwaysOnTopWorks = true;
412 #if OSL_DEBUG_LEVEL > 1
413 SAL_INFO("vcl.app", " "
414 << pAtomNames[i]
415 << (((pMatch)&&(pMatch->nProtocol != -1)) ?
416 "" : " (unsupported)"));
417 #endif
418 XFree( pAtomNames[i] );
421 XFree( pProperty );
422 pProperty = nullptr;
424 else if( pProperty )
426 XFree( pProperty );
427 pProperty = nullptr;
430 // get number of desktops
431 if( m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ]
432 && XGetWindowProperty( m_pDisplay,
433 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
434 m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ],
435 0, 1,
436 False,
437 XA_CARDINAL,
438 &aRealType,
439 &nFormat,
440 &nItems,
441 &nBytesLeft,
442 &pProperty ) == 0
443 && pProperty
446 m_nDesktops = *reinterpret_cast<long*>(pProperty);
447 XFree( pProperty );
448 pProperty = nullptr;
449 // get work areas
450 if( m_aWMAtoms[ NET_WORKAREA ]
451 && XGetWindowProperty( m_pDisplay,
452 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
453 m_aWMAtoms[ NET_WORKAREA ],
454 0, 4*m_nDesktops,
455 False,
456 XA_CARDINAL,
457 &aRealType,
458 &nFormat,
459 &nItems,
460 &nBytesLeft,
461 &pProperty
462 ) == 0
463 && nItems == 4*static_cast<unsigned>(m_nDesktops)
466 m_aWMWorkAreas = ::std::vector< tools::Rectangle > ( m_nDesktops );
467 tools::Long* pValues = reinterpret_cast<long*>(pProperty);
468 for( int i = 0; i < m_nDesktops; i++ )
470 Point aPoint( pValues[4*i],
471 pValues[4*i+1] );
472 Size aSize( pValues[4*i+2],
473 pValues[4*i+3] );
474 tools::Rectangle aWorkArea( aPoint, aSize );
475 m_aWMWorkAreas[i] = aWorkArea;
476 if( aWorkArea != m_aWMWorkAreas[0] )
477 m_bEqualWorkAreas = false;
478 #if OSL_DEBUG_LEVEL > 1
479 SAL_INFO("vcl.app", "workarea " << i
480 << ": " << m_aWMWorkAreas[i].GetWidth()
481 << "x" << m_aWMWorkAreas[i].GetHeight()
482 << "+" << m_aWMWorkAreas[i].Left()
483 << "+" << m_aWMWorkAreas[i].Top());
484 #endif
486 XFree( pProperty );
488 else
490 #if OSL_DEBUG_LEVEL > 1
491 SAL_INFO("vcl.app", nItems/4 << " workareas for "
492 << m_nDesktops << " desktops !");
493 #endif
494 if( pProperty )
496 XFree(pProperty);
497 pProperty = nullptr;
501 else if( pProperty )
503 XFree( pProperty );
504 pProperty = nullptr;
507 else if( pProperty )
509 XFree( pProperty );
510 pProperty = nullptr;
515 * GnomeWMAdaptor constructor
518 GnomeWMAdaptor::GnomeWMAdaptor( SalDisplay* pSalDisplay ) :
519 WMAdaptor( pSalDisplay ),
520 m_bValid( false )
522 // currently all Gnome WMs do transient like expected
524 Atom aRealType = None;
525 int nFormat = 8;
526 unsigned long nItems = 0;
527 unsigned long nBytesLeft = 0;
528 unsigned char* pProperty = nullptr;
530 initAtoms();
532 // check for GnomeWM
533 if( m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ WIN_PROTOCOLS ] )
535 if( XGetWindowProperty( m_pDisplay,
536 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
537 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
538 0, 1,
539 False,
540 XA_CARDINAL,
541 &aRealType,
542 &nFormat,
543 &nItems,
544 &nBytesLeft,
545 &pProperty ) == 0
546 && aRealType == XA_CARDINAL
547 && nFormat == 32
548 && nItems != 0
551 ::Window aWMChild = *reinterpret_cast< ::Window* >(pProperty);
552 XFree( pProperty );
553 pProperty = nullptr;
554 GetGenericUnixSalData()->ErrorTrapPush();
555 if( XGetWindowProperty( m_pDisplay,
556 aWMChild,
557 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
558 0, 1,
559 False,
560 XA_CARDINAL,
561 &aRealType,
562 &nFormat,
563 &nItems,
564 &nBytesLeft,
565 &pProperty ) == 0
566 && aRealType == XA_CARDINAL
567 && nFormat == 32
568 && nItems != 0 )
570 if (! GetGenericUnixSalData()->ErrorTrapPop( false ) )
572 GetGenericUnixSalData()->ErrorTrapPush();
574 ::Window aCheckWindow = *reinterpret_cast< ::Window* >(pProperty);
575 XFree( pProperty );
576 pProperty = nullptr;
577 if( aCheckWindow == aWMChild )
579 m_bValid = true;
581 * get name of WM
582 * this is NOT part of the GNOME WM hints, but e.g. Sawfish
583 * already supports this part of the extended WM hints
585 m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
586 getNetWmName();
589 else
590 GetGenericUnixSalData()->ErrorTrapPush();
592 GetGenericUnixSalData()->ErrorTrapPop();
594 else if( pProperty )
596 XFree( pProperty );
597 pProperty = nullptr;
600 if( m_bValid
601 && XGetWindowProperty( m_pDisplay,
602 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
603 m_aWMAtoms[ WIN_PROTOCOLS ],
604 0, 0,
605 False,
606 XA_ATOM,
607 &aRealType,
608 &nFormat,
609 &nItems,
610 &nBytesLeft,
611 &pProperty ) == 0
612 && aRealType == XA_ATOM
613 && nFormat == 32
616 if( pProperty )
618 XFree( pProperty );
619 pProperty = nullptr;
621 // collect supported protocols
622 if( XGetWindowProperty( m_pDisplay,
623 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
624 m_aWMAtoms[ WIN_PROTOCOLS ],
625 0, nBytesLeft/4,
626 False,
627 XA_ATOM,
628 &aRealType,
629 &nFormat,
630 &nItems,
631 &nBytesLeft,
632 &pProperty ) == 0
633 && pProperty
636 Atom* pAtoms = reinterpret_cast<Atom*>(pProperty);
637 char** pAtomNames = static_cast<char**>(alloca( sizeof(char*)*nItems ));
638 if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
640 #if OSL_DEBUG_LEVEL > 1
641 SAL_INFO("vcl.app", "supported protocols:");
642 #endif
643 for( unsigned long i = 0; i < nItems; i++ )
645 // #i80971# protect against invalid atoms
646 if( pAtomNames[i] == nullptr )
647 continue;
649 WMAdaptorProtocol aSearch;
650 aSearch.pProtocol = pAtomNames[i];
651 WMAdaptorProtocol* pMatch = static_cast<WMAdaptorProtocol*>(
652 bsearch( &aSearch,
653 aProtocolTab,
654 SAL_N_ELEMENTS( aProtocolTab ),
655 sizeof( struct WMAdaptorProtocol ),
656 compareProtocol ));
657 if( pMatch )
659 m_aWMAtoms[ pMatch->nProtocol ] = pAtoms[ i ];
660 if( pMatch->nProtocol == WIN_LAYER )
661 m_bEnableAlwaysOnTopWorks = true;
663 if( strncmp( "_ICEWM_TRAY", pAtomNames[i], 11 ) == 0 )
665 m_aWMName = "IceWM";
666 m_nWinGravity = NorthWestGravity;
667 m_nInitWinGravity = NorthWestGravity;
669 #if OSL_DEBUG_LEVEL > 1
670 SAL_INFO("vcl.app", " "
671 << pAtomNames[i]
672 << (((pMatch) && (pMatch->nProtocol != -1)) ?
673 "" : " (unsupported)"));
674 #endif
675 XFree( pAtomNames[i] );
678 XFree( pProperty );
679 pProperty = nullptr;
681 else if( pProperty )
683 XFree( pProperty );
684 pProperty = nullptr;
687 // get number of desktops
688 if( m_aWMAtoms[ WIN_WORKSPACE_COUNT ]
689 && XGetWindowProperty( m_pDisplay,
690 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
691 m_aWMAtoms[ WIN_WORKSPACE_COUNT ],
692 0, 1,
693 False,
694 XA_CARDINAL,
695 &aRealType,
696 &nFormat,
697 &nItems,
698 &nBytesLeft,
699 &pProperty ) == 0
700 && pProperty
703 m_nDesktops = *reinterpret_cast<long*>(pProperty);
704 XFree( pProperty );
705 pProperty = nullptr;
707 else if( pProperty )
709 XFree( pProperty );
710 pProperty = nullptr;
713 else if( pProperty )
715 XFree( pProperty );
716 pProperty = nullptr;
721 * getNetWmName()
723 bool WMAdaptor::getNetWmName()
725 Atom aRealType = None;
726 int nFormat = 8;
727 unsigned long nItems = 0;
728 unsigned long nBytesLeft = 0;
729 unsigned char* pProperty = nullptr;
730 bool bNetWM = false;
732 if( m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ NET_WM_NAME ] )
734 if( XGetWindowProperty( m_pDisplay,
735 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
736 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
737 0, 1,
738 False,
739 XA_WINDOW,
740 &aRealType,
741 &nFormat,
742 &nItems,
743 &nBytesLeft,
744 &pProperty ) == 0
745 && aRealType == XA_WINDOW
746 && nFormat == 32
747 && nItems != 0
750 ::Window aWMChild = *reinterpret_cast< ::Window* >(pProperty);
751 XFree( pProperty );
752 pProperty = nullptr;
753 GetGenericUnixSalData()->ErrorTrapPush();
754 if( XGetWindowProperty( m_pDisplay,
755 aWMChild,
756 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
757 0, 1,
758 False,
759 XA_WINDOW,
760 &aRealType,
761 &nFormat,
762 &nItems,
763 &nBytesLeft,
764 &pProperty ) == 0
765 && aRealType == XA_WINDOW
766 && nFormat == 32
767 && nItems != 0 )
769 if ( ! GetGenericUnixSalData()->ErrorTrapPop( false ) )
771 GetGenericUnixSalData()->ErrorTrapPush();
772 ::Window aCheckWindow = *reinterpret_cast< ::Window* >(pProperty);
773 XFree( pProperty );
774 pProperty = nullptr;
775 if( aCheckWindow == aWMChild )
777 bNetWM = true;
778 // get name of WM
779 m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
780 if( XGetWindowProperty( m_pDisplay,
781 aWMChild,
782 m_aWMAtoms[ NET_WM_NAME ],
783 0, 256,
784 False,
785 AnyPropertyType, /* m_aWMAtoms[ UTF8_STRING ],*/
786 &aRealType,
787 &nFormat,
788 &nItems,
789 &nBytesLeft,
790 &pProperty ) == 0
791 && nItems != 0
794 if (aRealType == m_aWMAtoms[ UTF8_STRING ])
795 m_aWMName = OUString( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_UTF8 );
796 else if (aRealType == XA_STRING)
797 m_aWMName = OUString( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_ISO_8859_1 );
799 XFree( pProperty );
800 pProperty = nullptr;
802 else if( pProperty )
804 XFree( pProperty );
805 pProperty = nullptr;
808 // if this is metacity, check for version to enable a legacy workaround
809 if( m_aWMName == "Metacity" )
811 int nVersionMajor = 0, nVersionMinor = 0;
812 Atom nVersionAtom = XInternAtom( m_pDisplay, "_METACITY_VERSION", True );
813 if( nVersionAtom )
815 if( XGetWindowProperty( m_pDisplay,
816 aWMChild,
817 nVersionAtom,
818 0, 256,
819 False,
820 m_aWMAtoms[ UTF8_STRING ],
821 &aRealType,
822 &nFormat,
823 &nItems,
824 &nBytesLeft,
825 &pProperty ) == 0
826 && nItems != 0
829 OUString aMetaVersion( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_UTF8 );
830 sal_Int32 nIdx {0};
831 nVersionMajor = aMetaVersion.getToken(0, '.', nIdx).toInt32();
832 nVersionMinor = aMetaVersion.getToken(0, '.', nIdx).toInt32();
834 if( pProperty )
836 XFree( pProperty );
837 pProperty = nullptr;
840 if( nVersionMajor < 2 || (nVersionMajor == 2 && nVersionMinor < 12) )
841 m_bLegacyPartialFullscreen = true;
845 else
847 if( pProperty )
849 XFree( pProperty );
850 pProperty = nullptr;
852 GetGenericUnixSalData()->ErrorTrapPush();
856 GetGenericUnixSalData()->ErrorTrapPop();
858 else if( pProperty )
860 XFree( pProperty );
861 pProperty = nullptr;
864 return bNetWM;
867 bool WMAdaptor::getWMshouldSwitchWorkspace() const
869 if( ! m_bWMshouldSwitchWorkspaceInit )
871 WMAdaptor * pWMA = const_cast<WMAdaptor*>(this);
873 pWMA->m_bWMshouldSwitchWorkspace = true;
874 vcl::SettingsConfigItem* pItem = vcl::SettingsConfigItem::get();
875 OUString aSetting( pItem->getValue( "WM",
876 "ShouldSwitchWorkspace" ) );
877 if( aSetting.isEmpty() )
879 if( m_aWMName == "awesome" )
881 pWMA->m_bWMshouldSwitchWorkspace = false;
884 else
885 pWMA->m_bWMshouldSwitchWorkspace = aSetting.toBoolean();
886 pWMA->m_bWMshouldSwitchWorkspaceInit = true;
888 return m_bWMshouldSwitchWorkspace;
892 * WMAdaptor::isValid()
894 bool WMAdaptor::isValid() const
896 return true;
900 * NetWMAdaptor::isValid()
902 bool NetWMAdaptor::isValid() const
904 // some necessary sanity checks; there are WMs out there
905 // which implement some of the WM hints spec without
906 // real functionality
907 return
908 m_aWMAtoms[ NET_SUPPORTED ]
909 && m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]
910 && m_aWMAtoms[ NET_WM_NAME ]
911 && m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ]
912 && m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ]
917 * GnomeWMAdaptor::isValid()
919 bool GnomeWMAdaptor::isValid() const
921 return m_bValid;
925 * WMAdaptor::initAtoms
928 void WMAdaptor::initAtoms()
930 // get basic atoms
931 for(const WMAdaptorProtocol & i : aAtomTab)
932 m_aWMAtoms[ i.nProtocol ] = XInternAtom( m_pDisplay, i.pProtocol, False );
933 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] = XInternAtom( m_pDisplay, "_NET_SUPPORTING_WM_CHECK", True );
934 m_aWMAtoms[ NET_WM_NAME ] = XInternAtom( m_pDisplay, "_NET_WM_NAME", True );
938 * NetWMAdaptor::initAtoms
941 void NetWMAdaptor::initAtoms()
943 WMAdaptor::initAtoms();
945 m_aWMAtoms[ NET_SUPPORTED ] = XInternAtom( m_pDisplay, "_NET_SUPPORTED", True );
949 * GnomeWMAdaptor::initAtoms
952 void GnomeWMAdaptor::initAtoms()
954 WMAdaptor::initAtoms();
956 m_aWMAtoms[ WIN_PROTOCOLS ] = XInternAtom( m_pDisplay, "_WIN_PROTOCOLS", True );
957 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] = XInternAtom( m_pDisplay, "_WIN_SUPPORTING_WM_CHECK", True );
961 * WMAdaptor::setWMName
962 * sets WM_NAME
963 * WM_ICON_NAME
966 void WMAdaptor::setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const
968 OString aTitle(OUStringToOString(rWMName,
969 osl_getThreadTextEncoding()));
971 OString aWMLocale;
972 rtl_Locale* pLocale = nullptr;
973 osl_getProcessLocale( &pLocale );
974 if( pLocale )
976 OUString aLocaleString( LanguageTag( *pLocale).getGlibcLocaleString( OUString()));
977 aWMLocale = OUStringToOString( aLocaleString, RTL_TEXTENCODING_ISO_8859_1 );
979 else
981 static const char* pLang = getenv( "LANG" );
982 aWMLocale = pLang ? pLang : "C";
985 char* pT = const_cast<char*>(aTitle.getStr());
986 XTextProperty aProp = { nullptr, None, 0, 0 };
987 XmbTextListToTextProperty( m_pDisplay,
988 &pT,
990 XStdICCTextStyle,
991 &aProp );
993 unsigned char const * pData = aProp.nitems ? aProp.value : reinterpret_cast<unsigned char const *>(aTitle.getStr());
994 Atom nType = aProp.nitems ? aProp.encoding : XA_STRING;
995 int nFormat = aProp.nitems ? aProp.format : 8;
996 int nBytes = aProp.nitems ? aProp.nitems : aTitle.getLength();
997 const SystemEnvData* pEnv = pFrame->GetSystemData();
998 XChangeProperty( m_pDisplay,
999 static_cast<::Window>(pEnv->aShellWindow),
1000 XA_WM_NAME,
1001 nType,
1002 nFormat,
1003 PropModeReplace,
1004 pData,
1005 nBytes );
1006 XChangeProperty( m_pDisplay,
1007 static_cast<::Window>(pEnv->aShellWindow),
1008 XA_WM_ICON_NAME,
1009 nType,
1010 nFormat,
1011 PropModeReplace,
1012 pData,
1013 nBytes );
1014 XChangeProperty( m_pDisplay,
1015 static_cast<::Window>(pEnv->aShellWindow),
1016 m_aWMAtoms[ WM_LOCALE_NAME ],
1017 XA_STRING,
1019 PropModeReplace,
1020 reinterpret_cast<unsigned char const *>(aWMLocale.getStr()),
1021 aWMLocale.getLength() );
1022 if (aProp.value != nullptr)
1023 XFree( aProp.value );
1027 * NetWMAdaptor::setWMName
1028 * sets WM_NAME
1029 * _NET_WM_NAME
1030 * WM_ICON_NAME
1031 * _NET_WM_ICON_NAME
1033 void NetWMAdaptor::setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const
1035 WMAdaptor::setWMName( pFrame, rWMName );
1037 OString aTitle(OUStringToOString(rWMName, RTL_TEXTENCODING_UTF8));
1038 const SystemEnvData* pEnv = pFrame->GetSystemData();
1039 if( m_aWMAtoms[ NET_WM_NAME ] )
1040 XChangeProperty( m_pDisplay,
1041 static_cast<::Window>(pEnv->aShellWindow),
1042 m_aWMAtoms[ NET_WM_NAME ],
1043 m_aWMAtoms[ UTF8_STRING ],
1045 PropModeReplace,
1046 reinterpret_cast<unsigned char const *>(aTitle.getStr()),
1047 aTitle.getLength() );
1048 if( m_aWMAtoms[ NET_WM_ICON_NAME ] )
1049 XChangeProperty( m_pDisplay,
1050 static_cast<::Window>(pEnv->aShellWindow),
1051 m_aWMAtoms[ NET_WM_ICON_NAME ],
1052 m_aWMAtoms[ UTF8_STRING ],
1054 PropModeReplace,
1055 reinterpret_cast<unsigned char const *>(aTitle.getStr()),
1056 aTitle.getLength() );
1060 * NetWMAdaptor::setNetWMState
1061 * sets _NET_WM_STATE
1063 void NetWMAdaptor::setNetWMState( X11SalFrame* pFrame ) const
1065 if( !(m_aWMAtoms[ NET_WM_STATE ]) )
1066 return;
1068 Atom aStateAtoms[ 10 ];
1069 int nStateAtoms = 0;
1071 // set NET_WM_STATE_MODAL
1072 if( pFrame->mbMaximizedVert
1073 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
1074 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1075 if( pFrame->mbMaximizedHorz
1076 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
1077 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1078 if( pFrame->bAlwaysOnTop_ && m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
1079 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1080 if( pFrame->mbShaded && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
1081 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SHADED ];
1082 if( pFrame->mbFullScreen && m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
1083 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
1084 if( pFrame->meWindowType == WMWindowType::Utility && m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ] )
1085 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];
1087 if( nStateAtoms )
1089 XChangeProperty( m_pDisplay,
1090 pFrame->GetShellWindow(),
1091 m_aWMAtoms[ NET_WM_STATE ],
1092 XA_ATOM,
1094 PropModeReplace,
1095 reinterpret_cast<unsigned char*>(aStateAtoms),
1096 nStateAtoms
1099 else
1100 XDeleteProperty( m_pDisplay,
1101 pFrame->GetShellWindow(),
1102 m_aWMAtoms[ NET_WM_STATE ] );
1103 if( !pFrame->mbMaximizedHorz
1104 || !pFrame->mbMaximizedVert
1105 || ( pFrame->nStyle_ & SalFrameStyleFlags::SIZEABLE ) )
1106 return;
1109 * for maximizing use NorthWestGravity (including decoration)
1111 XSizeHints hints;
1112 tools::Long supplied;
1113 bool bHint = false;
1114 if( XGetWMNormalHints( m_pDisplay,
1115 pFrame->GetShellWindow(),
1116 &hints,
1117 &supplied ) )
1119 bHint = true;
1120 hints.flags |= PWinGravity;
1121 hints.win_gravity = NorthWestGravity;
1122 XSetWMNormalHints( m_pDisplay,
1123 pFrame->GetShellWindow(),
1124 &hints );
1125 XSync( m_pDisplay, False );
1128 // SetPosSize necessary to set width/height, min/max w/h
1129 sal_Int32 nCurrent = 0;
1131 * get current desktop here if work areas have different size
1132 * (does this happen on any platform ?)
1134 if( ! m_bEqualWorkAreas )
1136 nCurrent = getCurrentWorkArea();
1137 if( nCurrent < 0 )
1138 nCurrent = 0;
1140 tools::Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1141 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1142 aPosSize = tools::Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1143 aPosSize.Top() + rGeom.nTopDecoration ),
1144 Size( aPosSize.GetWidth()
1145 - rGeom.nLeftDecoration
1146 - rGeom.nRightDecoration,
1147 aPosSize.GetHeight()
1148 - rGeom.nTopDecoration
1149 - rGeom.nBottomDecoration )
1151 pFrame->SetPosSize( aPosSize );
1154 * reset gravity hint to static gravity
1155 * (this should not move window according to ICCCM)
1157 if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1159 hints.win_gravity = StaticGravity;
1160 XSetWMNormalHints( m_pDisplay,
1161 pFrame->GetShellWindow(),
1162 &hints );
1167 * GnomeWMAdaptor::setNetWMState
1168 * sets _WIN_STATE
1170 void GnomeWMAdaptor::setGnomeWMState( X11SalFrame* pFrame ) const
1172 if( !(m_aWMAtoms[ WIN_STATE ]) )
1173 return;
1175 sal_uInt32 nWinWMState = 0;
1177 if( pFrame->mbMaximizedVert )
1178 nWinWMState |= 1 << 2;
1179 if( pFrame->mbMaximizedHorz )
1180 nWinWMState |= 1 << 3;
1181 if( pFrame->mbShaded )
1182 nWinWMState |= 1 << 5;
1184 XChangeProperty( m_pDisplay,
1185 pFrame->GetShellWindow(),
1186 m_aWMAtoms[ WIN_STATE ],
1187 XA_CARDINAL,
1189 PropModeReplace,
1190 reinterpret_cast<unsigned char*>(&nWinWMState),
1193 if( !pFrame->mbMaximizedHorz
1194 || !pFrame->mbMaximizedVert
1195 || ( pFrame->nStyle_ & SalFrameStyleFlags::SIZEABLE ) )
1196 return;
1199 * for maximizing use NorthWestGravity (including decoration)
1201 XSizeHints hints;
1202 tools::Long supplied;
1203 bool bHint = false;
1204 if( XGetWMNormalHints( m_pDisplay,
1205 pFrame->GetShellWindow(),
1206 &hints,
1207 &supplied ) )
1209 bHint = true;
1210 hints.flags |= PWinGravity;
1211 hints.win_gravity = NorthWestGravity;
1212 XSetWMNormalHints( m_pDisplay,
1213 pFrame->GetShellWindow(),
1214 &hints );
1215 XSync( m_pDisplay, False );
1218 // SetPosSize necessary to set width/height, min/max w/h
1219 sal_Int32 nCurrent = 0;
1221 * get current desktop here if work areas have different size
1222 * (does this happen on any platform ?)
1224 if( ! m_bEqualWorkAreas )
1226 nCurrent = getCurrentWorkArea();
1227 if( nCurrent < 0 )
1228 nCurrent = 0;
1230 tools::Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1231 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1232 aPosSize = tools::Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1233 aPosSize.Top() + rGeom.nTopDecoration ),
1234 Size( aPosSize.GetWidth()
1235 - rGeom.nLeftDecoration
1236 - rGeom.nRightDecoration,
1237 aPosSize.GetHeight()
1238 - rGeom.nTopDecoration
1239 - rGeom.nBottomDecoration )
1241 pFrame->SetPosSize( aPosSize );
1244 * reset gravity hint to static gravity
1245 * (this should not move window according to ICCCM)
1247 if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1249 hints.win_gravity = StaticGravity;
1250 XSetWMNormalHints( m_pDisplay,
1251 pFrame->GetShellWindow(),
1252 &hints );
1257 * WMAdaptor::setFrameDecoration
1258 * sets _MOTIF_WM_HINTS
1259 * WM_TRANSIENT_FOR
1262 void WMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1264 pFrame->meWindowType = eType;
1266 if( ! pFrame->mbFullScreen )
1268 // set mwm hints
1269 struct _mwmhints {
1270 unsigned long flags, func, deco;
1271 tools::Long input_mode;
1272 unsigned long status;
1273 } aHint;
1275 aHint.flags = 15; /* flags for functions, decoration, input mode and status */
1276 aHint.deco = 0;
1277 aHint.func = 1 << 2;
1278 aHint.status = 0;
1279 aHint.input_mode = 0;
1281 // evaluate decoration flags
1282 if( nDecorationFlags & decoration_All )
1284 aHint.deco = 1;
1285 aHint.func = 1;
1287 else
1289 if( nDecorationFlags & decoration_Title )
1290 aHint.deco |= 1 << 3;
1291 if( nDecorationFlags & decoration_Border )
1292 aHint.deco |= 1 << 1;
1293 if( nDecorationFlags & decoration_Resize )
1295 aHint.deco |= 1 << 2;
1296 aHint.func |= 1 << 1;
1298 if( nDecorationFlags & decoration_MinimizeBtn )
1300 aHint.deco |= 1 << 5;
1301 aHint.func |= 1 << 3;
1303 if( nDecorationFlags & decoration_MaximizeBtn )
1305 aHint.deco |= 1 << 6;
1306 aHint.func |= 1 << 4;
1308 if( nDecorationFlags & decoration_CloseBtn )
1310 aHint.deco |= 1 << 4;
1311 aHint.func |= 1 << 5;
1315 // set the hint
1316 XChangeProperty( m_pDisplay,
1317 pFrame->GetShellWindow(),
1318 m_aWMAtoms[ MOTIF_WM_HINTS ],
1319 m_aWMAtoms[ MOTIF_WM_HINTS ],
1321 PropModeReplace,
1322 reinterpret_cast<unsigned char*>(&aHint),
1323 5 );
1326 // set transientFor hint
1327 /* #91030# dtwm will not map a dialogue if the transient
1328 * window is iconified. This is deemed undesirable because
1329 * message boxes do not get mapped, so use the root as transient
1330 * instead.
1332 if( pReferenceFrame )
1334 XSetTransientForHint( m_pDisplay,
1335 pFrame->GetShellWindow(),
1336 pReferenceFrame->bMapped_ ?
1337 pReferenceFrame->GetShellWindow() :
1338 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() )
1340 if( ! pReferenceFrame->bMapped_ )
1341 pFrame->mbTransientForRoot = true;
1346 * NetWMAdaptor::setFrameDecoration
1347 * sets _MOTIF_WM_HINTS
1348 * _NET_WM_WINDOW_TYPE
1349 * _NET_WM_STATE
1350 * WM_TRANSIENT_FOR
1353 void NetWMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1355 WMAdaptor::setFrameTypeAndDecoration( pFrame, eType, nDecorationFlags, pReferenceFrame );
1357 setNetWMState( pFrame );
1359 // set NET_WM_WINDOW_TYPE
1360 if( m_aWMAtoms[ NET_WM_WINDOW_TYPE ] )
1362 Atom aWindowTypes[4];
1363 int nWindowTypes = 0;
1364 switch( eType )
1366 case WMWindowType::Utility:
1367 aWindowTypes[nWindowTypes++] =
1368 m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] ?
1369 m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] :
1370 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1371 break;
1372 case WMWindowType::ModelessDialogue:
1373 aWindowTypes[nWindowTypes++] =
1374 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1375 break;
1376 case WMWindowType::Splash:
1377 aWindowTypes[nWindowTypes++] =
1378 m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] ?
1379 m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] :
1380 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1381 break;
1382 case WMWindowType::Toolbar:
1383 if( m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ] )
1384 aWindowTypes[nWindowTypes++] = m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ];
1385 aWindowTypes[nWindowTypes++] =
1386 m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] ?
1387 m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] :
1388 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1389 break;
1390 case WMWindowType::Dock:
1391 aWindowTypes[nWindowTypes++] =
1392 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] ?
1393 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] :
1394 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1395 break;
1396 default:
1397 aWindowTypes[nWindowTypes++] = m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1398 break;
1400 XChangeProperty( m_pDisplay,
1401 pFrame->GetShellWindow(),
1402 m_aWMAtoms[ NET_WM_WINDOW_TYPE ],
1403 XA_ATOM,
1405 PropModeReplace,
1406 reinterpret_cast<unsigned char*>(aWindowTypes),
1407 nWindowTypes );
1409 if( ( eType == WMWindowType::ModelessDialogue )
1410 && ! pReferenceFrame )
1412 XSetTransientForHint( m_pDisplay,
1413 pFrame->GetShellWindow(),
1414 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ) );
1415 pFrame->mbTransientForRoot = true;
1420 * WMAdaptor::maximizeFrame
1423 void WMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1425 pFrame->mbMaximizedVert = bVertical;
1426 pFrame->mbMaximizedHorz = bHorizontal;
1428 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1430 // discard pending configure notifies for this frame
1431 XSync( m_pDisplay, False );
1432 XEvent aDiscard;
1433 while( XCheckTypedWindowEvent( m_pDisplay,
1434 pFrame->GetShellWindow(),
1435 ConfigureNotify,
1436 &aDiscard ) )
1438 while( XCheckTypedWindowEvent( m_pDisplay,
1439 pFrame->GetWindow(),
1440 ConfigureNotify,
1441 &aDiscard ) )
1444 if( bHorizontal || bVertical )
1446 Size aScreenSize( m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() ) );
1447 Point aTL( rGeom.nLeftDecoration, rGeom.nTopDecoration );
1448 if( m_pSalDisplay->IsXinerama() )
1450 Point aMed( aTL.X() + rGeom.nWidth/2, aTL.Y() + rGeom.nHeight/2 );
1451 const std::vector< tools::Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
1452 for(const auto & rScreen : rScreens)
1453 if( rScreen.IsInside( aMed ) )
1455 aTL += rScreen.TopLeft();
1456 aScreenSize = rScreen.GetSize();
1457 break;
1460 tools::Rectangle aTarget( aTL,
1461 Size( aScreenSize.Width() - rGeom.nLeftDecoration - rGeom.nTopDecoration,
1462 aScreenSize.Height() - rGeom.nTopDecoration - rGeom.nBottomDecoration )
1464 if( ! bHorizontal )
1466 aTarget.SetSize(
1467 Size(
1468 pFrame->maRestorePosSize.IsEmpty() ?
1469 rGeom.nWidth : pFrame->maRestorePosSize.GetWidth(),
1470 aTarget.GetHeight()
1473 aTarget.SetLeft(
1474 pFrame->maRestorePosSize.IsEmpty() ?
1475 rGeom.nX : pFrame->maRestorePosSize.Left() );
1477 else if( ! bVertical )
1479 aTarget.SetSize(
1480 Size(
1481 aTarget.GetWidth(),
1482 pFrame->maRestorePosSize.IsEmpty() ?
1483 rGeom.nHeight : pFrame->maRestorePosSize.GetHeight()
1486 aTarget.SetTop(
1487 pFrame->maRestorePosSize.IsEmpty() ?
1488 rGeom.nY : pFrame->maRestorePosSize.Top() );
1491 tools::Rectangle aRestore( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1492 if( pFrame->bMapped_ )
1494 XSetInputFocus( m_pDisplay,
1495 pFrame->GetShellWindow(),
1496 RevertToNone,
1497 CurrentTime
1501 if( pFrame->maRestorePosSize.IsEmpty() )
1502 pFrame->maRestorePosSize = aRestore;
1504 pFrame->SetPosSize( aTarget );
1505 pFrame->nWidth_ = aTarget.GetWidth();
1506 pFrame->nHeight_ = aTarget.GetHeight();
1507 XRaiseWindow( m_pDisplay,
1508 pFrame->GetShellWindow()
1510 if( pFrame->GetStackingWindow() )
1511 XRaiseWindow( m_pDisplay,
1512 pFrame->GetStackingWindow()
1516 else
1518 pFrame->SetPosSize( pFrame->maRestorePosSize );
1519 pFrame->maRestorePosSize = tools::Rectangle();
1520 pFrame->nWidth_ = rGeom.nWidth;
1521 pFrame->nHeight_ = rGeom.nHeight;
1526 * NetWMAdaptor::maximizeFrame
1527 * changes _NET_WM_STATE by sending a client message
1530 void NetWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1532 pFrame->mbMaximizedVert = bVertical;
1533 pFrame->mbMaximizedHorz = bHorizontal;
1535 if( m_aWMAtoms[ NET_WM_STATE ]
1536 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ]
1537 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ]
1538 && ( pFrame->nStyle_ & ~SalFrameStyleFlags::DEFAULT )
1541 if( pFrame->bMapped_ )
1543 // window already mapped, send WM a message
1544 XEvent aEvent;
1545 aEvent.type = ClientMessage;
1546 aEvent.xclient.display = m_pDisplay;
1547 aEvent.xclient.window = pFrame->GetShellWindow();
1548 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
1549 aEvent.xclient.format = 32;
1550 aEvent.xclient.data.l[0] = bHorizontal ? 1 : 0;
1551 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1552 aEvent.xclient.data.l[2] = bHorizontal == bVertical ? m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] : 0;
1553 aEvent.xclient.data.l[3] = 0;
1554 aEvent.xclient.data.l[4] = 0;
1555 XSendEvent( m_pDisplay,
1556 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1557 False,
1558 SubstructureNotifyMask | SubstructureRedirectMask,
1559 &aEvent
1561 if( bHorizontal != bVertical )
1563 aEvent.xclient.data.l[0]= bVertical ? 1 : 0;
1564 aEvent.xclient.data.l[1]= m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1565 aEvent.xclient.data.l[2]= 0;
1566 XSendEvent( m_pDisplay,
1567 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1568 False,
1569 SubstructureNotifyMask | SubstructureRedirectMask,
1570 &aEvent
1574 else
1576 // window not mapped yet, set _NET_WM_STATE directly
1577 setNetWMState( pFrame );
1579 if( !bHorizontal && !bVertical )
1580 pFrame->maRestorePosSize = tools::Rectangle();
1581 else if( pFrame->maRestorePosSize.IsEmpty() )
1583 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1584 pFrame->maRestorePosSize =
1585 tools::Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1588 else
1589 WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1593 * GnomeWMAdaptor::maximizeFrame
1594 * changes _WIN_STATE by sending a client message
1597 void GnomeWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1599 pFrame->mbMaximizedVert = bVertical;
1600 pFrame->mbMaximizedHorz = bHorizontal;
1602 if( m_aWMAtoms[ WIN_STATE ]
1603 && ( pFrame->nStyle_ & ~SalFrameStyleFlags::DEFAULT )
1606 if( pFrame->bMapped_ )
1608 // window already mapped, send WM a message
1609 XEvent aEvent;
1610 aEvent.type = ClientMessage;
1611 aEvent.xclient.display = m_pDisplay;
1612 aEvent.xclient.window = pFrame->GetShellWindow();
1613 aEvent.xclient.message_type = m_aWMAtoms[ WIN_STATE ];
1614 aEvent.xclient.format = 32;
1615 aEvent.xclient.data.l[0] = (1<<2)|(1<<3);
1616 aEvent.xclient.data.l[1] =
1617 (bVertical ? (1<<2) : 0)
1618 | (bHorizontal ? (1<<3) : 0);
1619 aEvent.xclient.data.l[2] = 0;
1620 aEvent.xclient.data.l[3] = 0;
1621 aEvent.xclient.data.l[4] = 0;
1622 XSendEvent( m_pDisplay,
1623 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1624 False,
1625 SubstructureNotifyMask,
1626 &aEvent
1629 else
1630 // window not mapped yet, set _WIN_STATE directly
1631 setGnomeWMState( pFrame );
1633 if( !bHorizontal && !bVertical )
1634 pFrame->maRestorePosSize = tools::Rectangle();
1635 else if( pFrame->maRestorePosSize.IsEmpty() )
1637 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1638 pFrame->maRestorePosSize =
1639 tools::Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1642 else
1643 WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1647 * WMAdaptor::enableAlwaysOnTop
1649 void WMAdaptor::enableAlwaysOnTop( X11SalFrame*, bool /*bEnable*/ ) const
1654 * NetWMAdaptor::enableAlwaysOnTop
1656 void NetWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1658 pFrame->bAlwaysOnTop_ = bEnable;
1659 if( !(m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ]) )
1660 return;
1662 if( pFrame->bMapped_ )
1664 // window already mapped, send WM a message
1665 XEvent aEvent;
1666 aEvent.type = ClientMessage;
1667 aEvent.xclient.display = m_pDisplay;
1668 aEvent.xclient.window = pFrame->GetShellWindow();
1669 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
1670 aEvent.xclient.format = 32;
1671 aEvent.xclient.data.l[0] = bEnable ? 1 : 0;
1672 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1673 aEvent.xclient.data.l[2] = 0;
1674 aEvent.xclient.data.l[3] = 0;
1675 aEvent.xclient.data.l[4] = 0;
1676 XSendEvent( m_pDisplay,
1677 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1678 False,
1679 SubstructureNotifyMask | SubstructureRedirectMask,
1680 &aEvent
1683 else
1684 setNetWMState( pFrame );
1688 * GnomeWMAdaptor::enableAlwaysOnTop
1690 void GnomeWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1692 pFrame->bAlwaysOnTop_ = bEnable;
1693 if( !(m_aWMAtoms[ WIN_LAYER ]) )
1694 return;
1696 if( pFrame->bMapped_ )
1698 // window already mapped, send WM a message
1699 XEvent aEvent;
1700 aEvent.type = ClientMessage;
1701 aEvent.xclient.display = m_pDisplay;
1702 aEvent.xclient.window = pFrame->GetShellWindow();
1703 aEvent.xclient.message_type = m_aWMAtoms[ WIN_LAYER ];
1704 aEvent.xclient.format = 32;
1705 aEvent.xclient.data.l[0] = bEnable ? 6 : 4;
1706 aEvent.xclient.data.l[1] = 0;
1707 aEvent.xclient.data.l[2] = 0;
1708 aEvent.xclient.data.l[3] = 0;
1709 aEvent.xclient.data.l[4] = 0;
1710 XSendEvent( m_pDisplay,
1711 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1712 False,
1713 SubstructureNotifyMask | SubstructureRedirectMask,
1714 &aEvent
1717 else
1719 sal_uInt32 nNewLayer = bEnable ? 6 : 4;
1720 XChangeProperty( m_pDisplay,
1721 pFrame->GetShellWindow(),
1722 m_aWMAtoms[ WIN_LAYER ],
1723 XA_CARDINAL,
1725 PropModeReplace,
1726 reinterpret_cast<unsigned char*>(&nNewLayer),
1733 * WMAdaptor::changeReferenceFrame
1735 void WMAdaptor::changeReferenceFrame( X11SalFrame* pFrame, X11SalFrame const * pReferenceFrame ) const
1737 if( ( pFrame->nStyle_ & SalFrameStyleFlags::PLUG )
1738 || pFrame->IsOverrideRedirect()
1739 || pFrame->IsFloatGrabWindow()
1741 return;
1743 ::Window aTransient = pFrame->pDisplay_->GetRootWindow( pFrame->GetScreenNumber() );
1744 pFrame->mbTransientForRoot = true;
1745 if( pReferenceFrame )
1747 aTransient = pReferenceFrame->GetShellWindow();
1748 pFrame->mbTransientForRoot = false;
1750 XSetTransientForHint( m_pDisplay,
1751 pFrame->GetShellWindow(),
1752 aTransient );
1756 * WMAdaptor::handlePropertyNotify
1758 int WMAdaptor::handlePropertyNotify( X11SalFrame*, XPropertyEvent* ) const
1760 return 0;
1764 * NetWMAdaptor::handlePropertyNotify
1766 int NetWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
1768 int nHandled = 1;
1769 if( pEvent->atom == m_aWMAtoms[ NET_WM_STATE ] )
1771 pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
1772 pFrame->mbShaded = false;
1774 if( pEvent->state == PropertyNewValue )
1776 Atom nType, *pStates;
1777 int nFormat;
1778 unsigned long nItems, nBytesLeft;
1779 unsigned char* pData = nullptr;
1780 tools::Long nOffset = 0;
1783 XGetWindowProperty( m_pDisplay,
1784 pEvent->window,
1785 m_aWMAtoms[ NET_WM_STATE ],
1786 nOffset, 64,
1787 False,
1788 XA_ATOM,
1789 &nType,
1790 &nFormat,
1791 &nItems, &nBytesLeft,
1792 &pData );
1793 if( pData )
1795 if( nType == XA_ATOM && nFormat == 32 && nItems > 0 )
1797 pStates = reinterpret_cast<Atom*>(pData);
1798 for( unsigned long i = 0; i < nItems; i++ )
1800 if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
1801 pFrame->mbMaximizedVert = true;
1802 else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
1803 pFrame->mbMaximizedHorz = true;
1804 else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_SHADED ] && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
1805 pFrame->mbShaded = true;
1808 XFree( pData );
1809 pData = nullptr;
1810 nOffset += nItems * nFormat / 32;
1812 else
1813 break;
1814 } while( nBytesLeft > 0 );
1817 if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
1818 pFrame->maRestorePosSize = tools::Rectangle();
1819 else
1821 const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
1822 // the current geometry may already be changed by the corresponding
1823 // ConfigureNotify, but this cannot be helped
1824 pFrame->maRestorePosSize =
1825 tools::Rectangle( Point( rGeom.nX, rGeom.nY ),
1826 Size( rGeom.nWidth, rGeom.nHeight ) );
1829 else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
1831 pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
1833 else
1834 nHandled = 0;
1836 return nHandled;
1840 * GnomeWMAdaptor::handlePropertyNotify
1842 int GnomeWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
1844 int nHandled = 1;
1845 if( pEvent->atom == m_aWMAtoms[ WIN_STATE ] )
1847 pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
1848 pFrame->mbShaded = false;
1850 if( pEvent->state == PropertyNewValue )
1852 Atom nType;
1853 int nFormat = 0;
1854 unsigned long nItems = 0;
1855 unsigned long nBytesLeft = 0;
1856 unsigned char* pData = nullptr;
1857 XGetWindowProperty( m_pDisplay,
1858 pEvent->window,
1859 m_aWMAtoms[ WIN_STATE ],
1860 0, 1,
1861 False,
1862 XA_CARDINAL,
1863 &nType,
1864 &nFormat,
1865 &nItems, &nBytesLeft,
1866 &pData );
1867 if( pData )
1869 if( nType == XA_CARDINAL && nFormat == 32 && nItems == 1 )
1871 sal_uInt32 nWinState = *reinterpret_cast<sal_uInt32*>(pData);
1872 if( nWinState & (1<<2) )
1873 pFrame->mbMaximizedVert = true;
1874 if( nWinState & (1<<3) )
1875 pFrame->mbMaximizedHorz = true;
1876 if( nWinState & (1<<5) )
1877 pFrame->mbShaded = true;
1879 XFree( pData );
1883 if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
1884 pFrame->maRestorePosSize = tools::Rectangle();
1885 else
1887 const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
1888 // the current geometry may already be changed by the corresponding
1889 // ConfigureNotify, but this cannot be helped
1890 pFrame->maRestorePosSize =
1891 tools::Rectangle( Point( rGeom.nX, rGeom.nY ),
1892 Size( rGeom.nWidth, rGeom.nHeight ) );
1895 else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
1897 pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
1899 else
1900 nHandled = 0;
1902 return nHandled;
1906 * WMAdaptor::shade
1908 void WMAdaptor::shade( X11SalFrame*, bool /*bToShaded*/ ) const
1913 * NetWMAdaptor::shade
1915 void NetWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
1917 if( !(m_aWMAtoms[ NET_WM_STATE ]
1918 && m_aWMAtoms[ NET_WM_STATE_SHADED ]
1919 && ( pFrame->nStyle_ & ~SalFrameStyleFlags::DEFAULT ))
1921 return;
1923 pFrame->mbShaded = bToShaded;
1924 if( pFrame->bMapped_ )
1926 // window already mapped, send WM a message
1927 XEvent aEvent;
1928 aEvent.type = ClientMessage;
1929 aEvent.xclient.display = m_pDisplay;
1930 aEvent.xclient.window = pFrame->GetShellWindow();
1931 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
1932 aEvent.xclient.format = 32;
1933 aEvent.xclient.data.l[0] = bToShaded ? 1 : 0;
1934 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_SHADED ];
1935 aEvent.xclient.data.l[2] = 0;
1936 aEvent.xclient.data.l[3] = 0;
1937 aEvent.xclient.data.l[4] = 0;
1938 XSendEvent( m_pDisplay,
1939 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1940 False,
1941 SubstructureNotifyMask | SubstructureRedirectMask,
1942 &aEvent
1945 else
1947 // window not mapped yet, set _NET_WM_STATE directly
1948 setNetWMState( pFrame );
1953 * GnomeWMAdaptor::shade
1955 void GnomeWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
1957 if( !(m_aWMAtoms[ WIN_STATE ]) )
1958 return;
1960 pFrame->mbShaded = bToShaded;
1961 if( pFrame->bMapped_ )
1963 // window already mapped, send WM a message
1964 XEvent aEvent;
1965 aEvent.type = ClientMessage;
1966 aEvent.xclient.display = m_pDisplay;
1967 aEvent.xclient.window = pFrame->GetShellWindow();
1968 aEvent.xclient.message_type = m_aWMAtoms[ WIN_STATE ];
1969 aEvent.xclient.format = 32;
1970 aEvent.xclient.data.l[0] = (1<<5);
1971 aEvent.xclient.data.l[1] = bToShaded ? (1<<5) : 0;
1972 aEvent.xclient.data.l[2] = 0;
1973 aEvent.xclient.data.l[3] = 0;
1974 aEvent.xclient.data.l[4] = 0;
1975 XSendEvent( m_pDisplay,
1976 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1977 False,
1978 SubstructureNotifyMask | SubstructureRedirectMask,
1979 &aEvent
1982 else
1983 setGnomeWMState( pFrame );
1987 * WMAdaptor::showFullScreen
1989 void WMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
1991 pFrame->mbFullScreen = bFullScreen;
1992 maximizeFrame( pFrame, bFullScreen, bFullScreen );
1996 * NetWMAdaptor::showFullScreen
1998 void NetWMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
2000 if( m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
2002 pFrame->mbFullScreen = bFullScreen;
2003 if( bFullScreen )
2005 if( m_aWMAtoms[ MOTIF_WM_HINTS ] )
2007 XDeleteProperty( m_pDisplay,
2008 pFrame->GetShellWindow(),
2009 m_aWMAtoms[ MOTIF_WM_HINTS ] );
2012 if( pFrame->bMapped_ )
2014 // window already mapped, send WM a message
2015 XEvent aEvent;
2016 aEvent.type = ClientMessage;
2017 aEvent.xclient.display = m_pDisplay;
2018 aEvent.xclient.window = pFrame->GetShellWindow();
2019 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
2020 aEvent.xclient.format = 32;
2021 aEvent.xclient.data.l[0] = bFullScreen ? 1 : 0;
2022 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
2023 aEvent.xclient.data.l[2] = 0;
2024 aEvent.xclient.data.l[3] = 0;
2025 aEvent.xclient.data.l[4] = 0;
2026 XSendEvent( m_pDisplay,
2027 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2028 False,
2029 SubstructureNotifyMask | SubstructureRedirectMask,
2030 &aEvent
2033 else
2035 // window not mapped yet, set _NET_WM_STATE directly
2036 setNetWMState( pFrame );
2038 // #i42750# guess size before resize event shows up
2039 if( bFullScreen )
2041 if( m_pSalDisplay->IsXinerama() )
2043 ::Window aRoot, aChild;
2044 int root_x = 0, root_y = 0, lx, ly;
2045 unsigned int mask;
2046 XQueryPointer( m_pDisplay,
2047 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2048 &aRoot, &aChild,
2049 &root_x, &root_y, &lx, &ly, &mask );
2050 const std::vector< tools::Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
2051 Point aMousePoint( root_x, root_y );
2052 for(const auto & rScreen : rScreens)
2054 if( rScreen.IsInside( aMousePoint ) )
2056 pFrame->maGeometry.nX = rScreen.Left();
2057 pFrame->maGeometry.nY = rScreen.Top();
2058 pFrame->maGeometry.nWidth = rScreen.GetWidth();
2059 pFrame->maGeometry.nHeight = rScreen.GetHeight();
2060 break;
2064 else
2066 Size aSize = m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() );
2067 pFrame->maGeometry.nX = 0;
2068 pFrame->maGeometry.nY = 0;
2069 pFrame->maGeometry.nWidth = aSize.Width();
2070 pFrame->maGeometry.nHeight = aSize.Height();
2072 pFrame->CallCallback( SalEvent::MoveResize, nullptr );
2075 else WMAdaptor::showFullScreen( pFrame, bFullScreen );
2079 * WMAdaptor::getCurrentWorkArea
2081 // FIXME: multiscreen case
2082 int WMAdaptor::getCurrentWorkArea() const
2084 int nCurrent = -1;
2085 if( m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2087 Atom aRealType = None;
2088 int nFormat = 8;
2089 unsigned long nItems = 0;
2090 unsigned long nBytesLeft = 0;
2091 unsigned char* pProperty = nullptr;
2092 if( XGetWindowProperty( m_pDisplay,
2093 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
2094 m_aWMAtoms[ NET_CURRENT_DESKTOP ],
2095 0, 1,
2096 False,
2097 XA_CARDINAL,
2098 &aRealType,
2099 &nFormat,
2100 &nItems,
2101 &nBytesLeft,
2102 &pProperty ) == 0
2103 && pProperty
2106 nCurrent = int(*reinterpret_cast<sal_Int32*>(pProperty));
2107 XFree( pProperty );
2109 else if( pProperty )
2111 XFree( pProperty );
2112 pProperty = nullptr;
2115 return nCurrent;
2119 * WMAdaptor::getWindowWorkArea
2121 int WMAdaptor::getWindowWorkArea( ::Window aWindow ) const
2123 int nCurrent = -1;
2124 if( m_aWMAtoms[ NET_WM_DESKTOP ] )
2126 Atom aRealType = None;
2127 int nFormat = 8;
2128 unsigned long nItems = 0;
2129 unsigned long nBytesLeft = 0;
2130 unsigned char* pProperty = nullptr;
2131 if( XGetWindowProperty( m_pDisplay,
2132 aWindow,
2133 m_aWMAtoms[ NET_WM_DESKTOP ],
2134 0, 1,
2135 False,
2136 XA_CARDINAL,
2137 &aRealType,
2138 &nFormat,
2139 &nItems,
2140 &nBytesLeft,
2141 &pProperty ) == 0
2142 && pProperty
2145 nCurrent = int(*reinterpret_cast<sal_Int32*>(pProperty));
2146 XFree( pProperty );
2148 else if( pProperty )
2150 XFree( pProperty );
2151 pProperty = nullptr;
2154 return nCurrent;
2158 * WMAdaptor::getCurrentWorkArea
2160 // fixme: multi screen case
2161 void WMAdaptor::switchToWorkArea( int nWorkArea ) const
2163 if( ! getWMshouldSwitchWorkspace() )
2164 return;
2166 if( !m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2167 return;
2169 XEvent aEvent;
2170 aEvent.type = ClientMessage;
2171 aEvent.xclient.display = m_pDisplay;
2172 aEvent.xclient.window = m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() );
2173 aEvent.xclient.message_type = m_aWMAtoms[ NET_CURRENT_DESKTOP ];
2174 aEvent.xclient.format = 32;
2175 aEvent.xclient.data.l[0] = nWorkArea;
2176 aEvent.xclient.data.l[1] = 0;
2177 aEvent.xclient.data.l[2] = 0;
2178 aEvent.xclient.data.l[3] = 0;
2179 aEvent.xclient.data.l[4] = 0;
2180 XSendEvent( m_pDisplay,
2181 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
2182 False,
2183 SubstructureNotifyMask | SubstructureRedirectMask,
2184 &aEvent
2190 * WMAdaptor::frameIsMapping
2192 void WMAdaptor::frameIsMapping( X11SalFrame* ) const
2197 * NetWMAdaptor::frameIsMapping
2199 void NetWMAdaptor::frameIsMapping( X11SalFrame* pFrame ) const
2201 setNetWMState( pFrame );
2205 * WMAdaptor::setUserTime
2207 void WMAdaptor::setUserTime( X11SalFrame*, tools::Long ) const
2212 * NetWMAdaptor::setUserTime
2214 void NetWMAdaptor::setUserTime( X11SalFrame* i_pFrame, tools::Long i_nUserTime ) const
2216 if( m_aWMAtoms[NET_WM_USER_TIME] )
2218 XChangeProperty( m_pDisplay,
2219 i_pFrame->GetShellWindow(),
2220 m_aWMAtoms[NET_WM_USER_TIME],
2221 XA_CARDINAL,
2223 PropModeReplace,
2224 reinterpret_cast<unsigned char*>(&i_nUserTime),
2231 * WMAdaptor::setPID
2233 void WMAdaptor::setPID( X11SalFrame const * i_pFrame ) const
2235 if( !(m_aWMAtoms[NET_WM_PID]) )
2236 return;
2238 tools::Long nPID = static_cast<tools::Long>(getpid());
2239 XChangeProperty( m_pDisplay,
2240 i_pFrame->GetShellWindow(),
2241 m_aWMAtoms[NET_WM_PID],
2242 XA_CARDINAL,
2244 PropModeReplace,
2245 reinterpret_cast<unsigned char*>(&nPID),
2251 * WMAdaptor::setClientMachine
2253 void WMAdaptor::setClientMachine( X11SalFrame const * i_pFrame ) const
2255 OString aWmClient( OUStringToOString( GetGenericUnixSalData()->GetHostname(), RTL_TEXTENCODING_ASCII_US ) );
2256 XTextProperty aClientProp = { reinterpret_cast<unsigned char *>(const_cast<char *>(aWmClient.getStr())), XA_STRING, 8, sal::static_int_cast<unsigned long>( aWmClient.getLength() ) };
2257 XSetWMClientMachine( m_pDisplay, i_pFrame->GetShellWindow(), &aClientProp );
2260 void WMAdaptor::answerPing( X11SalFrame const * i_pFrame, XClientMessageEvent const * i_pEvent ) const
2262 if( !m_aWMAtoms[NET_WM_PING] ||
2263 i_pEvent->message_type != m_aWMAtoms[ WM_PROTOCOLS ] ||
2264 static_cast<Atom>(i_pEvent->data.l[0]) != m_aWMAtoms[ NET_WM_PING ] )
2265 return;
2267 XEvent aEvent;
2268 aEvent.xclient = *i_pEvent;
2269 aEvent.xclient.window = m_pSalDisplay->GetRootWindow( i_pFrame->GetScreenNumber() );
2270 XSendEvent( m_pDisplay,
2271 m_pSalDisplay->GetRootWindow( i_pFrame->GetScreenNumber() ),
2272 False,
2273 SubstructureNotifyMask | SubstructureRedirectMask,
2274 &aEvent
2276 XFlush( m_pDisplay );
2279 void WMAdaptor::activateWindow( X11SalFrame const *pFrame, Time nTimestamp )
2281 if (!pFrame->bMapped_)
2282 return;
2284 XEvent aEvent;
2286 aEvent.xclient.type = ClientMessage;
2287 aEvent.xclient.window = pFrame->GetShellWindow();
2288 aEvent.xclient.message_type = m_aWMAtoms[ NET_ACTIVE_WINDOW ];
2289 aEvent.xclient.format = 32;
2290 aEvent.xclient.data.l[0] = 1;
2291 aEvent.xclient.data.l[1] = nTimestamp;
2292 aEvent.xclient.data.l[2] = None;
2293 aEvent.xclient.data.l[3] = 0;
2294 aEvent.xclient.data.l[4] = 0;
2296 XSendEvent( m_pDisplay,
2297 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2298 False,
2299 SubstructureNotifyMask | SubstructureRedirectMask,
2300 &aEvent );
2304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */