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" { 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 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 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 421 WMAdaptor::~WMAdaptor() 422 { 423 } 424 425 /* 426 * NetWMAdaptor constructor 427 */ 428 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 */ 614 NetWMAdaptor::~NetWMAdaptor() 615 { 616 } 617 618 /* 619 * GnomeWMAdaptor constructor 620 */ 621 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 */ 825 GnomeWMAdaptor::~GnomeWMAdaptor() 826 { 827 } 828 829 /* 830 * getNetWmName() 831 */ 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 974 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 */ 1001 bool WMAdaptor::isValid() const 1002 { 1003 return true; 1004 } 1005 1006 /* 1007 * NetWMAdaptor::isValid() 1008 */ 1009 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 */ 1026 bool GnomeWMAdaptor::isValid() const 1027 { 1028 return m_bValid; 1029 } 1030 1031 /* 1032 * WMAdaptor::initAtoms 1033 */ 1034 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 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 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 1073 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 */ 1191 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 */ 1225 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 */ 1343 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 1435 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 1525 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 1597 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 1719 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 1786 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 1839 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 1850 bool NetWMAdaptor::supportsICCCMPos() const 1851 { 1852 return true; 1853 } 1854 1855 1856 /* 1857 * WMAdaptor::enableAlwaysOnTop 1858 */ 1859 void WMAdaptor::enableAlwaysOnTop( X11SalFrame*, bool /*bEnable*/ ) const 1860 { 1861 } 1862 1863 /* 1864 * NetWMAdaptor::enableAlwaysOnTop 1865 */ 1866 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 */ 1900 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 */ 1945 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 */ 1968 int WMAdaptor::handlePropertyNotify( X11SalFrame*, XPropertyEvent* ) const 1969 { 1970 return 0; 1971 } 1972 1973 /* 1974 * NetWMAdaptor::handlePropertyNotify 1975 */ 1976 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 */ 2052 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 */ 2118 void WMAdaptor::shade( X11SalFrame*, bool /*bToShaded*/ ) const 2119 { 2120 } 2121 2122 /* 2123 * NetWMAdaptor::shade 2124 */ 2125 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 */ 2165 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 */ 2199 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 */ 2208 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 2292 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 */ 2331 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 2371 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 */ 2401 void WMAdaptor::frameIsMapping( X11SalFrame* ) const 2402 { 2403 } 2404 2405 /* 2406 * NetWMAdaptor::frameIsMapping 2407 */ 2408 void NetWMAdaptor::frameIsMapping( X11SalFrame* pFrame ) const 2409 { 2410 setNetWMState( pFrame ); 2411 } 2412 2413 /* 2414 * WMAdaptor::setFrameStruts 2415 */ 2416 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 */ 2426 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 */ 2476 void WMAdaptor::setUserTime( X11SalFrame*, long ) const 2477 { 2478 } 2479 2480 /* 2481 * NetWMAdaptor::setUserTime 2482 */ 2483 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 */ 2502 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 */ 2522 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, aWmClient.getLength() }; 2526 XSetWMClientMachine( m_pDisplay, i_pFrame->GetShellWindow(), &aClientProp ); 2527 } 2528 2529 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 */ 2551 void WMAdaptor::setFullScreenMonitors( XLIB_Window, sal_Int32 ) 2552 { 2553 } 2554 2555 /* 2556 * NetWMAdaptor::setFullScreenMonitors 2557 */ 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