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