Update ooo320-m1
[ooovba.git] / vcl / unx / source / app / wmadaptor.cxx
blobf72c4e376d887019441bc21cc05edcbe25ef8e1d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wmadaptor.cxx,v $
10 * $Revision: 1.71 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sal/alloca.h>
38 #include <wmadaptor.hxx>
39 #include <saldisp.hxx>
40 #include <salframe.h>
41 #include <vcl/salgdi.hxx>
42 #include <osl/thread.h>
43 #include <rtl/locale.h>
44 #include <osl/process.h>
46 #include <tools/prex.h>
47 #include <X11/X.h>
48 #include <X11/Xatom.h>
49 #include <X11/Xresource.h>
50 #include <tools/postx.h>
52 #if OSL_DEBUG_LEVEL > 1
53 #include <stdio.h>
54 #endif
56 namespace vcl_sal {
58 class NetWMAdaptor : public WMAdaptor
60 void setNetWMState( X11SalFrame* pFrame ) const;
61 void initAtoms();
62 virtual bool isValid() const;
63 public:
64 NetWMAdaptor( SalDisplay* );
65 virtual ~NetWMAdaptor();
67 virtual void setWMName( X11SalFrame* pFrame, const String& rWMName ) const;
68 virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const;
69 virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const;
70 virtual void setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pTransientFrame = NULL ) const;
71 virtual bool supportsICCCMPos() const;
72 virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const;
73 virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const;
74 virtual void showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const;
75 virtual void frameIsMapping( X11SalFrame* pFrame ) const;
76 virtual void setFrameStruts( X11SalFrame* pFrame,
77 int left, int right, int top, int bottom,
78 int left_start_y, int left_end_y,
79 int right_start_y, int right_end_y,
80 int top_start_x, int top_end_x,
81 int bottom_start_x, int bottom_end_x ) const;
82 virtual void setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const;
85 class GnomeWMAdaptor : public WMAdaptor
87 bool m_bValid;
89 void setGnomeWMState( X11SalFrame* pFrame ) const;
90 void initAtoms();
91 virtual bool isValid() const;
92 public:
93 GnomeWMAdaptor( SalDisplay * );
94 virtual ~GnomeWMAdaptor();
96 virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = true, bool bVertical = true ) const;
97 virtual void shade( X11SalFrame* pFrame, bool bToShaded ) const;
98 virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const;
99 virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const;
104 using namespace vcl_sal;
106 struct WMAdaptorProtocol
108 const char* pProtocol;
109 int nProtocol;
114 * table must be sorted ascending in strings
115 * since it is use with bsearch
117 static const WMAdaptorProtocol aProtocolTab[] =
119 { "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", WMAdaptor::KDE_NET_WM_WINDOW_TYPE_OVERRIDE },
120 { "_NET_CURRENT_DESKTOP", WMAdaptor::NET_CURRENT_DESKTOP },
121 { "_NET_NUMBER_OF_DESKTOPS", WMAdaptor::NET_NUMBER_OF_DESKTOPS },
122 { "_NET_WM_DESKTOP", WMAdaptor::NET_WM_DESKTOP },
123 { "_NET_WM_ICON_NAME", WMAdaptor::NET_WM_ICON_NAME },
124 { "_NET_WM_STATE", WMAdaptor::NET_WM_STATE },
125 { "_NET_WM_STATE_ABOVE", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
126 { "_NET_WM_STATE_FULLSCREEN", WMAdaptor::NET_WM_STATE_FULLSCREEN },
127 { "_NET_WM_STATE_MAXIMIZED_HORIZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ }, // common bug in e.g. older kwin and sawfish implementations
128 { "_NET_WM_STATE_MAXIMIZED_HORZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ },
129 { "_NET_WM_STATE_MAXIMIZED_VERT", WMAdaptor::NET_WM_STATE_MAXIMIZED_VERT },
130 { "_NET_WM_STATE_MODAL", WMAdaptor::NET_WM_STATE_MODAL },
131 { "_NET_WM_STATE_SHADED", WMAdaptor::NET_WM_STATE_SHADED },
132 { "_NET_WM_STATE_SKIP_PAGER", WMAdaptor::NET_WM_STATE_SKIP_PAGER },
133 { "_NET_WM_STATE_SKIP_TASKBAR", WMAdaptor::NET_WM_STATE_SKIP_TASKBAR },
134 { "_NET_WM_STATE_STAYS_ON_TOP", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
135 { "_NET_WM_STATE_STICKY", WMAdaptor::NET_WM_STATE_STICKY },
136 { "_NET_WM_STRUT", WMAdaptor::NET_WM_STRUT },
137 { "_NET_WM_STRUT_PARTIAL", WMAdaptor::NET_WM_STRUT_PARTIAL },
138 { "_NET_WM_WINDOW_TYPE", WMAdaptor::NET_WM_WINDOW_TYPE },
139 { "_NET_WM_WINDOW_TYPE_DESKTOP", WMAdaptor::NET_WM_WINDOW_TYPE_DESKTOP },
140 { "_NET_WM_WINDOW_TYPE_DIALOG", WMAdaptor::NET_WM_WINDOW_TYPE_DIALOG },
141 { "_NET_WM_WINDOW_TYPE_DOCK", WMAdaptor::NET_WM_WINDOW_TYPE_DOCK },
142 { "_NET_WM_WINDOW_TYPE_MENU", WMAdaptor::NET_WM_WINDOW_TYPE_MENU },
143 { "_NET_WM_WINDOW_TYPE_NORMAL", WMAdaptor::NET_WM_WINDOW_TYPE_NORMAL },
144 { "_NET_WM_WINDOW_TYPE_SPLASH", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH },
145 { "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH }, // bug in Metacity 2.4.1
146 { "_NET_WM_WINDOW_TYPE_TOOLBAR", WMAdaptor::NET_WM_WINDOW_TYPE_TOOLBAR },
147 { "_NET_WM_WINDOW_TYPE_UTILITY", WMAdaptor::NET_WM_WINDOW_TYPE_UTILITY },
148 { "_NET_WORKAREA", WMAdaptor::NET_WORKAREA },
149 { "_WIN_APP_STATE", WMAdaptor::WIN_APP_STATE },
150 { "_WIN_CLIENT_LIST", WMAdaptor::WIN_CLIENT_LIST },
151 { "_WIN_EXPANDED_SIZE", WMAdaptor::WIN_EXPANDED_SIZE },
152 { "_WIN_HINTS", WMAdaptor::WIN_HINTS },
153 { "_WIN_ICONS", WMAdaptor::WIN_ICONS },
154 { "_WIN_LAYER", WMAdaptor::WIN_LAYER },
155 { "_WIN_STATE", WMAdaptor::WIN_STATE },
156 { "_WIN_WORKSPACE", WMAdaptor::WIN_WORKSPACE },
157 { "_WIN_WORKSPACE_COUNT", WMAdaptor::WIN_WORKSPACE_COUNT }
161 * table containing atoms to get anyway
164 static const WMAdaptorProtocol aAtomTab[] =
166 { "WM_STATE", WMAdaptor::WM_STATE },
167 { "_MOTIF_WM_HINTS", WMAdaptor::MOTIF_WM_HINTS },
168 { "WM_PROTOCOLS", WMAdaptor::WM_PROTOCOLS },
169 { "WM_DELETE_WINDOW", WMAdaptor::WM_DELETE_WINDOW },
170 { "WM_TAKE_FOCUS", WMAdaptor::WM_TAKE_FOCUS },
171 { "WM_SAVE_YOURSELF", WMAdaptor::WM_SAVE_YOURSELF },
172 { "WM_COMMAND", WMAdaptor::WM_COMMAND },
173 { "WM_CLIENT_LEADER", WMAdaptor::WM_CLIENT_LEADER },
174 { "WM_LOCALE_NAME", WMAdaptor::WM_LOCALE_NAME },
175 { "WM_TRANSIENT_FOR", WMAdaptor::WM_TRANSIENT_FOR },
176 { "SAL_QUITEVENT", WMAdaptor::SAL_QUITEVENT },
177 { "SAL_USEREVENT", WMAdaptor::SAL_USEREVENT },
178 { "SAL_EXTTEXTEVENT", WMAdaptor::SAL_EXTTEXTEVENT },
179 { "SAL_GETTIMEEVENT", WMAdaptor::SAL_GETTIMEEVENT },
180 { "VCL_SYSTEM_SETTINGS", WMAdaptor::VCL_SYSTEM_SETTINGS },
181 { "DTWM_IS_RUNNING", WMAdaptor::DTWM_IS_RUNNING },
182 { "_XSETTINGS_SETTINGS", WMAdaptor::XSETTINGS },
183 { "_XEMBED", WMAdaptor::XEMBED },
184 { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO },
185 { "_NET_WM_USER_TIME", WMAdaptor::NET_WM_USER_TIME }
188 extern "C" {
189 static int compareProtocol( const void* pLeft, const void* pRight )
191 return strcmp( ((const WMAdaptorProtocol*)pLeft)->pProtocol, ((const WMAdaptorProtocol*)pRight)->pProtocol );
195 WMAdaptor* WMAdaptor::createWMAdaptor( SalDisplay* pSalDisplay )
197 WMAdaptor* pAdaptor = NULL;
199 // try a NetWM
200 pAdaptor = new NetWMAdaptor( pSalDisplay );
201 if( ! pAdaptor->isValid() )
202 delete pAdaptor, pAdaptor = NULL;
203 #if OSL_DEBUG_LEVEL > 1
204 else
205 fprintf( stderr, "WM supports extended WM hints\n" );
206 #endif
208 // try a GnomeWM
209 if( ! pAdaptor )
211 pAdaptor = new GnomeWMAdaptor( pSalDisplay );
212 if( ! pAdaptor->isValid() )
213 delete pAdaptor, pAdaptor = NULL;
214 #if OSL_DEBUG_LEVEL > 1
215 else
216 fprintf( stderr, "WM supports GNOME WM hints\n" );
217 #endif
220 if( ! pAdaptor )
221 pAdaptor = new WMAdaptor( pSalDisplay );
223 #if OSL_DEBUG_LEVEL > 1
224 fprintf( stderr, "Window Manager's name is \"%s\"\n",
225 ByteString( pAdaptor->getWindowManagerName(), RTL_TEXTENCODING_ISO_8859_1 ).GetBuffer() );
226 #endif
227 return pAdaptor;
232 * WMAdaptor constructor
235 WMAdaptor::WMAdaptor( SalDisplay* pDisplay ) :
236 m_pSalDisplay( pDisplay ),
237 m_bTransientBehaviour( true ),
238 m_bEnableAlwaysOnTopWorks( false ),
239 m_nWinGravity( StaticGravity ),
240 m_nInitWinGravity( StaticGravity )
242 Atom aRealType = None;
243 int nFormat = 8;
244 unsigned long nItems = 0;
245 unsigned long nBytesLeft = 0;
246 unsigned char* pProperty = NULL;
248 // default desktops
249 m_nDesktops = 1;
250 m_aWMWorkAreas = ::std::vector< Rectangle >
251 ( 1, Rectangle( Point(), m_pSalDisplay->GetScreenSize( m_pSalDisplay->GetDefaultScreenNumber() ) ) );
252 m_bEqualWorkAreas = true;
254 memset( m_aWMAtoms, 0, sizeof( m_aWMAtoms ) );
255 m_pDisplay = m_pSalDisplay->GetDisplay();
257 initAtoms();
258 getNetWmName(); // try to discover e.g. Sawfish
260 // check for dtwm running
261 if( m_aWMAtoms[ DTWM_IS_RUNNING ] )
263 if ( (XGetWindowProperty( m_pDisplay,
264 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
265 m_aWMAtoms[ DTWM_IS_RUNNING ],
266 0, 1,
267 False,
268 XA_INTEGER,
269 &aRealType,
270 &nFormat,
271 &nItems,
272 &nBytesLeft,
273 &pProperty) == 0
274 && nItems)
275 || (XGetWindowProperty( m_pDisplay,
276 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
277 m_aWMAtoms[ DTWM_IS_RUNNING ],
278 0, 1,
279 False,
280 m_aWMAtoms[ DTWM_IS_RUNNING ],
281 &aRealType,
282 &nFormat,
283 &nItems,
284 &nBytesLeft,
285 &pProperty) == 0
286 && nItems))
288 if (*pProperty)
290 m_aWMName = String(RTL_CONSTASCII_USTRINGPARAM("Dtwm"));
291 m_bTransientBehaviour = false;
292 m_nWinGravity = CenterGravity;
294 XFree (pProperty);
296 else if( pProperty )
298 XFree( pProperty );
299 pProperty = NULL;
302 if( m_aWMName.Len() == 0 )
304 // check for window maker - needs different gravity
305 Atom aWMakerRunning = XInternAtom( m_pDisplay, "_WINDOWMAKER_WM_PROTOCOLS", True );
306 if( aWMakerRunning != None &&
307 XGetWindowProperty( m_pDisplay,
308 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
309 aWMakerRunning,
310 0, 32,
311 False,
312 XA_ATOM,
313 &aRealType,
314 &nFormat,
315 &nItems,
316 &nBytesLeft,
317 &pProperty ) == 0 )
319 if( aRealType == XA_ATOM )
320 m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("Windowmaker" ) );
321 XFree( pProperty );
322 m_nInitWinGravity = NorthWestGravity;
324 else if( pProperty )
326 XFree( pProperty );
327 pProperty = NULL;
330 if( m_aWMName.Len() == 0 )
332 if( XInternAtom( m_pDisplay, "_OL_WIN_ATTR", True ) )
334 m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM( "Olwm" ) );
335 m_nInitWinGravity = NorthWestGravity;
338 if( m_aWMName.Len() == 0 )
340 // check for ReflectionX wm (as it needs a workaround in Windows mode
341 Atom aRwmRunning = XInternAtom( m_pDisplay, "RWM_RUNNING", True );
342 if( aRwmRunning != None &&
343 XGetWindowProperty( m_pDisplay,
344 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
345 aRwmRunning,
346 0, 32,
347 False,
348 aRwmRunning,
349 &aRealType,
350 &nFormat,
351 &nItems,
352 &nBytesLeft,
353 &pProperty ) == 0 )
355 if( aRealType == aRwmRunning )
356 m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("ReflectionX" ) );
357 XFree( pProperty );
359 else if( (aRwmRunning = XInternAtom( m_pDisplay, "_WRQ_WM_RUNNING", True )) != None &&
360 XGetWindowProperty( m_pDisplay,
361 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
362 aRwmRunning,
363 0, 32,
364 False,
365 XA_STRING,
366 &aRealType,
367 &nFormat,
368 &nItems,
369 &nBytesLeft,
370 &pProperty ) == 0 )
372 if( aRealType == XA_STRING )
373 m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM( "ReflectionX Windows" ) );
374 XFree( pProperty );
377 if( m_aWMName.Len() == 0 )
379 Atom aTTAPlatform = XInternAtom( m_pDisplay, "TTA_CLIENT_PLATFORM", True );
380 if( aTTAPlatform != None &&
381 XGetWindowProperty( m_pDisplay,
382 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
383 aTTAPlatform,
384 0, 32,
385 False,
386 XA_STRING,
387 &aRealType,
388 &nFormat,
389 &nItems,
390 &nBytesLeft,
391 &pProperty ) == 0 )
393 if( aRealType == XA_STRING )
395 m_aWMName = String( RTL_CONSTASCII_USTRINGPARAM("Tarantella" ) );
396 // #i62319# pretend that AlwaysOnTop works since
397 // the alwaysontop workaround in salframe.cxx results
398 // in a raise/lower loop on a Windows tarantella client
399 // FIXME: this property contains an identification string that
400 // in theory should be good enough to recognize running on a
401 // Windows client; however this string does not seem to be
402 // documented as well as the property itself.
403 m_bEnableAlwaysOnTopWorks = true;
405 XFree( pProperty );
411 * WMAdaptor destructor
414 WMAdaptor::~WMAdaptor()
419 * NetWMAdaptor constructor
422 NetWMAdaptor::NetWMAdaptor( SalDisplay* pSalDisplay ) :
423 WMAdaptor( pSalDisplay )
425 // currently all _NET WMs do transient like expected
426 m_bTransientBehaviour = true;
428 Atom aRealType = None;
429 int nFormat = 8;
430 unsigned long nItems = 0;
431 unsigned long nBytesLeft = 0;
432 unsigned char* pProperty = NULL;
433 bool bNetWM = false;
435 initAtoms();
437 // check for NetWM
438 bNetWM = getNetWmName();
439 if( bNetWM
440 && XGetWindowProperty( m_pDisplay,
441 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
442 m_aWMAtoms[ NET_SUPPORTED ],
443 0, 0,
444 False,
445 XA_ATOM,
446 &aRealType,
447 &nFormat,
448 &nItems,
449 &nBytesLeft,
450 &pProperty ) == 0
451 && aRealType == XA_ATOM
452 && nFormat == 32
455 if( pProperty )
457 XFree( pProperty );
458 pProperty = NULL;
460 // collect supported protocols
461 if( XGetWindowProperty( m_pDisplay,
462 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
463 m_aWMAtoms[ NET_SUPPORTED ],
464 0, nBytesLeft/4,
465 False,
466 XA_ATOM,
467 &aRealType,
468 &nFormat,
469 &nItems,
470 &nBytesLeft,
471 &pProperty ) == 0
472 && nItems
475 Atom* pAtoms = (Atom*)pProperty;
476 char** pAtomNames = (char**)alloca( sizeof(char*)*nItems );
477 if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
479 #if OSL_DEBUG_LEVEL > 1
480 fprintf( stderr, "supported protocols:\n" );
481 #endif
482 for( unsigned int i = 0; i < nItems; i++ )
484 // #i80971# protect against invalid atoms
485 if( pAtomNames[i] == NULL )
486 continue;
488 int nProtocol = -1;
489 WMAdaptorProtocol aSearch;
490 aSearch.pProtocol = pAtomNames[i];
491 WMAdaptorProtocol* pMatch = (WMAdaptorProtocol*)
492 bsearch( &aSearch,
493 aProtocolTab,
494 sizeof( aProtocolTab )/sizeof( aProtocolTab[0] ),
495 sizeof( struct WMAdaptorProtocol ),
496 compareProtocol );
497 if( pMatch )
499 nProtocol = pMatch->nProtocol;
500 m_aWMAtoms[ nProtocol ] = pAtoms[ i ];
501 if( pMatch->nProtocol == NET_WM_STATE_STAYS_ON_TOP )
502 m_bEnableAlwaysOnTopWorks = true;
504 #if OSL_DEBUG_LEVEL > 1
505 fprintf( stderr, " %s%s\n", pAtomNames[i], nProtocol != -1 ? "" : " (unsupported)" );
506 #endif
508 XFree( pAtomNames[i] );
511 XFree( pProperty );
512 pProperty = NULL;
514 else if( pProperty )
516 XFree( pProperty );
517 pProperty = NULL;
520 // get number of desktops
521 if( m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ]
522 && XGetWindowProperty( m_pDisplay,
523 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
524 m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ],
525 0, 1,
526 False,
527 XA_CARDINAL,
528 &aRealType,
529 &nFormat,
530 &nItems,
531 &nBytesLeft,
532 &pProperty ) == 0
533 && pProperty
536 m_nDesktops = *(long*)pProperty;
537 XFree( pProperty );
538 pProperty = NULL;
539 // get work areas
540 if( m_aWMAtoms[ NET_WORKAREA ]
541 && XGetWindowProperty( m_pDisplay,
542 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
543 m_aWMAtoms[ NET_WORKAREA ],
544 0, 4*m_nDesktops,
545 False,
546 XA_CARDINAL,
547 &aRealType,
548 &nFormat,
549 &nItems,
550 &nBytesLeft,
551 &pProperty
552 ) == 0
553 && nItems == 4*(unsigned)m_nDesktops
556 m_aWMWorkAreas = ::std::vector< Rectangle > ( m_nDesktops );
557 long* pValues = (long*)pProperty;
558 for( int i = 0; i < m_nDesktops; i++ )
560 Point aPoint( pValues[4*i],
561 pValues[4*i+1] );
562 Size aSize( pValues[4*i+2],
563 pValues[4*i+3] );
564 Rectangle aWorkArea( aPoint, aSize );
565 m_aWMWorkAreas[i] = aWorkArea;
566 if( aWorkArea != m_aWMWorkAreas[0] )
567 m_bEqualWorkAreas = false;
568 #if OSL_DEBUG_LEVEL > 1
569 fprintf( stderr, "workarea %d: %ldx%ld+%ld+%ld\n",
571 m_aWMWorkAreas[i].GetWidth(),
572 m_aWMWorkAreas[i].GetHeight(),
573 m_aWMWorkAreas[i].Left(),
574 m_aWMWorkAreas[i].Top() );
575 #endif
577 XFree( pProperty );
579 else
581 #if OSL_DEBUG_LEVEL > 1
582 fprintf( stderr, "%ld workareas for %d desktops !\n", nItems/4, m_nDesktops );
583 #endif
584 if( pProperty )
586 XFree(pProperty);
587 pProperty = NULL;
591 else if( pProperty )
593 XFree( pProperty );
594 pProperty = NULL;
597 else if( pProperty )
599 XFree( pProperty );
600 pProperty = NULL;
605 * NetWMAdaptor destructor
607 NetWMAdaptor::~NetWMAdaptor()
612 * GnomeWMAdaptor constructor
615 GnomeWMAdaptor::GnomeWMAdaptor( SalDisplay* pSalDisplay ) :
616 WMAdaptor( pSalDisplay ),
617 m_bValid( false )
619 // currently all Gnome WMs do transient like expected
620 m_bTransientBehaviour = true;
622 Atom aRealType = None;
623 int nFormat = 8;
624 unsigned long nItems = 0;
625 unsigned long nBytesLeft = 0;
626 unsigned char* pProperty = NULL;
628 initAtoms();
630 // check for GnomeWM
631 if( m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ WIN_PROTOCOLS ] )
633 XLIB_Window aWMChild = None;
634 if( XGetWindowProperty( m_pDisplay,
635 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
636 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
637 0, 1,
638 False,
639 XA_CARDINAL,
640 &aRealType,
641 &nFormat,
642 &nItems,
643 &nBytesLeft,
644 &pProperty ) == 0
645 && aRealType == XA_CARDINAL
646 && nFormat == 32
647 && nItems != 0
650 aWMChild = *(XLIB_Window*)pProperty;
651 XFree( pProperty );
652 pProperty = NULL;
653 XLIB_Window aCheckWindow = None;
654 m_pSalDisplay->GetXLib()->PushXErrorLevel( true );
655 if( XGetWindowProperty( m_pDisplay,
656 aWMChild,
657 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
658 0, 1,
659 False,
660 XA_CARDINAL,
661 &aRealType,
662 &nFormat,
663 &nItems,
664 &nBytesLeft,
665 &pProperty ) == 0
666 && aRealType == XA_CARDINAL
667 && nFormat == 32
668 && nItems != 0
669 && ! m_pSalDisplay->GetXLib()->HasXErrorOccured()
672 aCheckWindow = *(XLIB_Window*)pProperty;
673 XFree( pProperty );
674 pProperty = NULL;
675 if( aCheckWindow == aWMChild )
677 m_bValid = true;
679 * get name of WM
680 * this is NOT part of the GNOME WM hints, but e.g. Sawfish
681 * already supports this part of the extended WM hints
683 m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
684 getNetWmName();
687 m_pSalDisplay->GetXLib()->PopXErrorLevel();
689 else if( pProperty )
691 XFree( pProperty );
692 pProperty = NULL;
695 if( m_bValid
696 && XGetWindowProperty( m_pDisplay,
697 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
698 m_aWMAtoms[ WIN_PROTOCOLS ],
699 0, 0,
700 False,
701 XA_ATOM,
702 &aRealType,
703 &nFormat,
704 &nItems,
705 &nBytesLeft,
706 &pProperty ) == 0
707 && aRealType == XA_ATOM
708 && nFormat == 32
711 if( pProperty )
713 XFree( pProperty );
714 pProperty = NULL;
716 // collect supported protocols
717 if( XGetWindowProperty( m_pDisplay,
718 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
719 m_aWMAtoms[ WIN_PROTOCOLS ],
720 0, nBytesLeft/4,
721 False,
722 XA_ATOM,
723 &aRealType,
724 &nFormat,
725 &nItems,
726 &nBytesLeft,
727 &pProperty ) == 0
728 && pProperty
731 Atom* pAtoms = (Atom*)pProperty;
732 char** pAtomNames = (char**)alloca( sizeof(char*)*nItems );
733 if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
735 #if OSL_DEBUG_LEVEL > 1
736 fprintf( stderr, "supported protocols:\n" );
737 #endif
738 for( unsigned int i = 0; i < nItems; i++ )
740 // #i80971# protect against invalid atoms
741 if( pAtomNames[i] == NULL )
742 continue;
744 int nProtocol = -1;
745 WMAdaptorProtocol aSearch;
746 aSearch.pProtocol = pAtomNames[i];
747 WMAdaptorProtocol* pMatch = (WMAdaptorProtocol*)
748 bsearch( &aSearch,
749 aProtocolTab,
750 sizeof( aProtocolTab )/sizeof( aProtocolTab[0] ),
751 sizeof( struct WMAdaptorProtocol ),
752 compareProtocol );
753 if( pMatch )
755 nProtocol = pMatch->nProtocol;
756 m_aWMAtoms[ nProtocol ] = pAtoms[ i ];
757 if( pMatch->nProtocol == WIN_LAYER )
758 m_bEnableAlwaysOnTopWorks = true;
760 if( strncmp( "_ICEWM_TRAY", pAtomNames[i], 11 ) == 0 )
762 m_aWMName = String(RTL_CONSTASCII_USTRINGPARAM("IceWM" ));
763 m_nWinGravity = NorthWestGravity;
764 m_nInitWinGravity = NorthWestGravity;
766 #if OSL_DEBUG_LEVEL > 1
767 fprintf( stderr, " %s%s\n", pAtomNames[i], nProtocol != -1 ? "" : " (unsupported)" );
768 #endif
770 XFree( pAtomNames[i] );
773 XFree( pProperty );
774 pProperty = NULL;
776 else if( pProperty )
778 XFree( pProperty );
779 pProperty = NULL;
782 // get number of desktops
783 if( m_aWMAtoms[ WIN_WORKSPACE_COUNT ]
784 && XGetWindowProperty( m_pDisplay,
785 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
786 m_aWMAtoms[ WIN_WORKSPACE_COUNT ],
787 0, 1,
788 False,
789 XA_CARDINAL,
790 &aRealType,
791 &nFormat,
792 &nItems,
793 &nBytesLeft,
794 &pProperty ) == 0
795 && pProperty
798 m_nDesktops = *(long*)pProperty;
799 XFree( pProperty );
800 pProperty = NULL;
802 else if( pProperty )
804 XFree( pProperty );
805 pProperty = NULL;
808 else if( pProperty )
810 XFree( pProperty );
811 pProperty = NULL;
816 * GnomeWMAdaptor destructor
818 GnomeWMAdaptor::~GnomeWMAdaptor()
823 * getNetWmName()
825 bool WMAdaptor::getNetWmName()
827 Atom aRealType = None;
828 int nFormat = 8;
829 unsigned long nItems = 0;
830 unsigned long nBytesLeft = 0;
831 unsigned char* pProperty = NULL;
832 bool bNetWM = false;
834 if( m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ NET_WM_NAME ] )
836 XLIB_Window aWMChild = None;
837 if( XGetWindowProperty( m_pDisplay,
838 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
839 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
840 0, 1,
841 False,
842 XA_WINDOW,
843 &aRealType,
844 &nFormat,
845 &nItems,
846 &nBytesLeft,
847 &pProperty ) == 0
848 && aRealType == XA_WINDOW
849 && nFormat == 32
850 && nItems != 0
853 aWMChild = *(XLIB_Window*)pProperty;
854 XFree( pProperty );
855 pProperty = NULL;
856 XLIB_Window aCheckWindow = None;
857 m_pSalDisplay->GetXLib()->PushXErrorLevel( true );
858 if( XGetWindowProperty( m_pDisplay,
859 aWMChild,
860 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
861 0, 1,
862 False,
863 XA_WINDOW,
864 &aRealType,
865 &nFormat,
866 &nItems,
867 &nBytesLeft,
868 &pProperty ) == 0
869 && aRealType == XA_WINDOW
870 && nFormat == 32
871 && nItems != 0
872 && ! m_pSalDisplay->GetXLib()->HasXErrorOccured()
875 aCheckWindow = *(XLIB_Window*)pProperty;
876 XFree( pProperty );
877 pProperty = NULL;
878 if( aCheckWindow == aWMChild )
880 bNetWM = true;
881 // get name of WM
882 m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING", False );
883 if( XGetWindowProperty( m_pDisplay,
884 aWMChild,
885 m_aWMAtoms[ NET_WM_NAME ],
886 0, 256,
887 False,
888 AnyPropertyType, /* m_aWMAtoms[ UTF8_STRING ],*/
889 &aRealType,
890 &nFormat,
891 &nItems,
892 &nBytesLeft,
893 &pProperty ) == 0
894 && nItems != 0
897 if (aRealType == m_aWMAtoms[ UTF8_STRING ])
899 m_aWMName = String( (sal_Char*)pProperty, nItems, RTL_TEXTENCODING_UTF8 );
901 else
902 if (aRealType == XA_STRING)
904 m_aWMName = String( (sal_Char*)pProperty, nItems, RTL_TEXTENCODING_ISO_8859_1 );
907 XFree( pProperty );
908 pProperty = NULL;
910 else if( pProperty )
912 XFree( pProperty );
913 pProperty = NULL;
917 else if( pProperty )
919 XFree( pProperty );
920 pProperty = NULL;
922 m_pSalDisplay->GetXLib()->PopXErrorLevel();
924 else if( pProperty )
926 XFree( pProperty );
927 pProperty = NULL;
930 return bNetWM;
934 * WMAdaptor::isValid()
936 bool WMAdaptor::isValid() const
938 return true;
942 * NetWMAdaptor::isValid()
944 bool NetWMAdaptor::isValid() const
946 // some necessary sanity checks; there are WMs out there
947 // which implement some of the WM hints spec without
948 // real functionality
949 return
950 m_aWMAtoms[ NET_SUPPORTED ]
951 && m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]
952 && m_aWMAtoms[ NET_WM_NAME ]
953 && m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ]
954 && m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ]
959 * GnomeWMAdaptor::isValid()
961 bool GnomeWMAdaptor::isValid() const
963 return m_bValid;
967 * WMAdaptor::initAtoms
970 void WMAdaptor::initAtoms()
972 // get basic atoms
973 for( unsigned int i = 0; i < sizeof( aAtomTab )/sizeof( aAtomTab[0] ); i++ )
974 m_aWMAtoms[ aAtomTab[i].nProtocol ] = XInternAtom( m_pDisplay, aAtomTab[i].pProtocol, False );
975 m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] = XInternAtom( m_pDisplay, "_NET_SUPPORTING_WM_CHECK", True );
976 m_aWMAtoms[ NET_WM_NAME ] = XInternAtom( m_pDisplay, "_NET_WM_NAME", True );
980 * NetWMAdaptor::initAtoms
983 void NetWMAdaptor::initAtoms()
985 WMAdaptor::initAtoms();
987 m_aWMAtoms[ NET_SUPPORTED ] = XInternAtom( m_pDisplay, "_NET_SUPPORTED", True );
991 * GnomeWMAdaptor::initAtoms
994 void GnomeWMAdaptor::initAtoms()
996 WMAdaptor::initAtoms();
998 m_aWMAtoms[ WIN_PROTOCOLS ] = XInternAtom( m_pDisplay, "_WIN_PROTOCOLS", True );
999 m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] = XInternAtom( m_pDisplay, "_WIN_SUPPORTING_WM_CHECK", True );
1003 * WMAdaptor::setWMName
1004 * sets WM_NAME
1005 * WM_ICON_NAME
1008 void WMAdaptor::setWMName( X11SalFrame* pFrame, const String& rWMName ) const
1010 ByteString aTitle( rWMName, osl_getThreadTextEncoding() );
1012 if( ! rWMName.Len() && m_aWMName.EqualsAscii( "Dtwm" ) )
1013 aTitle = " ";
1015 ::rtl::OString aWMLocale;
1016 rtl_Locale* pLocale = NULL;
1017 osl_getProcessLocale( &pLocale );
1018 if( pLocale )
1020 ::rtl::OUString aLocaleString( pLocale->Language );
1021 ::rtl::OUString aCountry( pLocale->Country );
1022 ::rtl::OUString aVariant( pLocale->Variant );
1024 if( aCountry.getLength() )
1026 aLocaleString += ::rtl::OUString::createFromAscii( "_" );
1027 aLocaleString += aCountry;
1029 if( aVariant.getLength() )
1030 aLocaleString += aVariant;
1031 aWMLocale = ::rtl::OUStringToOString( aLocaleString, RTL_TEXTENCODING_ISO_8859_1 );
1033 else
1035 static const char* pLang = getenv( "LANG" );
1036 aWMLocale = pLang ? pLang : "C";
1039 static bool bTrustXmb = true;
1040 #ifdef SOLARIS
1041 /* #i64273# there are some weird cases when using IIIMP on Solaris
1042 * where for unknown reasons XmbTextListToTextProperty results in
1043 * garbage. Test one string once to ensure safety.
1045 * FIXME: This must be a bug in xiiimp.so.2 somewhere. However
1046 * it was not possible to recreate this in a small sample program.
1047 * This reeks of memory corruption somehow.
1049 static bool bOnce = true;
1050 if( bOnce )
1052 bOnce = false;
1053 XTextProperty aTestProp = { NULL, None, 0, 0 };
1054 const char *pText = "trustme";
1055 XmbTextListToTextProperty( m_pDisplay,
1056 &const_cast<char*>(pText),
1058 XStdICCTextStyle,
1059 &aTestProp );
1060 bTrustXmb = (aTestProp.nitems == 7) &&
1061 (aTestProp.value != NULL ) &&
1062 (strncmp( (char*)aTestProp.value, pText, 7 ) == 0) &&
1063 (aTestProp.encoding == XA_STRING);
1064 if( aTestProp.value )
1065 XFree( aTestProp.value );
1066 #if OSL_DEBUG_LEVEL > 1
1067 fprintf( stderr, "%s\n",
1068 bTrustXmb ?
1069 "XmbTextListToTextProperty seems to work" :
1070 "XmbTextListToTextProperty does not seem to work" );
1071 #endif
1073 #endif
1075 char* pT = const_cast<char*>(aTitle.GetBuffer());
1076 XTextProperty aProp = { NULL, None, 0, 0 };
1077 if( bTrustXmb )
1079 XmbTextListToTextProperty( m_pDisplay,
1080 &pT,
1082 XStdICCTextStyle,
1083 &aProp );
1086 unsigned char* pData = aProp.nitems ? aProp.value : (unsigned char*)aTitle.GetBuffer();
1087 Atom nType = aProp.nitems ? aProp.encoding : XA_STRING;
1088 int nFormat = aProp.nitems ? aProp.format : 8;
1089 int nBytes = aProp.nitems ? aProp.nitems : aTitle.Len();
1090 const SystemEnvData* pEnv = pFrame->GetSystemData();
1091 XChangeProperty( m_pDisplay,
1092 (XLIB_Window)pEnv->aShellWindow,
1093 XA_WM_NAME,
1094 nType,
1095 nFormat,
1096 PropModeReplace,
1097 pData,
1098 nBytes );
1099 XChangeProperty( m_pDisplay,
1100 (XLIB_Window)pEnv->aShellWindow,
1101 XA_WM_ICON_NAME,
1102 nType,
1103 nFormat,
1104 PropModeReplace,
1105 pData,
1106 nBytes );
1107 XChangeProperty( m_pDisplay,
1108 (XLIB_Window)pEnv->aShellWindow,
1109 m_aWMAtoms[ WM_LOCALE_NAME ],
1110 XA_STRING,
1112 PropModeReplace,
1113 (unsigned char*)aWMLocale.getStr(),
1114 aWMLocale.getLength() );
1115 if (aProp.value != NULL)
1116 XFree( aProp.value );
1120 * NetWMAdaptor::setWMName
1121 * sets WM_NAME
1122 * _NET_WM_NAME
1123 * WM_ICON_NAME
1124 * _NET_WM_ICON_NAME
1126 void NetWMAdaptor::setWMName( X11SalFrame* pFrame, const String& rWMName ) const
1128 WMAdaptor::setWMName( pFrame, rWMName );
1130 ByteString aTitle( rWMName, RTL_TEXTENCODING_UTF8 );
1131 const SystemEnvData* pEnv = pFrame->GetSystemData();
1132 if( m_aWMAtoms[ NET_WM_NAME ] )
1133 XChangeProperty( m_pDisplay,
1134 (XLIB_Window)pEnv->aShellWindow,
1135 m_aWMAtoms[ NET_WM_NAME ],
1136 m_aWMAtoms[ UTF8_STRING ],
1138 PropModeReplace,
1139 (unsigned char*)aTitle.GetBuffer(),
1140 aTitle.Len()+1 );
1141 if( m_aWMAtoms[ NET_WM_ICON_NAME ] )
1142 XChangeProperty( m_pDisplay,
1143 (XLIB_Window)pEnv->aShellWindow,
1144 m_aWMAtoms[ NET_WM_ICON_NAME ],
1145 m_aWMAtoms[ UTF8_STRING ],
1147 PropModeReplace,
1148 (unsigned char*)aTitle.GetBuffer(),
1149 aTitle.Len()+1 );
1150 // The +1 copies the terminating null byte. Although
1151 // the spec says, this should not be necessary
1152 // at least the kwin implementation seems to depend
1153 // on the null byte
1157 * NetWMAdaptor::setNetWMState
1158 * sets _NET_WM_STATE
1160 void NetWMAdaptor::setNetWMState( X11SalFrame* pFrame ) const
1162 if( m_aWMAtoms[ NET_WM_STATE ] )
1164 Atom aStateAtoms[ 10 ];
1165 int nStateAtoms = 0;
1167 // set NET_WM_STATE_MODAL
1168 if( m_aWMAtoms[ NET_WM_STATE_MODAL ]
1169 && pFrame->meWindowType == windowType_ModalDialogue )
1171 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MODAL ];
1173 * #90998# NET_WM_STATE_SKIP_TASKBAR set on a frame will
1174 * cause kwin not to give it the focus on map request
1175 * this seems to be a bug in kwin
1176 * aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];
1179 if( pFrame->mbMaximizedVert
1180 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
1181 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1182 if( pFrame->mbMaximizedHorz
1183 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
1184 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1185 if( pFrame->bAlwaysOnTop_ && m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
1186 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1187 if( pFrame->mbShaded && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
1188 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SHADED ];
1189 if( pFrame->mbFullScreen && m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
1190 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
1191 if( pFrame->meWindowType == windowType_Utility && m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ] )
1192 aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];
1194 if( nStateAtoms )
1196 XChangeProperty( m_pDisplay,
1197 pFrame->GetShellWindow(),
1198 m_aWMAtoms[ NET_WM_STATE ],
1199 XA_ATOM,
1201 PropModeReplace,
1202 (unsigned char*)aStateAtoms,
1203 nStateAtoms
1206 else
1207 XDeleteProperty( m_pDisplay,
1208 pFrame->GetShellWindow(),
1209 m_aWMAtoms[ NET_WM_STATE ] );
1210 if( pFrame->mbMaximizedHorz
1211 && pFrame->mbMaximizedVert
1212 && ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
1215 * for maximizing use NorthWestGravity (including decoration)
1217 XSizeHints hints;
1218 long supplied;
1219 bool bHint = false;
1220 if( XGetWMNormalHints( m_pDisplay,
1221 pFrame->GetShellWindow(),
1222 &hints,
1223 &supplied ) )
1225 bHint = true;
1226 hints.flags |= PWinGravity;
1227 hints.win_gravity = NorthWestGravity;
1228 XSetWMNormalHints( m_pDisplay,
1229 pFrame->GetShellWindow(),
1230 &hints );
1231 XSync( m_pDisplay, False );
1234 // SetPosSize necessary to set width/height, min/max w/h
1235 sal_Int32 nCurrent = 0;
1237 * get current desktop here if work areas have different size
1238 * (does this happen on any platform ?)
1240 if( ! m_bEqualWorkAreas )
1242 nCurrent = getCurrentWorkArea();
1243 if( nCurrent < 0 )
1244 nCurrent = 0;
1246 Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1247 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1248 aPosSize = Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1249 aPosSize.Top() + rGeom.nTopDecoration ),
1250 Size( aPosSize.GetWidth()
1251 - rGeom.nLeftDecoration
1252 - rGeom.nRightDecoration,
1253 aPosSize.GetHeight()
1254 - rGeom.nTopDecoration
1255 - rGeom.nBottomDecoration )
1257 pFrame->SetPosSize( aPosSize );
1260 * reset gravity hint to static gravity
1261 * (this should not move window according to ICCCM)
1263 if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1265 hints.win_gravity = StaticGravity;
1266 XSetWMNormalHints( m_pDisplay,
1267 pFrame->GetShellWindow(),
1268 &hints );
1275 * GnomeWMAdaptor::setNetWMState
1276 * sets _WIN_STATE
1278 void GnomeWMAdaptor::setGnomeWMState( X11SalFrame* pFrame ) const
1280 if( m_aWMAtoms[ WIN_STATE ] )
1282 sal_uInt32 nWinWMState = 0;
1284 if( pFrame->mbMaximizedVert )
1285 nWinWMState |= 1 << 2;
1286 if( pFrame->mbMaximizedHorz )
1287 nWinWMState |= 1 << 3;
1288 if( pFrame->mbShaded )
1289 nWinWMState |= 1 << 5;
1291 XChangeProperty( m_pDisplay,
1292 pFrame->GetShellWindow(),
1293 m_aWMAtoms[ WIN_STATE ],
1294 XA_CARDINAL,
1296 PropModeReplace,
1297 (unsigned char*)&nWinWMState,
1300 if( pFrame->mbMaximizedHorz
1301 && pFrame->mbMaximizedVert
1302 && ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
1305 * for maximizing use NorthWestGravity (including decoration)
1307 XSizeHints hints;
1308 long supplied;
1309 bool bHint = false;
1310 if( XGetWMNormalHints( m_pDisplay,
1311 pFrame->GetShellWindow(),
1312 &hints,
1313 &supplied ) )
1315 bHint = true;
1316 hints.flags |= PWinGravity;
1317 hints.win_gravity = NorthWestGravity;
1318 XSetWMNormalHints( m_pDisplay,
1319 pFrame->GetShellWindow(),
1320 &hints );
1321 XSync( m_pDisplay, False );
1324 // SetPosSize necessary to set width/height, min/max w/h
1325 sal_Int32 nCurrent = 0;
1327 * get current desktop here if work areas have different size
1328 * (does this happen on any platform ?)
1330 if( ! m_bEqualWorkAreas )
1332 nCurrent = getCurrentWorkArea();
1333 if( nCurrent < 0 )
1334 nCurrent = 0;
1336 Rectangle aPosSize = m_aWMWorkAreas[nCurrent];
1337 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1338 aPosSize = Rectangle( Point( aPosSize.Left() + rGeom.nLeftDecoration,
1339 aPosSize.Top() + rGeom.nTopDecoration ),
1340 Size( aPosSize.GetWidth()
1341 - rGeom.nLeftDecoration
1342 - rGeom.nRightDecoration,
1343 aPosSize.GetHeight()
1344 - rGeom.nTopDecoration
1345 - rGeom.nBottomDecoration )
1347 pFrame->SetPosSize( aPosSize );
1350 * reset gravity hint to static gravity
1351 * (this should not move window according to ICCCM)
1353 if( bHint && pFrame->nShowState_ != SHOWSTATE_UNKNOWN )
1355 hints.win_gravity = StaticGravity;
1356 XSetWMNormalHints( m_pDisplay,
1357 pFrame->GetShellWindow(),
1358 &hints );
1365 * WMAdaptor::setFrameDecoration
1366 * sets _MOTIF_WM_HINTS
1367 * WM_TRANSIENT_FOR
1370 void WMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1372 pFrame->meWindowType = eType;
1373 pFrame->mnDecorationFlags = nDecorationFlags;
1375 // set mwm hints
1376 struct _mwmhints {
1377 unsigned long flags, func, deco;
1378 long input_mode;
1379 unsigned long status;
1380 } aHint;
1382 aHint.flags = 15; /* flags for functions, decoration, input mode and status */
1383 aHint.deco = 0;
1384 aHint.func = 1L << 2;
1385 aHint.status = 0;
1386 aHint.input_mode = 0;
1388 // evaluate decoration flags
1389 if( nDecorationFlags & decoration_All )
1390 aHint.deco = 1, aHint.func = 1;
1391 else
1393 if( nDecorationFlags & decoration_Title )
1394 aHint.deco |= 1L << 3;
1395 if( nDecorationFlags & decoration_Border )
1396 aHint.deco |= 1L << 1;
1397 if( nDecorationFlags & decoration_Resize )
1398 aHint.deco |= 1L << 2, aHint.func |= 1L << 1;
1399 if( nDecorationFlags & decoration_MinimizeBtn )
1400 aHint.deco |= 1L << 5, aHint.func |= 1L << 3;
1401 if( nDecorationFlags & decoration_MaximizeBtn )
1402 aHint.deco |= 1L << 6, aHint.func |= 1L << 4;
1403 if( nDecorationFlags & decoration_CloseBtn )
1404 aHint.deco |= 1L << 4, aHint.func |= 1L << 5;
1406 // evaluate window type
1407 switch( eType )
1409 case windowType_ModalDialogue:
1410 aHint.input_mode = 1;
1411 break;
1412 default:
1413 break;
1416 // set the hint
1417 XChangeProperty( m_pDisplay,
1418 pFrame->GetShellWindow(),
1419 m_aWMAtoms[ MOTIF_WM_HINTS ],
1420 m_aWMAtoms[ MOTIF_WM_HINTS ],
1422 PropModeReplace,
1423 (unsigned char*)&aHint,
1424 5 );
1426 // set transientFor hint
1427 /* #91030# dtwm will not map a dialogue if the transient
1428 * window is iconified. This is deemed undesireable because
1429 * message boxes do not get mapped, so use the root as transient
1430 * instead.
1432 if( pReferenceFrame )
1434 XSetTransientForHint( m_pDisplay,
1435 pFrame->GetShellWindow(),
1436 pReferenceFrame->bMapped_ ?
1437 pReferenceFrame->GetShellWindow() :
1438 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() )
1440 if( ! pReferenceFrame->bMapped_ )
1441 pFrame->mbTransientForRoot = true;
1443 // #110333# in case no one ever sets a title prevent
1444 // the Dtwm taking the class instead
1445 if( m_aWMName.EqualsAscii( "Dtwm" ) )
1446 setWMName( pFrame, String() );
1450 * NetWMAdaptor::setFrameDecoration
1451 * sets _MOTIF_WM_HINTS
1452 * _NET_WM_WINDOW_TYPE
1453 * _NET_WM_STATE
1454 * WM_TRANSIENT_FOR
1457 void NetWMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
1459 WMAdaptor::setFrameTypeAndDecoration( pFrame, eType, nDecorationFlags, pReferenceFrame );
1461 setNetWMState( pFrame );
1463 // set NET_WM_WINDOW_TYPE
1464 if( m_aWMAtoms[ NET_WM_WINDOW_TYPE ] )
1466 Atom aWindowTypes[4];
1467 int nWindowTypes = 0;
1468 switch( eType )
1470 case windowType_Utility:
1471 aWindowTypes[nWindowTypes++] =
1472 m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] ?
1473 m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] :
1474 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1475 break;
1476 case windowType_ModelessDialogue:
1477 case windowType_ModalDialogue:
1478 aWindowTypes[nWindowTypes++] =
1479 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
1480 break;
1481 case windowType_Splash:
1482 aWindowTypes[nWindowTypes++] =
1483 m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] ?
1484 m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] :
1485 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1486 break;
1487 case windowType_Toolbar:
1488 if( m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ] )
1489 aWindowTypes[nWindowTypes++] = m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ];
1490 aWindowTypes[nWindowTypes++] =
1491 m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] ?
1492 m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] :
1493 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1494 break;
1495 case windowType_Dock:
1496 aWindowTypes[nWindowTypes++] =
1497 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] ?
1498 m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] :
1499 m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
1500 break;
1501 default:
1502 aWindowTypes[nWindowTypes++] = m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
1503 break;
1505 XChangeProperty( m_pDisplay,
1506 pFrame->GetShellWindow(),
1507 m_aWMAtoms[ NET_WM_WINDOW_TYPE ],
1508 XA_ATOM,
1510 PropModeReplace,
1511 (unsigned char*)aWindowTypes,
1512 nWindowTypes );
1514 if( ( eType == windowType_ModalDialogue ||
1515 eType == windowType_ModelessDialogue )
1516 && ! pReferenceFrame )
1518 XSetTransientForHint( m_pDisplay,
1519 pFrame->GetShellWindow(),
1520 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ) );
1521 pFrame->mbTransientForRoot = true;
1526 * WMAdaptor::maximizeFrame
1529 void WMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1531 pFrame->mbMaximizedVert = bVertical;
1532 pFrame->mbMaximizedHorz = bHorizontal;
1534 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1536 // discard pending configure notifies for this frame
1537 XSync( m_pDisplay, False );
1538 XEvent aDiscard;
1539 while( XCheckTypedWindowEvent( m_pDisplay,
1540 pFrame->GetShellWindow(),
1541 ConfigureNotify,
1542 &aDiscard ) )
1544 while( XCheckTypedWindowEvent( m_pDisplay,
1545 pFrame->GetWindow(),
1546 ConfigureNotify,
1547 &aDiscard ) )
1550 if( bHorizontal || bVertical )
1552 Size aScreenSize( m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() ) );
1553 Point aTL( rGeom.nLeftDecoration, rGeom.nTopDecoration );
1554 if( m_pSalDisplay->IsXinerama() )
1556 Point aMed( aTL.X() + rGeom.nWidth/2, aTL.Y() + rGeom.nHeight/2 );
1557 const std::vector< Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
1558 for( unsigned int i = 0; i < rScreens.size(); i++ )
1559 if( rScreens[i].IsInside( aMed ) )
1561 aTL += rScreens[i].TopLeft();
1562 aScreenSize = rScreens[i].GetSize();
1563 break;
1566 Rectangle aTarget( aTL,
1567 Size( aScreenSize.Width() - rGeom.nLeftDecoration - rGeom.nTopDecoration,
1568 aScreenSize.Height() - rGeom.nTopDecoration - rGeom.nBottomDecoration )
1570 if( ! bHorizontal )
1572 aTarget.SetSize(
1573 Size(
1574 pFrame->maRestorePosSize.IsEmpty() ?
1575 rGeom.nWidth : pFrame->maRestorePosSize.GetWidth(),
1576 aTarget.GetHeight()
1579 aTarget.Left() =
1580 pFrame->maRestorePosSize.IsEmpty() ?
1581 rGeom.nX : pFrame->maRestorePosSize.Left();
1583 else if( ! bVertical )
1585 aTarget.SetSize(
1586 Size(
1587 aTarget.GetWidth(),
1588 pFrame->maRestorePosSize.IsEmpty() ?
1589 rGeom.nHeight : pFrame->maRestorePosSize.GetHeight()
1592 aTarget.Top() =
1593 pFrame->maRestorePosSize.IsEmpty() ?
1594 rGeom.nY : pFrame->maRestorePosSize.Top();
1597 Rectangle aRestore( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1598 if( pFrame->bMapped_ )
1600 XSetInputFocus( m_pDisplay,
1601 pFrame->GetShellWindow(),
1602 RevertToNone,
1603 CurrentTime
1605 if( m_aWMName.EqualsAscii( "Dtwm" ) )
1608 * Dtwm will only position correctly with center gravity
1609 * and in this case the request actually changes the frame
1610 * not the shell window
1612 aTarget = Rectangle( Point( 0, 0 ), aScreenSize );
1613 aRestore.Move( -rGeom.nLeftDecoration, -rGeom.nTopDecoration );
1617 if( pFrame->maRestorePosSize.IsEmpty() )
1618 pFrame->maRestorePosSize = aRestore;
1620 pFrame->SetPosSize( aTarget );
1621 pFrame->nWidth_ = aTarget.GetWidth();
1622 pFrame->nHeight_ = aTarget.GetHeight();
1623 XRaiseWindow( m_pDisplay,
1624 pFrame->GetShellWindow()
1626 if( pFrame->GetStackingWindow() )
1627 XRaiseWindow( m_pDisplay,
1628 pFrame->GetStackingWindow()
1632 else
1634 pFrame->SetPosSize( pFrame->maRestorePosSize );
1635 pFrame->maRestorePosSize = Rectangle();
1636 pFrame->nWidth_ = rGeom.nWidth;
1637 pFrame->nHeight_ = rGeom.nHeight;
1638 if( m_aWMName.EqualsAscii( "Dtwm" ) && pFrame->bMapped_ )
1640 pFrame->maGeometry.nX += rGeom.nLeftDecoration;
1641 pFrame->maGeometry.nY += rGeom.nTopDecoration;
1647 * NetWMAdaptor::maximizeFrame
1648 * changes _NET_WM_STATE by sending a client message
1651 void NetWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1653 pFrame->mbMaximizedVert = bVertical;
1654 pFrame->mbMaximizedHorz = bHorizontal;
1656 if( m_aWMAtoms[ NET_WM_STATE ]
1657 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ]
1658 && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ]
1659 && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
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] = bHorizontal ? 1 : 0;
1672 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
1673 aEvent.xclient.data.l[2] = bHorizontal == bVertical ? m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] : 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
1682 if( bHorizontal != bVertical )
1684 aEvent.xclient.data.l[0]= bVertical ? 1 : 0;
1685 aEvent.xclient.data.l[1]= m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
1686 aEvent.xclient.data.l[2]= 0;
1687 XSendEvent( m_pDisplay,
1688 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1689 False,
1690 SubstructureNotifyMask | SubstructureRedirectMask,
1691 &aEvent
1695 else
1697 // window not mapped yet, set _NET_WM_STATE directly
1698 setNetWMState( pFrame );
1700 if( !bHorizontal && !bVertical )
1701 pFrame->maRestorePosSize = Rectangle();
1702 else if( pFrame->maRestorePosSize.IsEmpty() )
1704 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1705 pFrame->maRestorePosSize =
1706 Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1709 else
1710 WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1714 * GnomeWMAdaptor::maximizeFrame
1715 * changes _WIN_STATE by sending a client message
1718 void GnomeWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
1720 pFrame->mbMaximizedVert = bVertical;
1721 pFrame->mbMaximizedHorz = bHorizontal;
1723 if( m_aWMAtoms[ WIN_STATE ]
1724 && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
1727 if( pFrame->bMapped_ )
1729 // window already mapped, send WM a message
1730 XEvent aEvent;
1731 aEvent.type = ClientMessage;
1732 aEvent.xclient.display = m_pDisplay;
1733 aEvent.xclient.window = pFrame->GetShellWindow();
1734 aEvent.xclient.message_type = m_aWMAtoms[ WIN_STATE ];
1735 aEvent.xclient.format = 32;
1736 aEvent.xclient.data.l[0] = (1<<2)|(1<<3);
1737 aEvent.xclient.data.l[1] =
1738 (bVertical ? (1<<2) : 0)
1739 | (bHorizontal ? (1<<3) : 0);
1740 aEvent.xclient.data.l[2] = 0;
1741 aEvent.xclient.data.l[3] = 0;
1742 aEvent.xclient.data.l[4] = 0;
1743 XSendEvent( m_pDisplay,
1744 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1745 False,
1746 SubstructureNotifyMask,
1747 &aEvent
1750 else
1751 // window not mapped yet, set _WIN_STATE directly
1752 setGnomeWMState( pFrame );
1754 if( !bHorizontal && !bVertical )
1755 pFrame->maRestorePosSize = Rectangle();
1756 else if( pFrame->maRestorePosSize.IsEmpty() )
1758 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
1759 pFrame->maRestorePosSize =
1760 Rectangle( Point( rGeom.nX, rGeom.nY ), Size( rGeom.nWidth, rGeom.nHeight ) );
1763 else
1764 WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
1768 * WMAdaptor::supportsICCCMPos
1771 bool WMAdaptor::supportsICCCMPos() const
1773 return
1774 m_aWMName.EqualsAscii( "Sawfish" )
1775 || m_aWMName.EqualsAscii( "Dtwm" );
1779 * NetWMAdaptor::supportsICCCMPos
1782 bool NetWMAdaptor::supportsICCCMPos() const
1784 return true;
1789 * WMAdaptor::enableAlwaysOnTop
1791 void WMAdaptor::enableAlwaysOnTop( X11SalFrame*, bool /*bEnable*/ ) const
1796 * NetWMAdaptor::enableAlwaysOnTop
1798 void NetWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1800 pFrame->bAlwaysOnTop_ = bEnable;
1801 if( m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
1803 if( pFrame->bMapped_ )
1805 // window already mapped, send WM a message
1806 XEvent aEvent;
1807 aEvent.type = ClientMessage;
1808 aEvent.xclient.display = m_pDisplay;
1809 aEvent.xclient.window = pFrame->GetShellWindow();
1810 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
1811 aEvent.xclient.format = 32;
1812 aEvent.xclient.data.l[0] = bEnable ? 1 : 0;
1813 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
1814 aEvent.xclient.data.l[2] = 0;
1815 aEvent.xclient.data.l[3] = 0;
1816 aEvent.xclient.data.l[4] = 0;
1817 XSendEvent( m_pDisplay,
1818 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1819 False,
1820 SubstructureNotifyMask | SubstructureRedirectMask,
1821 &aEvent
1824 else
1825 setNetWMState( pFrame );
1830 * GnomeWMAdaptor::enableAlwaysOnTop
1832 void GnomeWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
1834 pFrame->bAlwaysOnTop_ = bEnable;
1835 if( m_aWMAtoms[ WIN_LAYER ] )
1837 if( pFrame->bMapped_ )
1839 // window already mapped, send WM a message
1840 XEvent aEvent;
1841 aEvent.type = ClientMessage;
1842 aEvent.xclient.display = m_pDisplay;
1843 aEvent.xclient.window = pFrame->GetShellWindow();
1844 aEvent.xclient.message_type = m_aWMAtoms[ WIN_LAYER ];
1845 aEvent.xclient.format = 32;
1846 aEvent.xclient.data.l[0] = bEnable ? 6 : 4;
1847 aEvent.xclient.data.l[1] = 0;
1848 aEvent.xclient.data.l[2] = 0;
1849 aEvent.xclient.data.l[3] = 0;
1850 aEvent.xclient.data.l[4] = 0;
1851 XSendEvent( m_pDisplay,
1852 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
1853 False,
1854 SubstructureNotifyMask | SubstructureRedirectMask,
1855 &aEvent
1858 else
1860 sal_uInt32 nNewLayer = bEnable ? 6 : 4;
1861 XChangeProperty( m_pDisplay,
1862 pFrame->GetShellWindow(),
1863 m_aWMAtoms[ WIN_LAYER ],
1864 XA_CARDINAL,
1866 PropModeReplace,
1867 (unsigned char*)&nNewLayer,
1875 * WMAdaptor::changeReferenceFrame
1877 void WMAdaptor::changeReferenceFrame( X11SalFrame* pFrame, X11SalFrame* pReferenceFrame ) const
1879 if( ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG )
1880 && ! pFrame->IsOverrideRedirect()
1881 && ! pFrame->IsFloatGrabWindow()
1884 XLIB_Window aTransient = pFrame->pDisplay_->GetRootWindow( pFrame->GetScreenNumber() );
1885 pFrame->mbTransientForRoot = true;
1886 if( pReferenceFrame )
1888 aTransient = pReferenceFrame->GetShellWindow();
1889 pFrame->mbTransientForRoot = false;
1891 XSetTransientForHint( m_pDisplay,
1892 pFrame->GetShellWindow(),
1893 aTransient );
1898 * WMAdaptor::handlePropertyNotify
1900 int WMAdaptor::handlePropertyNotify( X11SalFrame*, XPropertyEvent* ) const
1902 return 0;
1906 * NetWMAdaptor::handlePropertyNotify
1908 int NetWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
1910 int nHandled = 1;
1911 if( pEvent->atom == m_aWMAtoms[ NET_WM_STATE ] )
1913 pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
1914 pFrame->mbShaded = false;
1916 if( pEvent->state == PropertyNewValue )
1918 Atom nType, *pStates;
1919 int nFormat;
1920 unsigned long nItems, nBytesLeft;
1921 unsigned char* pData = NULL;
1922 long nOffset = 0;
1925 XGetWindowProperty( m_pDisplay,
1926 pEvent->window,
1927 m_aWMAtoms[ NET_WM_STATE ],
1928 nOffset, 64,
1929 False,
1930 XA_ATOM,
1931 &nType,
1932 &nFormat,
1933 &nItems, &nBytesLeft,
1934 &pData );
1935 if( pData )
1937 if( nType == XA_ATOM && nFormat == 32 && nItems > 0 )
1939 pStates = (Atom*)pData;
1940 for( unsigned long i = 0; i < nItems; i++ )
1942 if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
1943 pFrame->mbMaximizedVert = true;
1944 else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
1945 pFrame->mbMaximizedHorz = true;
1946 else if( pStates[i] == m_aWMAtoms[ NET_WM_STATE_SHADED ] && m_aWMAtoms[ NET_WM_STATE_SHADED ] )
1947 pFrame->mbShaded = true;
1950 XFree( pData );
1951 pData = NULL;
1952 nOffset += nItems * nFormat / 32;
1954 else
1955 break;
1956 } while( nBytesLeft > 0 );
1959 if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
1960 pFrame->maRestorePosSize = Rectangle();
1961 else
1963 const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
1964 // the current geometry may already be changed by the corresponding
1965 // ConfigureNotify, but this cannot be helped
1966 pFrame->maRestorePosSize =
1967 Rectangle( Point( rGeom.nX, rGeom.nY ),
1968 Size( rGeom.nWidth, rGeom.nHeight ) );
1971 else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
1973 pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
1975 else
1976 nHandled = 0;
1978 return nHandled;
1982 * GnomeWMAdaptor::handlePropertyNotify
1984 int GnomeWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
1986 int nHandled = 1;
1987 if( pEvent->atom == m_aWMAtoms[ WIN_STATE ] )
1989 pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;
1990 pFrame->mbShaded = false;
1992 if( pEvent->state == PropertyNewValue )
1994 Atom nType;
1995 int nFormat = 0;
1996 unsigned long nItems = 0;
1997 unsigned long nBytesLeft = 0;
1998 unsigned char* pData = 0;
1999 XGetWindowProperty( m_pDisplay,
2000 pEvent->window,
2001 m_aWMAtoms[ WIN_STATE ],
2002 0, 1,
2003 False,
2004 XA_CARDINAL,
2005 &nType,
2006 &nFormat,
2007 &nItems, &nBytesLeft,
2008 &pData );
2009 if( pData )
2011 if( nType == XA_CARDINAL && nFormat == 32 && nItems == 1 )
2013 sal_uInt32 nWinState = *(sal_uInt32*)pData;
2014 if( nWinState & (1<<2) )
2015 pFrame->mbMaximizedVert = true;
2016 if( nWinState & (1<<3) )
2017 pFrame->mbMaximizedHorz = true;
2018 if( nWinState & (1<<5) )
2019 pFrame->mbShaded = true;
2021 XFree( pData );
2025 if( ! (pFrame->mbMaximizedHorz || pFrame->mbMaximizedVert ) )
2026 pFrame->maRestorePosSize = Rectangle();
2027 else
2029 const SalFrameGeometry& rGeom = pFrame->GetUnmirroredGeometry();
2030 // the current geometry may already be changed by the corresponding
2031 // ConfigureNotify, but this cannot be helped
2032 pFrame->maRestorePosSize =
2033 Rectangle( Point( rGeom.nX, rGeom.nY ),
2034 Size( rGeom.nWidth, rGeom.nHeight ) );
2037 else if( pEvent->atom == m_aWMAtoms[ NET_WM_DESKTOP ] )
2039 pFrame->m_nWorkArea = getWindowWorkArea( pFrame->GetShellWindow() );
2041 else
2042 nHandled = 0;
2044 return nHandled;
2048 * WMAdaptor::shade
2050 void WMAdaptor::shade( X11SalFrame*, bool /*bToShaded*/ ) const
2055 * NetWMAdaptor::shade
2057 void NetWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
2059 if( m_aWMAtoms[ NET_WM_STATE ]
2060 && m_aWMAtoms[ NET_WM_STATE_SHADED ]
2061 && ( pFrame->nStyle_ & ~SAL_FRAME_STYLE_DEFAULT )
2064 pFrame->mbShaded = bToShaded;
2065 if( pFrame->bMapped_ )
2067 // window already mapped, send WM a message
2068 XEvent aEvent;
2069 aEvent.type = ClientMessage;
2070 aEvent.xclient.display = m_pDisplay;
2071 aEvent.xclient.window = pFrame->GetShellWindow();
2072 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
2073 aEvent.xclient.format = 32;
2074 aEvent.xclient.data.l[0] = bToShaded ? 1 : 0;
2075 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_SHADED ];
2076 aEvent.xclient.data.l[2] = 0;
2077 aEvent.xclient.data.l[3] = 0;
2078 aEvent.xclient.data.l[4] = 0;
2079 XSendEvent( m_pDisplay,
2080 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2081 False,
2082 SubstructureNotifyMask | SubstructureRedirectMask,
2083 &aEvent
2086 else
2088 // window not mapped yet, set _NET_WM_STATE directly
2089 setNetWMState( pFrame );
2095 * GnomeWMAdaptor::shade
2097 void GnomeWMAdaptor::shade( X11SalFrame* pFrame, bool bToShaded ) const
2099 if( m_aWMAtoms[ WIN_STATE ] )
2101 pFrame->mbShaded = bToShaded;
2102 if( pFrame->bMapped_ )
2104 // window already mapped, send WM a message
2105 XEvent aEvent;
2106 aEvent.type = ClientMessage;
2107 aEvent.xclient.display = m_pDisplay;
2108 aEvent.xclient.window = pFrame->GetShellWindow();
2109 aEvent.xclient.message_type = m_aWMAtoms[ WIN_STATE ];
2110 aEvent.xclient.format = 32;
2111 aEvent.xclient.data.l[0] = (1<<5);
2112 aEvent.xclient.data.l[1] = bToShaded ? (1<<5) : 0;
2113 aEvent.xclient.data.l[2] = 0;
2114 aEvent.xclient.data.l[3] = 0;
2115 aEvent.xclient.data.l[4] = 0;
2116 XSendEvent( m_pDisplay,
2117 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2118 False,
2119 SubstructureNotifyMask | SubstructureRedirectMask,
2120 &aEvent
2123 else
2124 setGnomeWMState( pFrame );
2129 * WMAdaptor::showFullScreen
2131 void WMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
2133 pFrame->mbFullScreen = bFullScreen;
2134 maximizeFrame( pFrame, bFullScreen, bFullScreen );
2138 * NetWMAdaptor::showFullScreen
2140 void NetWMAdaptor::showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const
2142 if( m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
2144 pFrame->mbFullScreen = bFullScreen;
2145 if( pFrame->bMapped_ )
2147 // window already mapped, send WM a message
2148 XEvent aEvent;
2149 aEvent.type = ClientMessage;
2150 aEvent.xclient.display = m_pDisplay;
2151 aEvent.xclient.window = pFrame->GetShellWindow();
2152 aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
2153 aEvent.xclient.format = 32;
2154 aEvent.xclient.data.l[0] = bFullScreen ? 1 : 0;
2155 aEvent.xclient.data.l[1] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
2156 aEvent.xclient.data.l[2] = 0;
2157 aEvent.xclient.data.l[3] = 0;
2158 aEvent.xclient.data.l[4] = 0;
2159 XSendEvent( m_pDisplay,
2160 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2161 False,
2162 SubstructureNotifyMask | SubstructureRedirectMask,
2163 &aEvent
2166 else
2168 // window not mapped yet, set _NET_WM_STATE directly
2169 setNetWMState( pFrame );
2171 // #i42750# guess size before resize event shows up
2172 if( bFullScreen )
2174 if( m_pSalDisplay->IsXinerama() )
2176 XLIB_Window aRoot, aChild;
2177 int root_x = 0, root_y = 0, lx, ly;
2178 unsigned int mask;
2179 XQueryPointer( m_pDisplay,
2180 m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
2181 &aRoot, &aChild,
2182 &root_x, &root_y, &lx, &ly, &mask );
2183 const std::vector< Rectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
2184 Point aMousePoint( root_x, root_y );
2185 for( unsigned int i = 0; i < rScreens.size(); i++ )
2187 if( rScreens[i].IsInside( aMousePoint ) )
2189 pFrame->maGeometry.nX = rScreens[i].Left();
2190 pFrame->maGeometry.nY = rScreens[i].Top();
2191 pFrame->maGeometry.nWidth = rScreens[i].GetWidth();
2192 pFrame->maGeometry.nHeight = rScreens[i].GetHeight();
2193 break;
2197 else
2199 Size aSize = m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() );
2200 pFrame->maGeometry.nX = 0;
2201 pFrame->maGeometry.nY = 0;
2202 pFrame->maGeometry.nWidth = aSize.Width();
2203 pFrame->maGeometry.nHeight = aSize.Height();
2205 pFrame->CallCallback( SALEVENT_MOVERESIZE, NULL );
2208 else WMAdaptor::showFullScreen( pFrame, bFullScreen );
2212 * WMAdaptor::getCurrentWorkArea
2214 // FIXME: multiscreen case
2215 int WMAdaptor::getCurrentWorkArea() const
2217 int nCurrent = -1;
2218 if( m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2220 Atom aRealType = None;
2221 int nFormat = 8;
2222 unsigned long nItems = 0;
2223 unsigned long nBytesLeft = 0;
2224 unsigned char* pProperty = NULL;
2225 if( XGetWindowProperty( m_pDisplay,
2226 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
2227 m_aWMAtoms[ NET_CURRENT_DESKTOP ],
2228 0, 1,
2229 False,
2230 XA_CARDINAL,
2231 &aRealType,
2232 &nFormat,
2233 &nItems,
2234 &nBytesLeft,
2235 &pProperty ) == 0
2236 && pProperty
2239 nCurrent = int(*(sal_Int32*)pProperty);
2240 XFree( pProperty );
2242 else if( pProperty )
2244 XFree( pProperty );
2245 pProperty = NULL;
2248 return nCurrent;
2252 * WMAdaptor::getWindowWorkArea
2254 int WMAdaptor::getWindowWorkArea( XLIB_Window aWindow ) const
2256 int nCurrent = -1;
2257 if( m_aWMAtoms[ NET_WM_DESKTOP ] )
2259 Atom aRealType = None;
2260 int nFormat = 8;
2261 unsigned long nItems = 0;
2262 unsigned long nBytesLeft = 0;
2263 unsigned char* pProperty = NULL;
2264 if( XGetWindowProperty( m_pDisplay,
2265 aWindow,
2266 m_aWMAtoms[ NET_WM_DESKTOP ],
2267 0, 1,
2268 False,
2269 XA_CARDINAL,
2270 &aRealType,
2271 &nFormat,
2272 &nItems,
2273 &nBytesLeft,
2274 &pProperty ) == 0
2275 && pProperty
2278 nCurrent = int(*(sal_Int32*)pProperty);
2279 XFree( pProperty );
2281 else if( pProperty )
2283 XFree( pProperty );
2284 pProperty = NULL;
2287 return nCurrent;
2291 * WMAdaptor::getCurrentWorkArea
2293 // fixme: multi screen case
2294 void WMAdaptor::switchToWorkArea( int nWorkArea ) const
2296 if( m_aWMAtoms[ NET_CURRENT_DESKTOP ] )
2298 XEvent aEvent;
2299 aEvent.type = ClientMessage;
2300 aEvent.xclient.display = m_pDisplay;
2301 aEvent.xclient.window = m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() );
2302 aEvent.xclient.message_type = m_aWMAtoms[ NET_CURRENT_DESKTOP ];
2303 aEvent.xclient.format = 32;
2304 aEvent.xclient.data.l[0] = nWorkArea;
2305 aEvent.xclient.data.l[1] = 0;
2306 aEvent.xclient.data.l[2] = 0;
2307 aEvent.xclient.data.l[3] = 0;
2308 aEvent.xclient.data.l[4] = 0;
2309 XSendEvent( m_pDisplay,
2310 m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultScreenNumber() ),
2311 False,
2312 SubstructureNotifyMask | SubstructureRedirectMask,
2313 &aEvent
2319 * WMAdaptor::frameIsMapping
2321 void WMAdaptor::frameIsMapping( X11SalFrame* ) const
2326 * NetWMAdaptor::frameIsMapping
2328 void NetWMAdaptor::frameIsMapping( X11SalFrame* pFrame ) const
2330 setNetWMState( pFrame );
2334 * WMAdaptor::setFrameStruts
2336 void WMAdaptor::setFrameStruts( X11SalFrame*,
2337 int, int, int, int,
2338 int, int, int, int,
2339 int, int, int, int ) const
2344 * NetWMAdaptor::setFrameStruts
2346 void NetWMAdaptor::setFrameStruts( X11SalFrame* pFrame,
2347 int left, int right, int top, int bottom,
2348 int left_start_y, int left_end_y,
2349 int right_start_y, int right_end_y,
2350 int top_start_x, int top_end_x,
2351 int bottom_start_x, int bottom_end_x ) const
2353 long nData[12];
2354 nData[0] = left;
2355 nData[1] = right;
2356 nData[2] = top;
2357 nData[3] = bottom;
2358 nData[4] = left_start_y;
2359 nData[5] = left_end_y;
2360 nData[6] = right_start_y;
2361 nData[7] = right_end_y;
2362 nData[8] = top_start_x;
2363 nData[9] = top_end_x;
2364 nData[10]= bottom_start_x;
2365 nData[11]= bottom_end_x;
2366 Atom aProperty = None;
2367 int nSetData = 0;
2369 if( m_aWMAtoms[NET_WM_STRUT_PARTIAL] )
2371 aProperty = m_aWMAtoms[NET_WM_STRUT_PARTIAL];
2372 nSetData = 12;
2374 else if( m_aWMAtoms[NET_WM_STRUT] )
2376 aProperty = m_aWMAtoms[NET_WM_STRUT];
2377 nSetData = 4;
2379 if( nSetData )
2381 XChangeProperty( m_pDisplay,
2382 pFrame->GetShellWindow(),
2383 aProperty,
2384 XA_CARDINAL,
2386 PropModeReplace,
2387 (unsigned char*)&nData,
2388 nSetData
2394 * WMAdaptor::setUserTime
2396 void WMAdaptor::setUserTime( X11SalFrame*, long ) const
2401 * NetWMAdaptor::setUserTime
2403 void NetWMAdaptor::setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const
2405 if( m_aWMAtoms[NET_WM_USER_TIME] )
2407 XChangeProperty( m_pDisplay,
2408 i_pFrame->GetShellWindow(),
2409 m_aWMAtoms[NET_WM_USER_TIME],
2410 XA_CARDINAL,
2412 PropModeReplace,
2413 (unsigned char*)&i_nUserTime,