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