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 #include <unistd.h> 35 36 #include "tools/debug.hxx" 37 38 #include "sal/alloca.h" 39 40 #include "vcl/floatwin.hxx" 41 #include "vcl/svapp.hxx" 42 #include "vcl/keycodes.hxx" 43 #include "vcl/printerinfomanager.hxx" 44 #include "vcl/settings.hxx" 45 46 #include <tools/prex.h> 47 #include <X11/Xatom.h> 48 #include <X11/keysym.h> 49 #include "FWS.hxx" 50 #include <X11/extensions/shape.h> 51 #ifndef SOLARIS 52 #include <X11/extensions/dpms.h> 53 #endif 54 #include <tools/postx.h> 55 56 #include "unx/salunx.h" 57 #include "unx/saldata.hxx" 58 #include "unx/saldisp.hxx" 59 #include "unx/salgdi.h" 60 #include "unx/salframe.h" 61 #include "unx/soicon.hxx" 62 #include "unx/dtint.hxx" 63 #include "unx/sm.hxx" 64 #include "unx/wmadaptor.hxx" 65 #include "unx/salprn.h" 66 #include "unx/salbmp.h" 67 #include "unx/i18n_ic.hxx" 68 #include "unx/i18n_keysym.hxx" 69 #include "unx/i18n_status.hxx" 70 71 #include "salinst.hxx" 72 #include "sallayout.hxx" 73 74 #include <com/sun/star/uno/Exception.hpp> 75 76 #include <algorithm> 77 78 #ifndef Button6 79 # define Button6 6 80 #endif 81 #ifndef Button7 82 # define Button7 7 83 #endif 84 85 using namespace vcl_sal; 86 using namespace vcl; 87 88 // -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 89 #define CLIENT_EVENTS StructureNotifyMask \ 90 | SubstructureNotifyMask \ 91 | KeyPressMask \ 92 | KeyReleaseMask \ 93 | ButtonPressMask \ 94 | ButtonReleaseMask \ 95 | PointerMotionMask \ 96 | EnterWindowMask \ 97 | LeaveWindowMask \ 98 | FocusChangeMask \ 99 | ExposureMask \ 100 | VisibilityChangeMask \ 101 | PropertyChangeMask \ 102 | ColormapChangeMask 103 104 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 105 106 static XLIB_Window hPresentationWindow = None, hPresFocusWindow = None; 107 static ::std::list< XLIB_Window > aPresentationReparentList; 108 static int nVisibleFloats = 0; 109 110 X11SalFrame* X11SalFrame::s_pSaveYourselfFrame = NULL; 111 112 // -=-= C++ statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 113 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 114 static void doReparentPresentationDialogues( SalDisplay* pDisplay ) 115 { 116 pDisplay->GetXLib()->PushXErrorLevel( true ); 117 while( aPresentationReparentList.begin() != aPresentationReparentList.end() ) 118 { 119 int x, y; 120 XLIB_Window aRoot, aChild; 121 unsigned int w, h, bw, d; 122 XGetGeometry( pDisplay->GetDisplay(), 123 aPresentationReparentList.front(), 124 &aRoot, 125 &x, &y, &w, &h, &bw, &d ); 126 XTranslateCoordinates( pDisplay->GetDisplay(), 127 hPresentationWindow, 128 aRoot, 129 x, y, 130 &x, &y, 131 &aChild ); 132 XReparentWindow( pDisplay->GetDisplay(), 133 aPresentationReparentList.front(), 134 aRoot, 135 x, y ); 136 aPresentationReparentList.pop_front(); 137 } 138 if( hPresFocusWindow ) 139 XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot, CurrentTime ); 140 XSync( pDisplay->GetDisplay(), False ); 141 pDisplay->GetXLib()->PopXErrorLevel(); 142 } 143 144 // -=-= SalFrame / X11SalFrame =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 145 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 146 147 bool X11SalFrame::IsOverrideRedirect() const 148 { 149 return 150 ((nStyle_ & SAL_FRAME_STYLE_INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash()) 151 || 152 (!( nStyle_ & ~SAL_FRAME_STYLE_DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen()) 153 ; 154 } 155 156 bool X11SalFrame::IsFloatGrabWindow() const 157 { 158 static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" ); 159 160 return 161 ( ( !pDisableGrab || !*pDisableGrab ) && 162 ( 163 (nStyle_ & SAL_FRAME_STYLE_FLOAT) && 164 ! (nStyle_ & SAL_FRAME_STYLE_TOOLTIP) && 165 ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) 166 ) 167 ); 168 } 169 170 void X11SalFrame::setXEmbedInfo() 171 { 172 if( m_bXEmbed ) 173 { 174 long aInfo[2]; 175 aInfo[0] = 1; // XEMBED protocol version 176 aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED 177 XChangeProperty( pDisplay_->GetDisplay(), 178 mhWindow, 179 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ), 180 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ), 181 32, 182 PropModeReplace, 183 reinterpret_cast<unsigned char*>(aInfo), 184 sizeof(aInfo)/sizeof(aInfo[0]) ); 185 } 186 } 187 188 void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode ) 189 { 190 XEvent aEvent; 191 192 rtl_zeroMemory( &aEvent, sizeof(aEvent) ); 193 aEvent.xclient.window = mhForeignParent; 194 aEvent.xclient.type = ClientMessage; 195 aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED ); 196 aEvent.xclient.format = 32; 197 aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime; 198 aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS 199 aEvent.xclient.data.l[2] = 0; 200 aEvent.xclient.data.l[3] = 0; 201 aEvent.xclient.data.l[4] = 0; 202 203 GetDisplay()->GetXLib()->PushXErrorLevel( true ); 204 XSendEvent( pDisplay_->GetDisplay(), 205 mhForeignParent, 206 False, NoEventMask, &aEvent ); 207 XSync( pDisplay_->GetDisplay(), False ); 208 GetDisplay()->GetXLib()->PopXErrorLevel(); 209 } 210 211 212 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 213 214 void X11SalFrame::Init( sal_uLong nSalFrameStyle, int nScreen, SystemParentData* pParentData, bool bUseGeometry ) 215 { 216 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) 217 nScreen = GetDisplay()->GetDefaultScreenNumber(); 218 if( mpParent ) 219 nScreen = mpParent->m_nScreen; 220 221 m_nScreen = nScreen; 222 nStyle_ = nSalFrameStyle; 223 XWMHints Hints; 224 Hints.flags = InputHint; 225 Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True; 226 227 int x = 0, y = 0; 228 unsigned int w = 500, h = 500; 229 XSetWindowAttributes Attributes; 230 231 int nAttrMask = CWBorderPixel 232 | CWBackPixmap 233 | CWColormap 234 | CWOverrideRedirect 235 | CWEventMask 236 ; 237 Attributes.border_pixel = 0; 238 Attributes.background_pixmap = None; 239 Attributes.colormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap(); 240 Attributes.override_redirect = False; 241 Attributes.event_mask = CLIENT_EVENTS; 242 243 const SalVisual& rVis = GetDisplay()->GetVisual( m_nScreen ); 244 XLIB_Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nScreen ); 245 XLIB_Window aClientLeader = None; 246 247 if( bUseGeometry ) 248 { 249 x = maGeometry.nX; 250 y = maGeometry.nY; 251 w = maGeometry.nWidth; 252 h = maGeometry.nHeight; 253 } 254 255 if( (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT) && 256 ! (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) 257 ) 258 { 259 if( nShowState_ == SHOWSTATE_UNKNOWN ) 260 { 261 w = 10; 262 h = 10; 263 } 264 Attributes.override_redirect = True; 265 } 266 else if( (nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) ) 267 { 268 DBG_ASSERT( mpParent, "SAL_FRAME_STYLE_SYSTEMCHILD window without parent" ); 269 if( mpParent ) 270 { 271 aFrameParent = mpParent->mhWindow; 272 // FIXME: since with SAL_FRAME_STYLE_SYSTEMCHILD 273 // multiple X11SalFrame objects can have the same shell window 274 // dispatching events in saldisp.cxx is unclear (the first frame) 275 // wins. HTH this correctly is unclear yet 276 // for the time being, treat set the shell window to own window 277 // like for a normal frame 278 // mhShellWindow = mpParent->GetShellWindow(); 279 } 280 } 281 else if( pParentData ) 282 { 283 // plugin parent may be killed unexpectedly by 284 // plugging process; ignore XErrors in that case 285 GetDisplay()->setHaveSystemChildFrame(); 286 287 nStyle_ |= SAL_FRAME_STYLE_PLUG; 288 Attributes.override_redirect = True; 289 if( pParentData->nSize >= sizeof(SystemParentData) ) 290 m_bXEmbed = pParentData->bXEmbedSupport; 291 292 int x_ret, y_ret; 293 unsigned int bw, d; 294 XLIB_Window aRoot, aParent; 295 296 XGetGeometry( GetXDisplay(), pParentData->aWindow, 297 &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d ); 298 mhForeignParent = pParentData->aWindow; 299 300 mhShellWindow = aParent = mhForeignParent; 301 XLIB_Window* pChildren; 302 unsigned int nChildren; 303 bool bBreak = false; 304 do 305 { 306 XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow, 307 &aRoot, &aParent, &pChildren, &nChildren ); 308 XFree( pChildren ); 309 if( aParent != aRoot ) 310 mhShellWindow = aParent; 311 int nCount = 0; 312 Atom* pProps = XListProperties( GetDisplay()->GetDisplay(), 313 mhShellWindow, 314 &nCount ); 315 for( int i = 0; i < nCount && ! bBreak; ++i ) 316 bBreak = (pProps[i] == XA_WM_HINTS); 317 if( pProps ) 318 XFree( pProps ); 319 } while( aParent != aRoot && ! bBreak ); 320 321 // check if this is really one of our own frames 322 // do not change the input mask in that case 323 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); 324 std::list< SalFrame* >::const_iterator it = rFrames.begin(); 325 while( it != rFrames.end() && mhForeignParent != static_cast<const X11SalFrame*>(*it)->GetWindow() ) 326 ++it; 327 328 if( it == rFrames.end() ) 329 { 330 XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask | FocusChangeMask ); 331 XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask | FocusChangeMask ); 332 } 333 } 334 else 335 { 336 if( ! bUseGeometry ) 337 { 338 Size aScreenSize( GetDisplay()->getDataForScreen( m_nScreen ).m_aSize ); 339 w = aScreenSize.Width(); 340 h = aScreenSize.Height(); 341 if( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE && 342 nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) 343 { 344 // fill in holy default values brought to us by product management 345 if( aScreenSize.Width() >= 800 ) 346 w = 785; 347 if( aScreenSize.Width() >= 1024 ) 348 w = 920; 349 350 if( aScreenSize.Height() >= 600 ) 351 h = 550; 352 if( aScreenSize.Height() >= 768 ) 353 h = 630; 354 if( aScreenSize.Height() >= 1024 ) 355 h = 875; 356 } 357 if( ! mpParent ) 358 { 359 // find the last document window (if any) 360 const X11SalFrame* pFrame = NULL; 361 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); 362 std::list< SalFrame* >::const_iterator it = rFrames.begin(); 363 while( it != rFrames.end() ) 364 { 365 pFrame = static_cast< const X11SalFrame* >(*it); 366 if( ! ( pFrame->mpParent 367 || pFrame->mbFullScreen 368 || ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) 369 || ! pFrame->GetUnmirroredGeometry().nWidth 370 || ! pFrame->GetUnmirroredGeometry().nHeight 371 ) 372 ) 373 break; 374 ++it; 375 } 376 377 if( it != rFrames.end() ) 378 { 379 // set a document position and size 380 // the first frame gets positioned by the window manager 381 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() ); 382 x = rGeom.nX; 383 y = rGeom.nY; 384 if( x+(int)w+40 <= (int)aScreenSize.Width() && 385 y+(int)h+40 <= (int)aScreenSize.Height() 386 ) 387 { 388 y += 40; 389 x += 40; 390 } 391 else 392 { 393 x = 10; // leave some space for decoration 394 y = 20; 395 } 396 } 397 else if( GetDisplay()->IsXinerama() ) 398 { 399 // place frame on same screen as mouse pointer 400 XLIB_Window aRoot, aChild; 401 int root_x = 0, root_y = 0, lx, ly; 402 unsigned int mask; 403 XQueryPointer( GetXDisplay(), 404 GetDisplay()->GetRootWindow( m_nScreen ), 405 &aRoot, &aChild, 406 &root_x, &root_y, &lx, &ly, &mask ); 407 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens(); 408 for( unsigned int i = 0; i < rScreens.size(); i++ ) 409 if( rScreens[i].IsInside( Point( root_x, root_y ) ) ) 410 { 411 x = rScreens[i].Left(); 412 y = rScreens[i].Top(); 413 break; 414 } 415 } 416 } 417 } 418 Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity(); 419 nAttrMask |= CWWinGravity; 420 if( mpParent ) 421 { 422 Attributes.save_under = True; 423 nAttrMask |= CWSaveUnder; 424 } 425 if( IsOverrideRedirect() ) 426 Attributes.override_redirect = True; 427 // default icon 428 if( (nStyle_ & SAL_FRAME_STYLE_INTRO) == 0 ) 429 { 430 bool bOk=false; 431 try 432 { 433 bOk=SelectAppIconPixmap( pDisplay_, m_nScreen, 434 mnIconID != 1 ? mnIconID : 435 (mpParent ? mpParent->mnIconID : 1), 32, 436 Hints.icon_pixmap, Hints.icon_mask ); 437 } 438 catch( com::sun::star::uno::Exception& ) 439 { 440 // can happen - no ucb during early startup 441 } 442 if( bOk ) 443 { 444 Hints.flags |= IconPixmapHint; 445 if( Hints.icon_mask ) 446 Hints.flags |= IconMaskHint; 447 } 448 } 449 450 // find the top level frame of the transience hierarchy 451 X11SalFrame* pFrame = this; 452 while( pFrame->mpParent ) 453 pFrame = pFrame->mpParent; 454 if( (pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) ) 455 { 456 // if the top level window is a plugin window, 457 // then we should place us in the same window group as 458 // the parent application (or none if there is no window group 459 // hint in the parent). 460 if( pFrame->GetShellWindow() ) 461 { 462 XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(), 463 pFrame->GetShellWindow() ); 464 if( pWMHints ) 465 { 466 if( (pWMHints->flags & WindowGroupHint) ) 467 { 468 Hints.flags |= WindowGroupHint; 469 Hints.window_group = pWMHints->window_group; 470 } 471 XFree( pWMHints ); 472 } 473 } 474 } 475 else 476 { 477 Hints.flags |= WindowGroupHint; 478 Hints.window_group = pFrame->GetShellWindow(); 479 // note: for a normal document window this will produce None 480 // as the window is not yet created and the shell window is 481 // initialized to None. This must be corrected after window creation. 482 aClientLeader = GetDisplay()->GetDrawable( m_nScreen ); 483 } 484 } 485 486 nShowState_ = SHOWSTATE_UNKNOWN; 487 bViewable_ = sal_True; 488 bMapped_ = sal_False; 489 nVisibility_ = VisibilityFullyObscured; 490 mhWindow = XCreateWindow( GetXDisplay(), 491 aFrameParent, 492 x, y, 493 w, h, 494 0, 495 rVis.GetDepth(), 496 InputOutput, 497 rVis.GetVisual(), 498 nAttrMask, 499 &Attributes ); 500 // FIXME: see above: fake shell window for now to own window 501 if( /*! IsSysChildWindow() &&*/ pParentData == NULL ) 502 { 503 mhShellWindow = mhWindow; 504 } 505 506 // correct window group if necessary 507 if( (Hints.flags & WindowGroupHint) == WindowGroupHint ) 508 { 509 if( Hints.window_group == None ) 510 Hints.window_group = GetShellWindow(); 511 } 512 513 maGeometry.nX = x; 514 maGeometry.nY = y; 515 maGeometry.nWidth = w; 516 maGeometry.nHeight = h; 517 updateScreenNumber(); 518 519 XSync( GetXDisplay(), False ); 520 setXEmbedInfo(); 521 522 XLIB_Time nUserTime = (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_TOOLWINDOW) ) == 0 ? 523 pDisplay_->GetLastUserEventTime() : 0; 524 pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime ); 525 526 if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect ) 527 { 528 XSetWMHints( GetXDisplay(), mhWindow, &Hints ); 529 // WM Protocols && internals 530 Atom a[4]; 531 int n = 0; 532 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW ); 533 if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) ) 534 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ); 535 if( ! s_pSaveYourselfFrame && ! mpParent) 536 { 537 // at all times have only one frame with SaveYourself 538 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF ); 539 s_pSaveYourselfFrame = this; 540 } 541 if( (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) 542 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS ); 543 XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n ); 544 545 XClassHint* pClass = XAllocClassHint(); 546 pClass->res_name = const_cast<char*>(X11SalData::getFrameResName()); 547 pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName()); 548 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass ); 549 XFree( pClass ); 550 551 XSizeHints* pHints = XAllocSizeHints(); 552 pHints->flags = PWinGravity | PPosition; 553 pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity(); 554 pHints->x = 0; 555 pHints->y = 0; 556 if( mbFullScreen ) 557 { 558 pHints->flags |= PMaxSize | PMinSize; 559 pHints->max_width = w+100; 560 pHints->max_height = h+100; 561 pHints->min_width = w; 562 pHints->min_height = h; 563 } 564 XSetWMNormalHints( GetXDisplay(), 565 GetShellWindow(), 566 pHints ); 567 XFree (pHints); 568 569 // set PID and WM_CLIENT_MACHINE 570 pDisplay_->getWMAdaptor()->setClientMachine( this ); 571 pDisplay_->getWMAdaptor()->setPID( this ); 572 573 // set client leader 574 if( aClientLeader ) 575 { 576 XChangeProperty( GetXDisplay(), 577 mhWindow, 578 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER), 579 XA_WINDOW, 580 32, 581 PropModeReplace, 582 (unsigned char*)&aClientLeader, 583 1 584 ); 585 } 586 #define DECOFLAGS (SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE) 587 int nDecoFlags = WMAdaptor::decoration_All; 588 if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) || 589 (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) 590 ) 591 nDecoFlags = 0; 592 else if( (nStyle_ & DECOFLAGS ) != DECOFLAGS || (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) 593 { 594 if( nStyle_ & DECOFLAGS ) 595 // if any decoration, then show a border 596 nDecoFlags = WMAdaptor::decoration_Border; 597 else 598 nDecoFlags = 0; 599 600 if( ! mpParent && (nStyle_ & DECOFLAGS) ) 601 // don't add a min button if window should be decorationless 602 nDecoFlags |= WMAdaptor::decoration_MinimizeBtn; 603 if( nStyle_ & SAL_FRAME_STYLE_CLOSEABLE ) 604 nDecoFlags |= WMAdaptor::decoration_CloseBtn; 605 if( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) 606 { 607 nDecoFlags |= WMAdaptor::decoration_Resize; 608 if( ! (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) 609 nDecoFlags |= WMAdaptor::decoration_MaximizeBtn; 610 } 611 if( nStyle_ & SAL_FRAME_STYLE_MOVEABLE ) 612 nDecoFlags |= WMAdaptor::decoration_Title; 613 } 614 615 WMAdaptor::WMWindowType eType = WMAdaptor::windowType_Normal; 616 if( nStyle_ & SAL_FRAME_STYLE_INTRO ) 617 eType = WMAdaptor::windowType_Splash; 618 if( (nStyle_ & SAL_FRAME_STYLE_DIALOG) && hPresentationWindow == None ) 619 eType = WMAdaptor::windowType_ModelessDialogue; 620 if( nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW ) 621 eType = WMAdaptor::windowType_Utility; 622 if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION ) 623 eType = WMAdaptor::windowType_Toolbar; 624 if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) 625 && GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) 626 eType = WMAdaptor::windowType_Dock; 627 628 GetDisplay()->getWMAdaptor()-> 629 setFrameTypeAndDecoration( this, 630 eType, 631 nDecoFlags, 632 hPresentationWindow ? NULL : mpParent ); 633 634 if( (nStyle_ & (SAL_FRAME_STYLE_DEFAULT | 635 SAL_FRAME_STYLE_OWNERDRAWDECORATION| 636 SAL_FRAME_STYLE_FLOAT | 637 SAL_FRAME_STYLE_INTRO | 638 SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ) 639 == SAL_FRAME_STYLE_DEFAULT ) 640 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true ); 641 } 642 643 m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea(); 644 645 // Pointer 646 SetPointer( POINTER_ARROW ); 647 } 648 649 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 650 X11SalFrame::X11SalFrame( SalFrame *pParent, sal_uLong nSalFrameStyle, SystemParentData* pSystemParent ) 651 { 652 X11SalData* pSalData = GetX11SalData(); 653 654 // initialize frame geometry 655 memset( &maGeometry, 0, sizeof(maGeometry) ); 656 657 mpParent = static_cast< X11SalFrame* >( pParent ); 658 659 mbTransientForRoot = false; 660 661 pDisplay_ = pSalData->GetDisplay(); 662 // insert frame in framelist 663 pDisplay_->registerFrame( this ); 664 665 mhWindow = None; 666 mhShellWindow = None; 667 mhStackingWindow = None; 668 mhForeignParent = None; 669 mhBackgroundPixmap = None; 670 m_bSetFocusOnMap = false; 671 672 pGraphics_ = NULL; 673 pFreeGraphics_ = NULL; 674 675 hCursor_ = None; 676 nCaptured_ = 0; 677 678 nReleaseTime_ = 0; 679 nKeyCode_ = 0; 680 nKeyState_ = 0; 681 nCompose_ = -1; 682 mbKeyMenu = false; 683 mbSendExtKeyModChange = false; 684 mnExtKeyMod = 0; 685 686 nShowState_ = SHOWSTATE_UNKNOWN; 687 nWidth_ = 0; 688 nHeight_ = 0; 689 nStyle_ = 0; 690 mnExtStyle = 0; 691 bAlwaysOnTop_ = sal_False; 692 693 // set bViewable_ to sal_True: hack GetClientSize to report something 694 // different to 0/0 before first map 695 bViewable_ = sal_True; 696 bMapped_ = sal_False; 697 bDefaultPosition_ = sal_True; 698 nVisibility_ = VisibilityFullyObscured; 699 m_nWorkArea = 0; 700 mbInShow = sal_False; 701 m_bXEmbed = false; 702 703 nScreenSaversTimeout_ = 0; 704 705 mpInputContext = NULL; 706 mbInputFocus = False; 707 708 maAlwaysOnTopRaiseTimer.SetTimeoutHdl( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise ) ); 709 maAlwaysOnTopRaiseTimer.SetTimeout( 100 ); 710 711 meWindowType = WMAdaptor::windowType_Normal; 712 mnDecorationFlags = WMAdaptor::decoration_All; 713 mbMaximizedVert = false; 714 mbMaximizedHorz = false; 715 mbShaded = false; 716 mbFullScreen = false; 717 718 mnIconID = 1; // ICON_DEFAULT 719 720 m_pClipRectangles = NULL; 721 m_nCurClipRect = 0; 722 m_nMaxClipRect = 0; 723 724 if( mpParent ) 725 mpParent->maChildren.push_back( this ); 726 727 Init( nSalFrameStyle, GetDisplay()->GetDefaultScreenNumber(), pSystemParent ); 728 } 729 730 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 731 732 void X11SalFrame::passOnSaveYourSelf() 733 { 734 if( this == s_pSaveYourselfFrame ) 735 { 736 // pass on SaveYourself 737 const X11SalFrame* pFrame = NULL; 738 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); 739 std::list< SalFrame* >::const_iterator it = rFrames.begin(); 740 while( it != rFrames.end() ) 741 { 742 pFrame = static_cast< const X11SalFrame* >(*it); 743 if( ! ( IsChildWindow() || pFrame->mpParent ) 744 && pFrame != s_pSaveYourselfFrame ) 745 break; 746 ++it; 747 } 748 749 s_pSaveYourselfFrame = (it != rFrames.end() ) ? const_cast<X11SalFrame*>(pFrame) : NULL; 750 if( s_pSaveYourselfFrame ) 751 { 752 Atom a[4]; 753 int n = 0; 754 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW ); 755 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF ); 756 if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) ) 757 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ); 758 XSetWMProtocols( GetXDisplay(), s_pSaveYourselfFrame->GetShellWindow(), a, n ); 759 } 760 } 761 } 762 763 X11SalFrame::~X11SalFrame() 764 { 765 notifyDelete(); 766 767 if( m_pClipRectangles ) 768 { 769 delete [] m_pClipRectangles; 770 m_pClipRectangles = NULL; 771 m_nCurClipRect = m_nMaxClipRect = 0; 772 } 773 774 if( mhBackgroundPixmap ) 775 { 776 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None ); 777 XFreePixmap( GetXDisplay(), mhBackgroundPixmap ); 778 } 779 780 if( mhStackingWindow ) 781 aPresentationReparentList.remove( mhStackingWindow ); 782 783 // remove from parent's list 784 if( mpParent ) 785 mpParent->maChildren.remove( this ); 786 787 // deregister on SalDisplay 788 pDisplay_->deregisterFrame( this ); 789 790 // unselect all events, some may be still in the queue anyway 791 if( ! IsSysChildWindow() ) 792 XSelectInput( GetXDisplay(), GetShellWindow(), 0 ); 793 XSelectInput( GetXDisplay(), GetWindow(), 0 ); 794 795 ShowFullScreen( sal_False, 0 ); 796 797 if( bMapped_ ) 798 Show( sal_False ); 799 800 if( mpInputContext ) 801 { 802 mpInputContext->UnsetICFocus( this ); 803 mpInputContext->Unmap( this ); 804 delete mpInputContext; 805 } 806 807 if( GetWindow() == hPresentationWindow ) 808 { 809 hPresentationWindow = None; 810 doReparentPresentationDialogues( GetDisplay() ); 811 } 812 813 if( pGraphics_ ) 814 { 815 pGraphics_->DeInit(); 816 delete pGraphics_; 817 } 818 819 if( pFreeGraphics_ ) 820 { 821 pFreeGraphics_->DeInit(); 822 delete pFreeGraphics_; 823 } 824 825 826 XDestroyWindow( GetXDisplay(), mhWindow ); 827 828 /* 829 * check if there is only the status frame left 830 * if so, free it 831 */ 832 if( ! GetDisplay()->getFrames().empty() && I18NStatus::exists() ) 833 { 834 SalFrame* pStatusFrame = I18NStatus::get().getStatusFrame(); 835 std::list< SalFrame* >::const_iterator sit = GetDisplay()->getFrames().begin(); 836 if( pStatusFrame 837 && *sit == pStatusFrame 838 && ++sit == GetDisplay()->getFrames().end() ) 839 vcl::I18NStatus::free(); 840 } 841 842 passOnSaveYourSelf(); 843 } 844 845 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 846 847 void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) 848 { 849 if( nStyle != mnExtStyle && ! IsChildWindow() ) 850 { 851 mnExtStyle = nStyle; 852 853 XClassHint* pClass = XAllocClassHint(); 854 rtl::OString aResHint = X11SalData::getFrameResName( mnExtStyle ); 855 pClass->res_name = const_cast<char*>(aResHint.getStr()); 856 pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName()); 857 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass ); 858 XFree( pClass ); 859 } 860 } 861 862 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 863 864 void X11SalFrame::SetBackgroundBitmap( SalBitmap* pBitmap ) 865 { 866 if( mhBackgroundPixmap ) 867 { 868 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None ); 869 XFreePixmap( GetXDisplay(), mhBackgroundPixmap ); 870 mhBackgroundPixmap = None; 871 } 872 if( pBitmap ) 873 { 874 X11SalBitmap* pBM = static_cast<X11SalBitmap*>(pBitmap); 875 Size aSize = pBM->GetSize(); 876 if( aSize.Width() && aSize.Height() ) 877 { 878 mhBackgroundPixmap = 879 XCreatePixmap( GetXDisplay(), 880 GetWindow(), 881 aSize.Width(), 882 aSize.Height(), 883 GetDisplay()->GetVisual( m_nScreen ).GetDepth() ); 884 if( mhBackgroundPixmap ) 885 { 886 SalTwoRect aTwoRect; 887 aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0; 888 aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width(); 889 aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height(); 890 pBM->ImplDraw( mhBackgroundPixmap, 891 m_nScreen, 892 GetDisplay()->GetVisual( m_nScreen ).GetDepth(), 893 aTwoRect, GetDisplay()->GetCopyGC( m_nScreen ) ); 894 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), mhBackgroundPixmap ); 895 } 896 } 897 } 898 } 899 900 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 901 902 const SystemChildData* X11SalFrame::GetSystemData() const 903 { 904 X11SalFrame *pFrame = const_cast<X11SalFrame*>(this); 905 pFrame->maSystemChildData.nSize = sizeof( SystemChildData ); 906 pFrame->maSystemChildData.pDisplay = GetXDisplay(); 907 pFrame->maSystemChildData.aWindow = pFrame->GetWindow(); 908 pFrame->maSystemChildData.pSalFrame = pFrame; 909 pFrame->maSystemChildData.pWidget = NULL; 910 pFrame->maSystemChildData.pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual(); 911 pFrame->maSystemChildData.nScreen = m_nScreen; 912 pFrame->maSystemChildData.nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth(); 913 pFrame->maSystemChildData.aColormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap(); 914 pFrame->maSystemChildData.pAppContext = NULL; 915 pFrame->maSystemChildData.aShellWindow = pFrame->GetShellWindow(); 916 pFrame->maSystemChildData.pShellWidget = NULL; 917 return &maSystemChildData; 918 } 919 920 SalGraphics *X11SalFrame::GetGraphics() 921 { 922 if( pGraphics_ ) 923 return NULL; 924 925 if( pFreeGraphics_ ) 926 { 927 pGraphics_ = pFreeGraphics_; 928 pFreeGraphics_ = NULL; 929 } 930 else 931 { 932 pGraphics_ = new X11SalGraphics(); 933 pGraphics_->Init( this, GetWindow(), m_nScreen ); 934 } 935 936 return pGraphics_; 937 } 938 939 void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics ) 940 { 941 DBG_ASSERT( pGraphics == pGraphics_, "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" ); 942 943 if( pGraphics != pGraphics_ ) 944 return; 945 946 pFreeGraphics_ = pGraphics_; 947 pGraphics_ = NULL; 948 } 949 950 void X11SalFrame::updateGraphics( bool bClear ) 951 { 952 Drawable aDrawable = bClear ? None : GetWindow(); 953 if( pGraphics_ ) 954 pGraphics_->SetDrawable( aDrawable, m_nScreen ); 955 if( pFreeGraphics_ ) 956 pFreeGraphics_->SetDrawable( aDrawable, m_nScreen ); 957 } 958 959 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 960 961 void X11SalFrame::Enable( sal_Bool /*bEnable*/ ) 962 { 963 // NYI: enable/disable frame 964 } 965 966 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 967 968 void X11SalFrame::SetIcon( sal_uInt16 nIcon ) 969 { 970 if ( ! IsChildWindow() ) 971 { 972 // 0 == default icon -> #1 973 if ( nIcon == 0 ) 974 nIcon = 1; 975 976 mnIconID = nIcon; 977 978 XIconSize *pIconSize = NULL; 979 int nSizes = 0; 980 int iconSize = 32; 981 if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ), &pIconSize, &nSizes ) ) 982 { 983 #if OSL_DEBUG_LEVEL > 1 984 fprintf(stderr, "X11SalFrame::SetIcon(): found %d IconSizes:\n", nSizes); 985 #endif 986 987 const int ourLargestIconSize = 48; 988 bool bFoundIconSize = false; 989 990 int i; 991 for( i=0; i<nSizes; i++) 992 { 993 // select largest supported icon 994 995 // Note: olwm/olvwm reports a huge max icon size of 996 // 160x160 pixels; always choosing the max as the 997 // preferred icon size is apparently wrong under olvwm 998 // - so we keep the safe default |iconSize| when we see 999 // unreasonable large max icon sizes (> twice of our 1000 // largest available icon) reported by XGetIconSizes. 1001 if( pIconSize[i].max_width > iconSize 1002 && pIconSize[i].max_width <= 2*ourLargestIconSize ) 1003 { 1004 iconSize = pIconSize[i].max_width; 1005 bFoundIconSize = true; 1006 } 1007 iconSize = pIconSize[i].max_width; 1008 1009 #if OSL_DEBUG_LEVEL > 1 1010 fprintf(stderr, "min: %d, %d\nmax: %d, %d\ninc: %d, %d\n\n", 1011 pIconSize[i].min_width, pIconSize[i].min_height, 1012 pIconSize[i].max_width, pIconSize[i].max_height, 1013 pIconSize[i].width_inc, pIconSize[i].height_inc); 1014 #endif 1015 } 1016 1017 if ( !bFoundIconSize ) 1018 { 1019 // Unless someone has fixed olwm/olvwm, we have rejected 1020 // the max icon size from |XGetIconSizes()|. Provide a 1021 // better icon size default value, in case our window manager 1022 // is olwm/olvwm. 1023 const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() ); 1024 1025 if ( rWM.EqualsAscii( "Olwm" ) ) 1026 iconSize = 48; 1027 } 1028 1029 XFree( pIconSize ); 1030 } 1031 else 1032 { 1033 const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() ); 1034 if( rWM.EqualsAscii( "KWin" ) ) // assume KDE is running 1035 iconSize = 48; 1036 static bool bGnomeIconSize = false; 1037 static bool bGnomeChecked = false; 1038 if( ! bGnomeChecked ) 1039 { 1040 bGnomeChecked=true; 1041 int nCount = 0; 1042 Atom* pProps = XListProperties( GetXDisplay(), 1043 GetDisplay()->GetRootWindow( m_nScreen ), 1044 &nCount ); 1045 for( int i = 0; i < nCount && !bGnomeIconSize; i++ ) 1046 { 1047 char* pName = XGetAtomName( GetXDisplay(), pProps[i] ); 1048 if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) ) 1049 bGnomeIconSize = true; 1050 if( pName ) 1051 XFree( pName ); 1052 } 1053 if( pProps ) 1054 XFree( pProps ); 1055 } 1056 if( bGnomeIconSize ) 1057 iconSize = 48; 1058 } 1059 1060 XWMHints Hints; 1061 Hints.flags = 0; 1062 XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() ); 1063 if( pHints ) 1064 { 1065 memcpy(&Hints, pHints, sizeof( XWMHints )); 1066 XFree( pHints ); 1067 } 1068 pHints = &Hints; 1069 1070 sal_Bool bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen, 1071 nIcon, iconSize, 1072 pHints->icon_pixmap, pHints->icon_mask ); 1073 if ( !bOk ) 1074 { 1075 // load default icon (0) 1076 bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen, 1077 0, iconSize, 1078 pHints->icon_pixmap, pHints->icon_mask ); 1079 } 1080 if( bOk ) 1081 { 1082 pHints->flags |= IconPixmapHint; 1083 if( pHints->icon_mask ) 1084 pHints->flags |= IconMaskHint; 1085 1086 XSetWMHints( GetXDisplay(), GetShellWindow(), pHints ); 1087 } 1088 } 1089 } 1090 1091 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1092 1093 void X11SalFrame::SetMaxClientSize( long nWidth, long nHeight ) 1094 { 1095 if( ! IsChildWindow() ) 1096 { 1097 if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) 1098 { 1099 XSizeHints* pHints = XAllocSizeHints(); 1100 long nSupplied = 0; 1101 XGetWMNormalHints( GetXDisplay(), 1102 GetShellWindow(), 1103 pHints, 1104 &nSupplied 1105 ); 1106 pHints->max_width = nWidth; 1107 pHints->max_height = nHeight; 1108 pHints->flags |= PMaxSize; 1109 XSetWMNormalHints( GetXDisplay(), 1110 GetShellWindow(), 1111 pHints ); 1112 XFree( pHints ); 1113 } 1114 } 1115 } 1116 1117 void X11SalFrame::SetMinClientSize( long nWidth, long nHeight ) 1118 { 1119 if( ! IsChildWindow() ) 1120 { 1121 if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) 1122 { 1123 XSizeHints* pHints = XAllocSizeHints(); 1124 long nSupplied = 0; 1125 XGetWMNormalHints( GetXDisplay(), 1126 GetShellWindow(), 1127 pHints, 1128 &nSupplied 1129 ); 1130 pHints->min_width = nWidth; 1131 pHints->min_height = nHeight; 1132 pHints->flags |= PMinSize; 1133 XSetWMNormalHints( GetXDisplay(), 1134 GetShellWindow(), 1135 pHints ); 1136 XFree( pHints ); 1137 } 1138 } 1139 } 1140 1141 // Show + Pos (x,y,z) + Size (width,height) 1142 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1143 void X11SalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate ) 1144 { 1145 if( ( bVisible && bMapped_ ) 1146 || ( !bVisible && !bMapped_ ) ) 1147 return; 1148 1149 // HACK: this is a workaround for (at least) kwin 1150 // even though transient frames should be kept above their parent 1151 // this does not necessarily hold true for DOCK type windows 1152 // so artificially set ABOVE and remove it again on hide 1153 if( mpParent && (mpParent->nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) && pDisplay_->getWMAdaptor()->isLegacyPartialFullscreen()) 1154 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible ); 1155 1156 bMapped_ = bVisible; 1157 bViewable_ = bVisible; 1158 setXEmbedInfo(); 1159 if( bVisible ) 1160 { 1161 SessionManagerClient::open(); // will simply return after the first time 1162 1163 mbInShow = sal_True; 1164 if( ! (nStyle_ & SAL_FRAME_STYLE_INTRO) ) 1165 { 1166 // hide all INTRO frames 1167 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); 1168 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) 1169 { 1170 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); 1171 // look for intro bit map; if present, hide it 1172 if( pFrame->nStyle_ & SAL_FRAME_STYLE_INTRO ) 1173 { 1174 if( pFrame->bMapped_ ) 1175 const_cast<X11SalFrame*>(pFrame)->Show( sal_False ); 1176 } 1177 } 1178 } 1179 1180 // update NET_WM_STATE which may have been deleted due to earlier Show(sal_False) 1181 if( nShowState_ == SHOWSTATE_HIDDEN ) 1182 GetDisplay()->getWMAdaptor()->frameIsMapping( this ); 1183 1184 /* 1185 * #95097# 1186 * Actually this is rather exotic and currently happens only in conjunction 1187 * with the basic dialogue editor, 1188 * which shows a frame and instantly hides it again. After that the 1189 * editor window is shown and the WM takes this as an opportunity 1190 * to show our hidden transient frame also. So Show( sal_False ) must 1191 * withdraw the frame AND delete the WM_TRANSIENT_FOR property. 1192 * In case the frame is shown again, the transient hint must be restored here. 1193 */ 1194 if( ! IsChildWindow() 1195 && ! IsOverrideRedirect() 1196 && ! IsFloatGrabWindow() 1197 && mpParent 1198 ) 1199 { 1200 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent ); 1201 } 1202 1203 // #i45160# switch to desktop where a dialog with parent will appear 1204 if( mpParent && mpParent->m_nWorkArea != m_nWorkArea ) 1205 GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea ); 1206 1207 if( IsFloatGrabWindow() && 1208 mpParent && 1209 nVisibleFloats == 0 && 1210 ! GetDisplay()->GetCaptureFrame() ) 1211 { 1212 /* #i39420# 1213 * outsmart KWin's "focus strictly under mouse" mode 1214 * which insists on taking the focus from the document 1215 * to the new float. Grab focus to parent frame BEFORE 1216 * showing the float (cannot grab it to the float 1217 * before show). 1218 */ 1219 XGrabPointer( GetXDisplay(), 1220 mpParent->GetWindow(), 1221 True, 1222 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 1223 GrabModeAsync, 1224 GrabModeAsync, 1225 None, 1226 mpParent ? mpParent->GetCursor() : None, 1227 CurrentTime 1228 ); 1229 } 1230 1231 XLIB_Time nUserTime = 0; 1232 if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) == 0 ) 1233 nUserTime = pDisplay_->GetLastUserEventTime( true ); 1234 GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime ); 1235 if( ! bNoActivate && (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) 1236 m_bSetFocusOnMap = true; 1237 1238 // actually map the window 1239 if( m_bXEmbed ) 1240 askForXEmbedFocus( 0 ); 1241 else 1242 { 1243 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() ) 1244 { 1245 if( IsChildWindow() ) 1246 XMapWindow( GetXDisplay(), GetShellWindow() ); 1247 XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS ); 1248 } 1249 if( nStyle_ & SAL_FRAME_STYLE_FLOAT ) 1250 XMapRaised( GetXDisplay(), GetWindow() ); 1251 else 1252 XMapWindow( GetXDisplay(), GetWindow() ); 1253 } 1254 XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS ); 1255 1256 if( maGeometry.nWidth > 0 1257 && maGeometry.nHeight > 0 1258 && ( nWidth_ != (int)maGeometry.nWidth 1259 || nHeight_ != (int)maGeometry.nHeight ) ) 1260 { 1261 nWidth_ = maGeometry.nWidth; 1262 nHeight_ = maGeometry.nHeight; 1263 } 1264 1265 XSync( GetXDisplay(), False ); 1266 1267 if( IsFloatGrabWindow() ) 1268 { 1269 /* 1270 * #95453# 1271 * Sawfish and twm can be switched to enter-exit focus behaviour. In this case 1272 * we must grab the pointer else the dumb WM will put the focus to the 1273 * override-redirect float window. The application window will be deactivated 1274 * which causes that the floats are destroyed, so the user can never click on 1275 * a menu because it vanishes as soon as he enters it. 1276 */ 1277 nVisibleFloats++; 1278 if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() ) 1279 { 1280 /* #i39420# now move grab to the new float window */ 1281 XGrabPointer( GetXDisplay(), 1282 GetWindow(), 1283 True, 1284 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 1285 GrabModeAsync, 1286 GrabModeAsync, 1287 None, 1288 mpParent ? mpParent->GetCursor() : None, 1289 CurrentTime 1290 ); 1291 } 1292 } 1293 CallCallback( SALEVENT_RESIZE, NULL ); 1294 1295 /* 1296 * sometimes a message box/dialogue is brought up when a frame is not mapped 1297 * the corresponding TRANSIENT_FOR hint is then set to the root window 1298 * so that the dialogue shows in all cases. Correct it here if the 1299 * frame is shown afterwards. 1300 */ 1301 if( ! IsChildWindow() 1302 && ! IsOverrideRedirect() 1303 && ! IsFloatGrabWindow() 1304 ) 1305 { 1306 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); 1307 it != maChildren.end(); ++it ) 1308 { 1309 if( (*it)->mbTransientForRoot ) 1310 GetDisplay()->getWMAdaptor()->changeReferenceFrame( *it, this ); 1311 } 1312 } 1313 /* 1314 * leave SHOWSTATE_UNKNOWN as this indicates first mapping 1315 * and is only reset int HandleSizeEvent 1316 */ 1317 if( nShowState_ != SHOWSTATE_UNKNOWN ) 1318 nShowState_ = SHOWSTATE_NORMAL; 1319 1320 /* 1321 * #98107# plugged windows don't necessarily get the 1322 * focus on show because the parent may already be mapped 1323 * and have the focus. So try to set the focus 1324 * to the child on Show(sal_True) 1325 */ 1326 if( (nStyle_ & SAL_FRAME_STYLE_PLUG) && ! m_bXEmbed ) 1327 XSetInputFocus( GetXDisplay(), 1328 GetWindow(), 1329 RevertToParent, 1330 CurrentTime ); 1331 1332 if( mpParent ) 1333 { 1334 // push this frame so it will be in front of its siblings 1335 // only necessary for insane transient behaviour of Dtwm/olwm 1336 mpParent->maChildren.remove( this ); 1337 mpParent->maChildren.push_front(this); 1338 } 1339 } 1340 else 1341 { 1342 if( getInputContext() ) 1343 getInputContext()->Unmap( this ); 1344 1345 if( ! IsChildWindow() ) 1346 { 1347 /* FIXME: Is deleting the property really necessary ? It hurts 1348 * owner drawn windows at least. 1349 */ 1350 if( mpParent && ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) 1351 XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) ); 1352 XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nScreen ); 1353 } 1354 else if( ! m_bXEmbed ) 1355 XUnmapWindow( GetXDisplay(), GetWindow() ); 1356 1357 nShowState_ = SHOWSTATE_HIDDEN; 1358 if( IsFloatGrabWindow() && nVisibleFloats ) 1359 { 1360 nVisibleFloats--; 1361 if( nVisibleFloats == 0 && ! GetDisplay()->GetCaptureFrame() ) 1362 XUngrabPointer( GetXDisplay(), 1363 CurrentTime ); 1364 } 1365 // flush here; there may be a very seldom race between 1366 // the display connection used for clipboard and our connection 1367 Flush(); 1368 } 1369 } 1370 1371 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1372 void X11SalFrame::ToTop( sal_uInt16 nFlags ) 1373 { 1374 if( ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN ) 1375 && ! ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) 1376 && nShowState_ != SHOWSTATE_HIDDEN 1377 && nShowState_ != SHOWSTATE_UNKNOWN 1378 ) 1379 { 1380 GetDisplay()->getWMAdaptor()->frameIsMapping( this ); 1381 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() ) 1382 XMapWindow( GetXDisplay(), GetShellWindow() ); 1383 XMapWindow( GetXDisplay(), GetWindow() ); 1384 } 1385 1386 XLIB_Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow(); 1387 if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) ) 1388 { 1389 XRaiseWindow( GetXDisplay(), aToTopWindow ); 1390 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() ) 1391 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); 1392 it != maChildren.end(); ++it ) 1393 (*it)->ToTop( nFlags & ~SAL_FRAME_TOTOP_GRABFOCUS ); 1394 } 1395 1396 if( ( ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) || ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY ) ) 1397 && bMapped_ ) 1398 { 1399 if( m_bXEmbed ) 1400 askForXEmbedFocus( 0 ); 1401 else 1402 XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent, CurrentTime ); 1403 } 1404 } 1405 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1406 void X11SalFrame::GetWorkArea( Rectangle& rWorkArea ) 1407 { 1408 rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 ); 1409 } 1410 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1411 void X11SalFrame::GetClientSize( long &rWidth, long &rHeight ) 1412 { 1413 if( ! bViewable_ ) 1414 { 1415 rWidth = rHeight = 0; 1416 return; 1417 } 1418 1419 rWidth = maGeometry.nWidth; 1420 rHeight = maGeometry.nHeight; 1421 1422 if( !rWidth || !rHeight ) 1423 { 1424 XWindowAttributes aAttrib; 1425 1426 XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib ); 1427 1428 maGeometry.nWidth = rWidth = aAttrib.width; 1429 maGeometry.nHeight = rHeight = aAttrib.height; 1430 } 1431 } 1432 1433 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1434 1435 void X11SalFrame::SetWindowGravity (int nGravity) const 1436 { 1437 if( ! IsChildWindow() ) 1438 { 1439 XSizeHints* pHint = XAllocSizeHints(); 1440 long nFlag; 1441 1442 XGetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint, &nFlag); 1443 pHint->flags |= PWinGravity; 1444 pHint->win_gravity = nGravity; 1445 1446 XSetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint); 1447 XSync (GetXDisplay(), False); 1448 1449 XFree (pHint); 1450 } 1451 } 1452 1453 void X11SalFrame::Center( ) 1454 { 1455 int nX, nY, nScreenWidth, nScreenHeight; 1456 int nRealScreenWidth, nRealScreenHeight; 1457 int nScreenX = 0, nScreenY = 0; 1458 1459 const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize; 1460 nScreenWidth = aScreenSize.Width(); 1461 nScreenHeight = aScreenSize.Height(); 1462 nRealScreenWidth = nScreenWidth; 1463 nRealScreenHeight = nScreenHeight; 1464 1465 if( GetDisplay()->IsXinerama() ) 1466 { 1467 // get xinerama screen we are on 1468 // if there is a parent, use its center for screen determination 1469 // else use the pointer 1470 XLIB_Window aRoot, aChild; 1471 int root_x, root_y, x, y; 1472 unsigned int mask; 1473 if( mpParent ) 1474 { 1475 root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2; 1476 root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2; 1477 } 1478 else 1479 XQueryPointer( GetXDisplay(), 1480 GetShellWindow(), 1481 &aRoot, &aChild, 1482 &root_x, &root_y, 1483 &x, &y, 1484 &mask ); 1485 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens(); 1486 for( unsigned int i = 0; i < rScreens.size(); i++ ) 1487 if( rScreens[i].IsInside( Point( root_x, root_y ) ) ) 1488 { 1489 nScreenX = rScreens[i].Left(); 1490 nScreenY = rScreens[i].Top(); 1491 nRealScreenWidth = rScreens[i].GetWidth(); 1492 nRealScreenHeight = rScreens[i].GetHeight(); 1493 break; 1494 } 1495 } 1496 1497 if( mpParent ) 1498 { 1499 X11SalFrame* pFrame = mpParent; 1500 while( pFrame->mpParent ) 1501 pFrame = pFrame->mpParent; 1502 if( pFrame->maGeometry.nWidth < 1 || pFrame->maGeometry.nHeight < 1 ) 1503 { 1504 Rectangle aRect; 1505 pFrame->GetPosSize( aRect ); 1506 pFrame->maGeometry.nX = aRect.Left(); 1507 pFrame->maGeometry.nY = aRect.Top(); 1508 pFrame->maGeometry.nWidth = aRect.GetWidth(); 1509 pFrame->maGeometry.nHeight = aRect.GetHeight(); 1510 } 1511 1512 if( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) 1513 { 1514 XLIB_Window aRoot; 1515 unsigned int bw, depth; 1516 XGetGeometry( GetXDisplay(), 1517 pFrame->GetShellWindow(), 1518 &aRoot, 1519 &nScreenX, &nScreenY, 1520 (unsigned int*)&nScreenWidth, 1521 (unsigned int*)&nScreenHeight, 1522 &bw, &depth ); 1523 } 1524 else 1525 { 1526 nScreenX = pFrame->maGeometry.nX; 1527 nScreenY = pFrame->maGeometry.nY; 1528 nScreenWidth = pFrame->maGeometry.nWidth; 1529 nScreenHeight = pFrame->maGeometry.nHeight; 1530 } 1531 } 1532 1533 if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL ) 1534 { 1535 if( maGeometry.nWidth >= mpParent->maGeometry.nWidth && 1536 maGeometry.nHeight >= mpParent->maGeometry.nHeight ) 1537 { 1538 nX = nScreenX + 40; 1539 nY = nScreenY + 40; 1540 } 1541 else 1542 { 1543 // center the window relative to the top level frame 1544 nX = (nScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX; 1545 nY = (nScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY; 1546 } 1547 } 1548 else 1549 { 1550 // center the window relative to screen 1551 nX = (nRealScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX; 1552 nY = (nRealScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY; 1553 } 1554 nX = nX < 0 ? 0 : nX; 1555 nY = nY < 0 ? 0 : nY; 1556 1557 bDefaultPosition_ = False; 1558 if( mpParent ) 1559 { 1560 nX -= mpParent->maGeometry.nX; 1561 nY -= mpParent->maGeometry.nY; 1562 } 1563 1564 Point aPoint(nX, nY); 1565 SetPosSize( Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) ); 1566 } 1567 1568 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1569 void X11SalFrame::updateScreenNumber() 1570 { 1571 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) 1572 { 1573 Point aPoint( maGeometry.nX, maGeometry.nY ); 1574 const std::vector<Rectangle>& rScreenRects( GetDisplay()->GetXineramaScreens() ); 1575 size_t nScreens = rScreenRects.size(); 1576 for( size_t i = 0; i < nScreens; i++ ) 1577 { 1578 if( rScreenRects[i].IsInside( aPoint ) ) 1579 { 1580 maGeometry.nScreenNumber = static_cast<unsigned int>(i); 1581 break; 1582 } 1583 } 1584 } 1585 else 1586 maGeometry.nScreenNumber = static_cast<unsigned int>(m_nScreen); 1587 } 1588 1589 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1590 void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 1591 { 1592 if( nStyle_ & SAL_FRAME_STYLE_PLUG ) 1593 return; 1594 1595 // relative positioning in X11SalFrame::SetPosSize 1596 Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) ); 1597 aPosSize.Justify(); 1598 1599 if( ! ( nFlags & SAL_FRAME_POSSIZE_X ) ) 1600 { 1601 nX = aPosSize.Left(); 1602 if( mpParent ) 1603 nX -= mpParent->maGeometry.nX; 1604 } 1605 if( ! ( nFlags & SAL_FRAME_POSSIZE_Y ) ) 1606 { 1607 nY = aPosSize.Top(); 1608 if( mpParent ) 1609 nY -= mpParent->maGeometry.nY; 1610 } 1611 if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH ) ) 1612 nWidth = aPosSize.GetWidth(); 1613 if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT ) ) 1614 nHeight = aPosSize.GetHeight(); 1615 1616 aPosSize = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); 1617 1618 if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) ) ) 1619 { 1620 if( bDefaultPosition_ ) 1621 { 1622 maGeometry.nWidth = aPosSize.GetWidth(); 1623 maGeometry.nHeight = aPosSize.GetHeight(); 1624 Center(); 1625 } 1626 else 1627 SetSize( Size( nWidth, nHeight ) ); 1628 } 1629 else 1630 SetPosSize( aPosSize ); 1631 1632 bDefaultPosition_ = False; 1633 } 1634 1635 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1636 void X11SalFrame::SetAlwaysOnTop( sal_Bool bOnTop ) 1637 { 1638 if( ! IsOverrideRedirect() ) 1639 { 1640 bAlwaysOnTop_ = bOnTop; 1641 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop ); 1642 } 1643 } 1644 1645 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1646 1647 #define _FRAMESTATE_MASK_GEOMETRY \ 1648 (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y | \ 1649 SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT) 1650 #define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \ 1651 (SAL_FRAMESTATE_MASK_MAXIMIZED_X | SAL_FRAMESTATE_MASK_MAXIMIZED_Y | \ 1652 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT) 1653 1654 void X11SalFrame::SetWindowState( const SalFrameState *pState ) 1655 { 1656 if (pState == NULL) 1657 return; 1658 1659 // Request for position or size change 1660 if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) 1661 { 1662 Rectangle aPosSize; 1663 bool bDoAdjust = false; 1664 1665 /* #i44325# 1666 * if maximized, set restore size and guess maximized size from last time 1667 * in state change below maximize window 1668 */ 1669 if( ! IsChildWindow() && 1670 (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) && 1671 (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) && 1672 (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) == _FRAMESTATE_MASK_GEOMETRY && 1673 (pState->mnMask & _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY 1674 ) 1675 { 1676 XSizeHints* pHints = XAllocSizeHints(); 1677 long nSupplied = 0; 1678 XGetWMNormalHints( GetXDisplay(), 1679 GetShellWindow(), 1680 pHints, 1681 &nSupplied ); 1682 pHints->flags |= PPosition | PWinGravity; 1683 pHints->x = pState->mnX; 1684 pHints->y = pState->mnY; 1685 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity(); 1686 XSetWMNormalHints( GetXDisplay(), 1687 GetShellWindow(), 1688 pHints ); 1689 XFree( pHints ); 1690 1691 XMoveResizeWindow( GetXDisplay(), GetShellWindow(), 1692 pState->mnX, pState->mnY, 1693 pState->mnWidth, pState->mnHeight ); 1694 // guess maximized geometry from last time 1695 maGeometry.nX = pState->mnMaximizedX; 1696 maGeometry.nY = pState->mnMaximizedY; 1697 maGeometry.nWidth = pState->mnMaximizedWidth; 1698 maGeometry.nHeight = pState->mnMaximizedHeight; 1699 updateScreenNumber(); 1700 } 1701 else 1702 { 1703 // initialize with current geometry 1704 if ((pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) != _FRAMESTATE_MASK_GEOMETRY) 1705 GetPosSize (aPosSize); 1706 1707 // change requested properties 1708 if (pState->mnMask & SAL_FRAMESTATE_MASK_X) 1709 { 1710 aPosSize.setX (pState->mnX); 1711 } 1712 if (pState->mnMask & SAL_FRAMESTATE_MASK_Y) 1713 { 1714 aPosSize.setY (pState->mnY); 1715 } 1716 if (pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH) 1717 { 1718 long nWidth = pState->mnWidth > 0 ? pState->mnWidth - 1 : 0; 1719 aPosSize.setWidth (nWidth); 1720 bDoAdjust = true; 1721 } 1722 if (pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT) 1723 { 1724 int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0; 1725 aPosSize.setHeight (nHeight); 1726 bDoAdjust = true; 1727 } 1728 1729 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize; 1730 const WMAdaptor *pWM = GetDisplay()->getWMAdaptor(); 1731 1732 if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width() 1733 && aPosSize.GetHeight() <= aScreenSize.Height() ) 1734 { 1735 SalFrameGeometry aGeom = maGeometry; 1736 1737 if( ! (nStyle_ & ( SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_PLUG ) ) && 1738 mpParent && 1739 aGeom.nLeftDecoration == 0 && 1740 aGeom.nTopDecoration == 0 ) 1741 { 1742 aGeom = mpParent->maGeometry; 1743 if( aGeom.nLeftDecoration == 0 && 1744 aGeom.nTopDecoration == 0 ) 1745 { 1746 aGeom.nLeftDecoration = 5; 1747 aGeom.nTopDecoration = 20; 1748 aGeom.nRightDecoration = 5; 1749 aGeom.nBottomDecoration = 5; 1750 } 1751 } 1752 1753 // adjust position so that frame fits onto screen 1754 if( aPosSize.Right()+(long)aGeom.nRightDecoration > aScreenSize.Width()-1 ) 1755 aPosSize.Move( (long)aScreenSize.Width() - (long)aPosSize.Right() - (long)aGeom.nRightDecoration, 0 ); 1756 if( aPosSize.Bottom()+(long)aGeom.nBottomDecoration > aScreenSize.Height()-1 ) 1757 aPosSize.Move( 0, (long)aScreenSize.Height() - (long)aPosSize.Bottom() - (long)aGeom.nBottomDecoration ); 1758 if( aPosSize.Left() < (long)aGeom.nLeftDecoration ) 1759 aPosSize.Move( (long)aGeom.nLeftDecoration - (long)aPosSize.Left(), 0 ); 1760 if( aPosSize.Top() < (long)aGeom.nTopDecoration ) 1761 aPosSize.Move( 0, (long)aGeom.nTopDecoration - (long)aPosSize.Top() ); 1762 } 1763 1764 // resize with new args 1765 if (pWM->supportsICCCMPos()) 1766 { 1767 if( mpParent ) 1768 aPosSize.Move( -mpParent->maGeometry.nX, 1769 -mpParent->maGeometry.nY ); 1770 SetPosSize( aPosSize ); 1771 bDefaultPosition_ = False; 1772 } 1773 else 1774 SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); 1775 } 1776 } 1777 1778 // request for status change 1779 if (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) 1780 { 1781 if (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) 1782 { 1783 nShowState_ = SHOWSTATE_NORMAL; 1784 if( ! (pState->mnState & (SAL_FRAMESTATE_MAXIMIZED_HORZ|SAL_FRAMESTATE_MAXIMIZED_VERT) ) ) 1785 Maximize(); 1786 else 1787 { 1788 bool bHorz = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_HORZ) ? true : false; 1789 bool bVert = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_VERT) ? true : false; 1790 GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert ); 1791 } 1792 maRestorePosSize.Left() = pState->mnX; 1793 maRestorePosSize.Top() = pState->mnY; 1794 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnWidth; 1795 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnHeight; 1796 } 1797 else if( mbMaximizedHorz || mbMaximizedVert ) 1798 GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false ); 1799 1800 if (pState->mnState & SAL_FRAMESTATE_MINIMIZED) 1801 { 1802 if (nShowState_ == SHOWSTATE_UNKNOWN) 1803 nShowState_ = SHOWSTATE_NORMAL; 1804 Minimize(); 1805 } 1806 if (pState->mnState & SAL_FRAMESTATE_NORMAL) 1807 { 1808 if (nShowState_ != SHOWSTATE_NORMAL) 1809 Restore(); 1810 } 1811 if (pState->mnState & SAL_FRAMESTATE_ROLLUP) 1812 GetDisplay()->getWMAdaptor()->shade( this, true ); 1813 } 1814 } 1815 1816 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1817 sal_Bool X11SalFrame::GetWindowState( SalFrameState* pState ) 1818 { 1819 if( SHOWSTATE_MINIMIZED == nShowState_ ) 1820 pState->mnState = SAL_FRAMESTATE_MINIMIZED; 1821 else 1822 pState->mnState = SAL_FRAMESTATE_NORMAL; 1823 1824 Rectangle aPosSize; 1825 if( maRestorePosSize.IsEmpty() ) 1826 GetPosSize( aPosSize ); 1827 else 1828 aPosSize = maRestorePosSize; 1829 1830 if( mbMaximizedHorz ) 1831 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_HORZ; 1832 if( mbMaximizedVert ) 1833 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_VERT; 1834 if( mbShaded ) 1835 pState->mnState |= SAL_FRAMESTATE_ROLLUP; 1836 1837 pState->mnX = aPosSize.Left(); 1838 pState->mnY = aPosSize.Top(); 1839 pState->mnWidth = aPosSize.GetWidth(); 1840 pState->mnHeight = aPosSize.GetHeight(); 1841 1842 pState->mnMask = _FRAMESTATE_MASK_GEOMETRY | SAL_FRAMESTATE_MASK_STATE; 1843 1844 1845 if (! maRestorePosSize.IsEmpty() ) 1846 { 1847 GetPosSize( aPosSize ); 1848 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED; 1849 pState->mnMaximizedX = aPosSize.Left(); 1850 pState->mnMaximizedY = aPosSize.Top(); 1851 pState->mnMaximizedWidth = aPosSize.GetWidth(); 1852 pState->mnMaximizedHeight = aPosSize.GetHeight(); 1853 pState->mnMask |= _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY; 1854 } 1855 1856 return sal_True; 1857 } 1858 1859 // ---------------------------------------------------------------------------- 1860 // get a screenshot of the current frame including window manager decoration 1861 SalBitmap* X11SalFrame::SnapShot() 1862 { 1863 Display* pDisplay = GetXDisplay(); 1864 1865 // make sure the frame has been reparented and all paint timer have been 1866 // expired 1867 do 1868 { 1869 XSync(pDisplay, False); 1870 Application::Reschedule (); 1871 } 1872 while (XPending(pDisplay)); 1873 TimeValue aVal; 1874 aVal.Seconds = 0; 1875 aVal.Nanosec = 50000000; 1876 osl_waitThread( &aVal ); 1877 do 1878 { 1879 XSync(pDisplay, False); 1880 Application::Reschedule (); 1881 } 1882 while (XPending(pDisplay)); 1883 1884 // get the most outer window, usually the window manager decoration 1885 Drawable hWindow = None; 1886 if (IsOverrideRedirect()) 1887 hWindow = GetDrawable(); 1888 else 1889 if (hPresentationWindow != None) 1890 hWindow = hPresentationWindow; 1891 else 1892 hWindow = GetStackingWindow(); 1893 1894 // query the contents of the window 1895 if (hWindow != None) 1896 { 1897 X11SalBitmap *pBmp = new X11SalBitmap; 1898 if (pBmp->SnapShot (pDisplay, hWindow)) 1899 return pBmp; 1900 else 1901 delete pBmp; 1902 } 1903 1904 return NULL; 1905 } 1906 1907 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1908 1909 // native menu implementation - currently empty 1910 void X11SalFrame::DrawMenuBar() 1911 { 1912 } 1913 1914 void X11SalFrame::SetMenu( SalMenu* ) 1915 { 1916 } 1917 1918 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1919 void X11SalFrame::GetPosSize( Rectangle &rPosSize ) 1920 { 1921 if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 ) 1922 { 1923 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize; 1924 long w = aScreenSize.Width() - maGeometry.nLeftDecoration - maGeometry.nRightDecoration; 1925 long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration; 1926 1927 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) ); 1928 } 1929 else 1930 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), 1931 Size( maGeometry.nWidth, maGeometry.nHeight ) ); 1932 } 1933 1934 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1935 void X11SalFrame::SetSize( const Size &rSize ) 1936 { 1937 if( rSize.Width() > 0 && rSize.Height() > 0 ) 1938 { 1939 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) 1940 && ! IsChildWindow() 1941 && ( nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) 1942 { 1943 XSizeHints* pHints = XAllocSizeHints(); 1944 long nSupplied = 0; 1945 XGetWMNormalHints( GetXDisplay(), 1946 GetShellWindow(), 1947 pHints, 1948 &nSupplied 1949 ); 1950 pHints->min_width = rSize.Width(); 1951 pHints->min_height = rSize.Height(); 1952 pHints->max_width = rSize.Width(); 1953 pHints->max_height = rSize.Height(); 1954 pHints->flags |= PMinSize | PMaxSize; 1955 XSetWMNormalHints( GetXDisplay(), 1956 GetShellWindow(), 1957 pHints ); 1958 XFree( pHints ); 1959 } 1960 XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() ); 1961 if( GetWindow() != GetShellWindow() ) 1962 { 1963 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) ) 1964 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() ); 1965 else 1966 XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() ); 1967 } 1968 1969 maGeometry.nWidth = rSize.Width(); 1970 maGeometry.nHeight = rSize.Height(); 1971 1972 // allow the external status window to reposition 1973 if (mbInputFocus && mpInputContext != NULL) 1974 mpInputContext->SetICFocus ( this ); 1975 } 1976 } 1977 1978 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1979 1980 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1981 1982 void X11SalFrame::SetPosSize( const Rectangle &rPosSize ) 1983 { 1984 XWindowChanges values; 1985 values.x = rPosSize.Left(); 1986 values.y = rPosSize.Top(); 1987 values.width = rPosSize.GetWidth(); 1988 values.height = rPosSize.GetHeight(); 1989 1990 if( !values.width || !values.height ) 1991 return; 1992 1993 if( mpParent && ! IsSysChildWindow() ) 1994 { 1995 // --- RTL --- (mirror window pos) 1996 if( Application::GetSettings().GetLayoutRTL() ) 1997 values.x = mpParent->maGeometry.nWidth-values.width-1-values.x; 1998 1999 XLIB_Window aChild; 2000 // coordinates are relative to parent, so translate to root coordinates 2001 XTranslateCoordinates( GetDisplay()->GetDisplay(), 2002 mpParent->GetWindow(), 2003 GetDisplay()->GetRootWindow( m_nScreen ), 2004 values.x, values.y, 2005 &values.x, &values.y, 2006 & aChild ); 2007 } 2008 2009 bool bMoved = false; 2010 bool bSized = false; 2011 if( values.x != maGeometry.nX || values.y != maGeometry.nY ) 2012 bMoved = true; 2013 if( values.width != (int)maGeometry.nWidth || values.height != (int)maGeometry.nHeight ) 2014 bSized = true; 2015 2016 if( ! ( nStyle_ & ( SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_FLOAT ) ) 2017 && !(pDisplay_->GetProperties() & PROPERTY_SUPPORT_WM_ClientPos) ) 2018 { 2019 values.x -= maGeometry.nLeftDecoration; 2020 values.y -= maGeometry.nTopDecoration; 2021 } 2022 2023 // do net set WMNormalHints for .. 2024 if( 2025 // child windows 2026 ! IsChildWindow() 2027 // popups (menu, help window, etc.) 2028 && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT 2029 // shown, sizeable windows 2030 && ( nShowState_ == SHOWSTATE_UNKNOWN || 2031 nShowState_ == SHOWSTATE_HIDDEN || 2032 ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) 2033 ) 2034 ) 2035 { 2036 XSizeHints* pHints = XAllocSizeHints(); 2037 long nSupplied = 0; 2038 XGetWMNormalHints( GetXDisplay(), 2039 GetShellWindow(), 2040 pHints, 2041 &nSupplied 2042 ); 2043 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) ) 2044 { 2045 pHints->min_width = rPosSize.GetWidth(); 2046 pHints->min_height = rPosSize.GetHeight(); 2047 pHints->max_width = rPosSize.GetWidth(); 2048 pHints->max_height = rPosSize.GetHeight(); 2049 pHints->flags |= PMinSize | PMaxSize; 2050 } 2051 if( nShowState_ == SHOWSTATE_UNKNOWN || nShowState_ == SHOWSTATE_HIDDEN ) 2052 { 2053 pHints->flags |= PPosition | PWinGravity; 2054 pHints->x = values.x; 2055 pHints->y = values.y; 2056 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity(); 2057 } 2058 if( mbFullScreen ) 2059 { 2060 pHints->max_width = 10000; 2061 pHints->max_height = 10000; 2062 pHints->flags |= PMaxSize; 2063 } 2064 XSetWMNormalHints( GetXDisplay(), 2065 GetShellWindow(), 2066 pHints ); 2067 XFree( pHints ); 2068 } 2069 2070 XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height ); 2071 if( GetShellWindow() != GetWindow() ) 2072 { 2073 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) ) 2074 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height ); 2075 else 2076 XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height ); 2077 } 2078 2079 maGeometry.nX = values.x; 2080 maGeometry.nY = values.y; 2081 maGeometry.nWidth = values.width; 2082 maGeometry.nHeight = values.height; 2083 if( IsSysChildWindow() && mpParent ) 2084 { 2085 // translate back to root coordinates 2086 maGeometry.nX += mpParent->maGeometry.nX; 2087 maGeometry.nY += mpParent->maGeometry.nY; 2088 } 2089 2090 updateScreenNumber(); 2091 if( bSized && ! bMoved ) 2092 CallCallback( SALEVENT_RESIZE, NULL ); 2093 else if( bMoved && ! bSized ) 2094 CallCallback( SALEVENT_MOVE, NULL ); 2095 else 2096 CallCallback( SALEVENT_MOVERESIZE, NULL ); 2097 2098 // allow the external status window to reposition 2099 if (mbInputFocus && mpInputContext != NULL) 2100 mpInputContext->SetICFocus ( this ); 2101 } 2102 2103 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2104 void X11SalFrame::Minimize() 2105 { 2106 if( IsSysChildWindow() ) 2107 return; 2108 2109 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ ) 2110 { 2111 stderr0( "X11SalFrame::Minimize on withdrawn window\n" ); 2112 return; 2113 } 2114 2115 if( XIconifyWindow( GetXDisplay(), 2116 GetShellWindow(), 2117 pDisplay_->GetDefaultScreenNumber() ) ) 2118 nShowState_ = SHOWSTATE_MINIMIZED; 2119 } 2120 2121 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2122 void X11SalFrame::Maximize() 2123 { 2124 if( IsSysChildWindow() ) 2125 return; 2126 2127 if( SHOWSTATE_MINIMIZED == nShowState_ ) 2128 { 2129 GetDisplay()->getWMAdaptor()->frameIsMapping( this ); 2130 XMapWindow( GetXDisplay(), GetShellWindow() ); 2131 nShowState_ = SHOWSTATE_NORMAL; 2132 } 2133 2134 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true ); 2135 } 2136 2137 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2138 void X11SalFrame::Restore() 2139 { 2140 if( IsSysChildWindow() ) 2141 return; 2142 2143 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ ) 2144 { 2145 stderr0( "X11SalFrame::Restore on withdrawn window\n" ); 2146 return; 2147 } 2148 2149 if( SHOWSTATE_MINIMIZED == nShowState_ ) 2150 { 2151 GetDisplay()->getWMAdaptor()->frameIsMapping( this ); 2152 XMapWindow( GetXDisplay(), GetShellWindow() ); 2153 nShowState_ = SHOWSTATE_NORMAL; 2154 } 2155 2156 pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false ); 2157 } 2158 2159 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2160 2161 void X11SalFrame::SetScreenNumber( unsigned int nNewScreen ) 2162 { 2163 if( nNewScreen == maGeometry.nScreenNumber ) 2164 return; 2165 2166 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) 2167 { 2168 if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() ) 2169 return; 2170 2171 Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nScreenNumber] ); 2172 Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] ); 2173 bool bVisible = bMapped_; 2174 if( bVisible ) 2175 Show( sal_False ); 2176 maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left()); 2177 maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top()); 2178 createNewWindow( None, m_nScreen ); 2179 if( bVisible ) 2180 Show( sal_True ); 2181 maGeometry.nScreenNumber = nNewScreen; 2182 } 2183 else if( sal_Int32(nNewScreen) < GetDisplay()->GetScreenCount() ) 2184 { 2185 bool bVisible = bMapped_; 2186 if( bVisible ) 2187 Show( sal_False ); 2188 createNewWindow( None, nNewScreen ); 2189 if( bVisible ) 2190 Show( sal_True ); 2191 maGeometry.nScreenNumber = nNewScreen; 2192 } 2193 } 2194 2195 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2196 2197 void X11SalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nScreen ) 2198 { 2199 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) 2200 { 2201 if( mbFullScreen == (bool)bFullScreen ) 2202 return; 2203 if( bFullScreen ) 2204 { 2205 maRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), 2206 Size( maGeometry.nWidth, maGeometry.nHeight ) ); 2207 Rectangle aRect; 2208 if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) ) 2209 aRect = Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nScreen ) ); 2210 else 2211 aRect = GetDisplay()->GetXineramaScreens()[nScreen]; 2212 nStyle_ |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN; 2213 bool bVisible = bMapped_; 2214 if( bVisible ) 2215 Show( sal_False ); 2216 maGeometry.nX = aRect.Left(); 2217 maGeometry.nY = aRect.Top(); 2218 maGeometry.nWidth = aRect.GetWidth(); 2219 maGeometry.nHeight = aRect.GetHeight(); 2220 mbMaximizedHorz = mbMaximizedVert = false; 2221 mbFullScreen = true; 2222 createNewWindow( None, m_nScreen ); 2223 if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) 2224 GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true ); 2225 else 2226 { 2227 GetDisplay()->getWMAdaptor()->setFullScreenMonitors( GetShellWindow(), nScreen ); 2228 GetDisplay()->getWMAdaptor()->showFullScreen( this, true ); 2229 } 2230 if( bVisible ) 2231 Show(sal_True); 2232 2233 } 2234 else 2235 { 2236 mbFullScreen = false; 2237 nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN; 2238 bool bVisible = bMapped_; 2239 Rectangle aRect = maRestorePosSize; 2240 maRestorePosSize = Rectangle(); 2241 if( bVisible ) 2242 Show( sal_False ); 2243 createNewWindow( None, m_nScreen ); 2244 if( !aRect.IsEmpty() ) 2245 SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 2246 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | 2247 SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); 2248 if( bVisible ) 2249 Show( sal_True ); 2250 } 2251 } 2252 else 2253 { 2254 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) 2255 nScreen = m_nScreen; 2256 if( nScreen != m_nScreen ) 2257 { 2258 bool bVisible = bMapped_; 2259 if( mbFullScreen ) 2260 pDisplay_->getWMAdaptor()->showFullScreen( this, false ); 2261 if( bVisible ) 2262 Show( sal_False ); 2263 createNewWindow( None, nScreen ); 2264 if( mbFullScreen ) 2265 pDisplay_->getWMAdaptor()->showFullScreen( this, true ); 2266 if( bVisible ) 2267 Show( sal_True ); 2268 } 2269 if( mbFullScreen == (bool)bFullScreen ) 2270 return; 2271 2272 pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen ); 2273 if( IsOverrideRedirect() 2274 && WMSupportsFWS( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ) ) ) 2275 { 2276 AddFwsProtocols( GetXDisplay(), GetShellWindow() ); 2277 RegisterFwsWindow( GetXDisplay(), GetShellWindow() ); 2278 } 2279 } 2280 } 2281 2282 /* --------------------------------------------------------------------- 2283 the xautolock pseudo screen saver needs special treatment since it 2284 doesn't cooperate with XxxxScreenSaver settings 2285 ------------------------------------------------------------------- */ 2286 2287 static Bool 2288 IsRunningXAutoLock( Display *p_display, XLIB_Window a_window ) 2289 { 2290 const char *p_atomname = "XAUTOLOCK_SEMAPHORE_PID"; 2291 Atom a_pidatom; 2292 2293 // xautolock interns this atom 2294 a_pidatom = XInternAtom( p_display, p_atomname, True ); 2295 if ( a_pidatom == None ) 2296 return False; 2297 2298 Atom a_type; 2299 int n_format; 2300 unsigned long n_items; 2301 unsigned long n_bytes_after; 2302 pid_t *p_pid; 2303 pid_t n_pid; 2304 // get pid of running xautolock 2305 XGetWindowProperty (p_display, a_window, a_pidatom, 0L, 2L, False, 2306 AnyPropertyType, &a_type, &n_format, &n_items, &n_bytes_after, 2307 (unsigned char**) &p_pid ); 2308 n_pid = *p_pid; 2309 XFree( p_pid ); 2310 2311 if ( a_type == XA_INTEGER ) 2312 { 2313 // check if xautolock pid points to a running process 2314 if ( kill(n_pid, 0) == -1 ) 2315 return False; 2316 else 2317 return True; 2318 } 2319 2320 return False; 2321 } 2322 2323 /* definitions from xautolock.c (pl15) */ 2324 #define XAUTOLOCK_DISABLE 1 2325 #define XAUTOLOCK_ENABLE 2 2326 2327 static Bool 2328 MessageToXAutoLock( Display *p_display, int n_message ) 2329 { 2330 const char *p_atomname = "XAUTOLOCK_MESSAGE" ; 2331 Atom a_messageatom; 2332 XLIB_Window a_rootwindow; 2333 2334 a_rootwindow = RootWindowOfScreen( ScreenOfDisplay(p_display, 0) ); 2335 if ( ! IsRunningXAutoLock(p_display, a_rootwindow) ) 2336 { 2337 // remove any pending messages 2338 a_messageatom = XInternAtom( p_display, p_atomname, True ); 2339 if ( a_messageatom != None ) 2340 XDeleteProperty( p_display, a_rootwindow, a_messageatom ); 2341 return False; 2342 } 2343 2344 a_messageatom = XInternAtom( p_display, p_atomname, False ); 2345 XChangeProperty (p_display, a_rootwindow, a_messageatom, XA_INTEGER, 2346 8, PropModeReplace, (unsigned char*)&n_message, sizeof(n_message) ); 2347 2348 return True; 2349 } 2350 2351 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2352 void X11SalFrame::StartPresentation( sal_Bool bStart ) 2353 { 2354 I18NStatus::get().show( !bStart, I18NStatus::presentation ); 2355 if ( bStart ) 2356 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_DISABLE ); 2357 else 2358 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_ENABLE ); 2359 2360 if( ! bStart && hPresentationWindow != None ) 2361 doReparentPresentationDialogues( GetDisplay() ); 2362 hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None; 2363 2364 2365 // needs static here to save DPMS settings 2366 int dummy; 2367 static bool DPMSExtensionAvailable = 2368 #ifndef SOLARIS 2369 (DPMSQueryExtension(GetXDisplay(), &dummy, &dummy) != 0); 2370 static sal_Bool DPMSEnabled = false; 2371 #else 2372 false; 2373 bool DPMSEnabled = false; 2374 (void)dummy; 2375 #define CARD16 unsigned short 2376 #endif 2377 static CARD16 dpms_standby_timeout=0; 2378 static CARD16 dpms_suspend_timeout=0; 2379 static CARD16 dpms_off_timeout=0; 2380 2381 2382 if( bStart || nScreenSaversTimeout_ || DPMSEnabled) 2383 { 2384 if( hPresentationWindow ) 2385 { 2386 /* #i10559# workaround for WindowMaker: try to restore 2387 * current focus after presentation window is gone 2388 */ 2389 int revert_to = 0; 2390 XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to ); 2391 } 2392 int timeout, interval, prefer_blanking, allow_exposures; 2393 XGetScreenSaver( GetXDisplay(), 2394 &timeout, 2395 &interval, 2396 &prefer_blanking, 2397 &allow_exposures ); 2398 2399 2400 // get the DPMS state right before the start 2401 if (DPMSExtensionAvailable) 2402 { 2403 #ifndef SOLARIS 2404 CARD16 state; // card16 is defined in Xdm.h 2405 DPMSInfo( GetXDisplay(), 2406 &state, 2407 &DPMSEnabled); 2408 #endif 2409 } 2410 if( bStart ) // start show 2411 { 2412 if ( timeout ) 2413 { 2414 nScreenSaversTimeout_ = timeout; 2415 XResetScreenSaver( GetXDisplay() ); 2416 XSetScreenSaver( GetXDisplay(), 2417 0, 2418 interval, 2419 prefer_blanking, 2420 allow_exposures ); 2421 } 2422 #ifndef SOLARIS 2423 if( DPMSEnabled ) 2424 { 2425 if ( DPMSExtensionAvailable ) 2426 { 2427 DPMSGetTimeouts( GetXDisplay(), 2428 &dpms_standby_timeout, 2429 &dpms_suspend_timeout, 2430 &dpms_off_timeout); 2431 DPMSSetTimeouts(GetXDisplay(), 0,0,0); 2432 } 2433 } 2434 #endif 2435 } 2436 else // if( !bStart ) // end of show 2437 { 2438 if( nScreenSaversTimeout_ ) 2439 { 2440 XSetScreenSaver( GetXDisplay(), 2441 nScreenSaversTimeout_, 2442 interval, 2443 prefer_blanking, 2444 allow_exposures ); 2445 nScreenSaversTimeout_ = 0; 2446 } 2447 #ifndef SOLARIS 2448 if ( DPMSEnabled ) 2449 { 2450 if ( DPMSExtensionAvailable ) 2451 { 2452 // restore timeouts 2453 DPMSSetTimeouts(GetXDisplay(), dpms_standby_timeout, 2454 dpms_suspend_timeout, dpms_off_timeout); 2455 } 2456 } 2457 #endif 2458 } 2459 } 2460 } 2461 2462 // Pointer 2463 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2464 void X11SalFrame::SetPointer( PointerStyle ePointerStyle ) 2465 { 2466 hCursor_ = pDisplay_->GetPointer( ePointerStyle ); 2467 XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ ); 2468 2469 if( IsCaptured() || nVisibleFloats > 0 ) 2470 XChangeActivePointerGrab( GetXDisplay(), 2471 PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 2472 hCursor_, 2473 CurrentTime ); 2474 } 2475 2476 void X11SalFrame::SetPointerPos(long nX, long nY) 2477 { 2478 /* #87921# when the application tries to center the mouse in the dialog the 2479 * window isn't mapped already. So use coordinates relative to the root window. 2480 */ 2481 unsigned int nWindowLeft = maGeometry.nX + nX; 2482 unsigned int nWindowTop = maGeometry.nY + nY; 2483 2484 XWarpPointer( GetXDisplay(), None, pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ), 2485 0, 0, 0, 0, nWindowLeft, nWindowTop); 2486 } 2487 2488 // delay handling of extended text input 2489 #if !defined(__synchronous_extinput__) 2490 void 2491 X11SalFrame::PostExtTextEvent (sal_uInt16 nExtTextEventType, void *pExtTextEvent) 2492 { 2493 XLIB_Window nFocusWindow = GetWindow(); 2494 Atom nEventAtom = GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::SAL_EXTTEXTEVENT ); 2495 2496 XEvent aEvent; 2497 aEvent.xclient.type = ClientMessage; 2498 aEvent.xclient.serial = 0; 2499 aEvent.xclient.send_event = True; 2500 aEvent.xclient.display = GetXDisplay(); 2501 aEvent.xclient.window = nFocusWindow; 2502 aEvent.xclient.message_type = nEventAtom; 2503 aEvent.xclient.format = 32; 2504 2505 #if SAL_TYPES_SIZEOFLONG > 4 2506 aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent & 0xffffffff); 2507 aEvent.xclient.data.l[1] = (sal_uInt32)((long)pExtTextEvent >> 32); 2508 #else 2509 aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent); 2510 aEvent.xclient.data.l[1] = 0; 2511 #endif 2512 aEvent.xclient.data.l[2] = (sal_uInt32)nExtTextEventType; 2513 aEvent.xclient.data.l[3] = 0; 2514 aEvent.xclient.data.l[4] = 0; 2515 2516 XPutBackEvent( GetXDisplay(), &aEvent ); 2517 } 2518 2519 void 2520 X11SalFrame::HandleExtTextEvent (XClientMessageEvent *pEvent) 2521 { 2522 #if SAL_TYPES_SIZEOFLONG > 4 2523 void* pExtTextEvent = (void*)( (pEvent->data.l[0] & 0xffffffff) 2524 | (pEvent->data.l[1] << 32) ); 2525 #else 2526 void* pExtTextEvent = (void*)(pEvent->data.l[0]); 2527 #endif 2528 sal_uInt16 nExtTextEventType = sal_uInt16(pEvent->data.l[2]); 2529 2530 CallCallback(nExtTextEventType, pExtTextEvent); 2531 2532 switch (nExtTextEventType) 2533 { 2534 case SALEVENT_ENDEXTTEXTINPUT: 2535 break; 2536 2537 case SALEVENT_EXTTEXTINPUT: 2538 break; 2539 2540 default: 2541 2542 fprintf(stderr, "X11SalFrame::HandleExtTextEvent: invalid extended input\n"); 2543 } 2544 } 2545 #endif /* defined(__synchronous_extinput__) */ 2546 2547 // PostEvent 2548 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2549 sal_Bool X11SalFrame::PostEvent( void *pData ) 2550 { 2551 GetDisplay()->SendInternalEvent( this, pData ); 2552 return sal_True; 2553 } 2554 2555 // Title 2556 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2557 void X11SalFrame::SetTitle( const XubString& rTitle ) 2558 { 2559 if( ! ( IsChildWindow() || (nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) ) 2560 { 2561 m_aTitle = rTitle; 2562 GetDisplay()->getWMAdaptor()->setWMName( this, rTitle ); 2563 } 2564 } 2565 2566 // ----------------------------------------------------------------------- 2567 2568 void X11SalFrame::Flush() 2569 { 2570 XFlush( GetDisplay()->GetDisplay() ); 2571 } 2572 2573 // ----------------------------------------------------------------------- 2574 2575 void X11SalFrame::Sync() 2576 { 2577 XSync( GetDisplay()->GetDisplay(), False ); 2578 } 2579 2580 // Keyboard 2581 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2582 2583 // ----------------------------------------------------------------------- 2584 2585 void X11SalFrame::SetInputContext( SalInputContext* pContext ) 2586 { 2587 if (pContext == NULL) 2588 return; 2589 2590 // 1. We should create an input context for this frame 2591 // only when SAL_INPUTCONTEXT_TEXT is set. 2592 2593 if (!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) 2594 { 2595 if( mpInputContext ) 2596 mpInputContext->Unmap( this ); 2597 return; 2598 } 2599 2600 // 2. We should use on-the-spot inputstyle 2601 // only when SAL_INPUTCONTEXT_EXTTEXTINPUT is set. 2602 2603 if (mpInputContext == NULL) 2604 { 2605 I18NStatus& rStatus( I18NStatus::get() ); 2606 rStatus.setParent( this ); 2607 mpInputContext = new SalI18N_InputContext( this ); 2608 if (mpInputContext->UseContext()) 2609 { 2610 mpInputContext->ExtendEventMask( GetShellWindow() ); 2611 if (pContext->mnOptions & SAL_INPUTCONTEXT_CHANGELANGUAGE) 2612 mpInputContext->SetLanguage(pContext->meLanguage); 2613 if (mbInputFocus) 2614 mpInputContext->SetICFocus( this ); 2615 } 2616 } 2617 else 2618 mpInputContext->Map( this ); 2619 return; 2620 } 2621 2622 // ----------------------------------------------------------------------- 2623 2624 void X11SalFrame::EndExtTextInput( sal_uInt16 nFlags ) 2625 { 2626 if (mpInputContext != NULL) 2627 mpInputContext->EndExtTextInput( nFlags ); 2628 } 2629 2630 // ----------------------------------------------------------------------- 2631 2632 XubString X11SalFrame::GetKeyName( sal_uInt16 nKeyCode ) 2633 { 2634 return GetDisplay()->GetKeyName( nKeyCode ); 2635 } 2636 2637 XubString X11SalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode ) 2638 { 2639 return GetKeyName( nKeyCode ); 2640 } 2641 2642 sal_Bool X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) 2643 { 2644 // not supported yet 2645 return sal_False; 2646 } 2647 2648 LanguageType X11SalFrame::GetInputLanguage() 2649 { 2650 // could be improved by checking unicode ranges of the last input 2651 return LANGUAGE_DONTKNOW; 2652 } 2653 2654 // Settings 2655 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2656 2657 inline Color getColorFromLong( long nColor ) 2658 { 2659 return Color( (nColor & 0xff), (nColor & 0xff00)>>8, (nColor & 0xff0000)>>16); 2660 } 2661 2662 void X11SalFrame::UpdateSettings( AllSettings& rSettings ) 2663 { 2664 2665 DtIntegrator* pIntegrator = GetDisplay()->getDtIntegrator(); 2666 #if OSL_DEBUG_LEVEL > 1 2667 fprintf( stderr, "DtIntegrator: %d\n", pIntegrator ? pIntegrator->GetDtType() : -1 ); 2668 #endif 2669 if( pIntegrator ) 2670 pIntegrator->GetSystemLook( rSettings ); 2671 } 2672 2673 void X11SalFrame::CaptureMouse( sal_Bool bCapture ) 2674 { 2675 nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : NULL ); 2676 } 2677 2678 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2679 2680 void X11SalFrame::SetParent( SalFrame* pNewParent ) 2681 { 2682 if( mpParent != pNewParent ) 2683 { 2684 if( mpParent ) 2685 mpParent->maChildren.remove( this ); 2686 2687 mpParent = static_cast<X11SalFrame*>(pNewParent); 2688 mpParent->maChildren.push_back( this ); 2689 if( mpParent->m_nScreen != m_nScreen ) 2690 createNewWindow( None, mpParent->m_nScreen ); 2691 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent ); 2692 } 2693 } 2694 2695 SalFrame* X11SalFrame::GetParent() const 2696 { 2697 return mpParent; 2698 } 2699 2700 void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen ) 2701 { 2702 bool bWasVisible = bMapped_; 2703 if( bWasVisible ) 2704 Show( sal_False ); 2705 2706 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) 2707 nScreen = m_nScreen; 2708 2709 SystemParentData aParentData; 2710 aParentData.aWindow = aNewParent; 2711 aParentData.bXEmbedSupport = (aNewParent != None && m_bXEmbed); // caution: this is guesswork 2712 if( aNewParent == None ) 2713 { 2714 aNewParent = GetDisplay()->GetRootWindow(nScreen); 2715 aParentData.aWindow = None; 2716 m_bXEmbed = false; 2717 } 2718 else 2719 { 2720 // is new parent a root window ? 2721 Display* pDisp = GetDisplay()->GetDisplay(); 2722 int nScreens = GetDisplay()->GetScreenCount(); 2723 for( int i = 0; i < nScreens; i++ ) 2724 { 2725 if( aNewParent == RootWindow( pDisp, i ) ) 2726 { 2727 nScreen = i; 2728 aParentData.aWindow = None; 2729 m_bXEmbed = false; 2730 break; 2731 } 2732 } 2733 } 2734 2735 // first deinit frame 2736 updateGraphics(true); 2737 if( mpInputContext ) 2738 { 2739 mpInputContext->UnsetICFocus( this ); 2740 mpInputContext->Unmap( this ); 2741 } 2742 if( GetWindow() == hPresentationWindow ) 2743 { 2744 hPresentationWindow = None; 2745 doReparentPresentationDialogues( GetDisplay() ); 2746 } 2747 XDestroyWindow( GetXDisplay(), mhWindow ); 2748 mhWindow = None; 2749 2750 passOnSaveYourSelf(); 2751 2752 // now init with new parent again 2753 if ( aParentData.aWindow != None ) 2754 Init( nStyle_ | SAL_FRAME_STYLE_PLUG, nScreen, &aParentData ); 2755 else 2756 Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nScreen, NULL, true ); 2757 2758 // update graphics if necessary 2759 updateGraphics(false); 2760 2761 if( m_aTitle.Len() ) 2762 SetTitle( m_aTitle ); 2763 2764 if( mpParent ) 2765 { 2766 if( mpParent->m_nScreen != m_nScreen ) 2767 SetParent( NULL ); 2768 else 2769 pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent ); 2770 } 2771 2772 if( bWasVisible ) 2773 Show( sal_True ); 2774 2775 std::list< X11SalFrame* > aChildren = maChildren; 2776 for( std::list< X11SalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it ) 2777 (*it)->createNewWindow( None, m_nScreen ); 2778 2779 // FIXME: SalObjects 2780 } 2781 2782 bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent ) 2783 { 2784 if( pNewParent->nSize >= sizeof(SystemParentData) ) 2785 m_bXEmbed = pNewParent->aWindow != None && pNewParent->bXEmbedSupport; 2786 createNewWindow( pNewParent ? pNewParent->aWindow : None ); 2787 2788 return true; 2789 } 2790 2791 // Sound 2792 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2793 void X11SalFrame::Beep( SoundType eSoundType ) // not fully suported 2794 { 2795 switch( eSoundType ) 2796 { 2797 case SOUND_DEFAULT: 2798 case SOUND_ERROR: 2799 GetDisplay()->Beep(); 2800 break; 2801 default: 2802 // Excessive beeping averted 2803 break; 2804 } 2805 } 2806 2807 // Event Handling 2808 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2809 static sal_uInt16 sal_GetCode( int state ) 2810 { 2811 sal_uInt16 nCode = 0; 2812 2813 if( state & Button1Mask ) 2814 nCode |= MOUSE_LEFT; 2815 if( state & Button2Mask ) 2816 nCode |= MOUSE_MIDDLE; 2817 if( state & Button3Mask ) 2818 nCode |= MOUSE_RIGHT; 2819 2820 if( state & ShiftMask ) 2821 nCode |= KEY_SHIFT; 2822 if( state & ControlMask ) 2823 nCode |= KEY_MOD1; 2824 if( state & Mod1Mask ) 2825 nCode |= KEY_MOD2; 2826 2827 // Map Meta/Super modifier to MOD3 on all Unix systems 2828 // except Mac OS X 2829 if( (state & Mod3Mask) ) 2830 nCode |= KEY_MOD3; 2831 2832 return nCode; 2833 } 2834 2835 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2836 2837 SalFrame::SalPointerState X11SalFrame::GetPointerState() 2838 { 2839 SalPointerState aState; 2840 XLIB_Window aRoot, aChild; 2841 int rx, ry, wx, wy; 2842 unsigned int nMask = 0; 2843 XQueryPointer( GetXDisplay(), 2844 GetShellWindow(), 2845 &aRoot, 2846 &aChild, 2847 &rx, &ry, 2848 &wx, &wy, 2849 &nMask 2850 ); 2851 2852 aState.maPos = Point(wx, wy); 2853 aState.mnState = sal_GetCode( nMask ); 2854 return aState; 2855 } 2856 2857 long X11SalFrame::HandleMouseEvent( XEvent *pEvent ) 2858 { 2859 SalMouseEvent aMouseEvt; 2860 sal_uInt16 nEvent = 0; 2861 bool bClosePopups = false; 2862 2863 if( nVisibleFloats && pEvent->type == EnterNotify ) 2864 return 0; 2865 2866 // Solaris X86: clicking the right button on a two-button mouse 2867 // generates a button2 event not a button3 event 2868 if (pDisplay_->GetProperties() & PROPERTY_SUPPORT_3ButtonMouse ) 2869 { 2870 switch (pEvent->type) 2871 { 2872 case EnterNotify: 2873 case LeaveNotify: 2874 if ( pEvent->xcrossing.state & Button2Mask ) 2875 { 2876 pEvent->xcrossing.state &= ~Button2Mask; 2877 pEvent->xcrossing.state |= Button3Mask; 2878 } 2879 break; 2880 2881 case MotionNotify: 2882 if ( pEvent->xmotion.state & Button2Mask ) 2883 { 2884 pEvent->xmotion.state &= ~Button2Mask; 2885 pEvent->xmotion.state |= Button3Mask; 2886 } 2887 break; 2888 2889 default: 2890 if ( Button2 == pEvent->xbutton.button ) 2891 { 2892 pEvent->xbutton.state &= ~Button2Mask; 2893 pEvent->xbutton.state |= Button3Mask; 2894 pEvent->xbutton.button = Button3; 2895 } 2896 break; 2897 } 2898 } 2899 2900 2901 if( LeaveNotify == pEvent->type || EnterNotify == pEvent->type ) 2902 { 2903 /* 2904 * #89075# #89335# 2905 * 2906 * some WMs (and/or) applications have a passive grab on 2907 * mouse buttons (XGrabButton). This leads to enter/leave notifies 2908 * with mouse buttons pressed in the state mask before the actual 2909 * ButtonPress event gets dispatched. But EnterNotify 2910 * is reported in vcl as MouseMove event. Some office code 2911 * decides that a pressed button in a MouseMove belongs to 2912 * a drag operation which leads to doing things differently. 2913 * 2914 * #95901# 2915 * ignore Enter/LeaveNotify resulting from grabs so that 2916 * help windows do not disappear just after appearing 2917 * 2918 * hopefully this workaround will not break anything. 2919 */ 2920 if( pEvent->xcrossing.mode == NotifyGrab || pEvent->xcrossing.mode == NotifyUngrab ) 2921 return 0; 2922 2923 aMouseEvt.mnX = pEvent->xcrossing.x; 2924 aMouseEvt.mnY = pEvent->xcrossing.y; 2925 aMouseEvt.mnTime = pEvent->xcrossing.time; 2926 aMouseEvt.mnCode = sal_GetCode( pEvent->xcrossing.state ); 2927 aMouseEvt.mnButton = 0; 2928 2929 nEvent = LeaveNotify == pEvent->type 2930 ? SALEVENT_MOUSELEAVE 2931 : SALEVENT_MOUSEMOVE; 2932 } 2933 else if( pEvent->type == MotionNotify ) 2934 { 2935 aMouseEvt.mnX = pEvent->xmotion.x; 2936 aMouseEvt.mnY = pEvent->xmotion.y; 2937 aMouseEvt.mnTime = pEvent->xmotion.time; 2938 aMouseEvt.mnCode = sal_GetCode( pEvent->xmotion.state ); 2939 2940 aMouseEvt.mnButton = 0; 2941 2942 nEvent = SALEVENT_MOUSEMOVE; 2943 if( nVisibleFloats > 0 && mpParent ) 2944 { 2945 XLIB_Cursor aCursor = mpParent->GetCursor(); 2946 if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < (int)maGeometry.nWidth && 2947 pEvent->xmotion.y >= 0 && pEvent->xmotion.y < (int)maGeometry.nHeight ) 2948 aCursor = None; 2949 2950 XChangeActivePointerGrab( GetXDisplay(), 2951 PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 2952 aCursor, 2953 CurrentTime ); 2954 } 2955 } 2956 else 2957 { 2958 // let mouse events reach the correct window 2959 if( nVisibleFloats < 1 ) 2960 { 2961 if( ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) 2962 XUngrabPointer( GetXDisplay(), CurrentTime ); 2963 } 2964 else if( pEvent->type == ButtonPress ) 2965 { 2966 // see if the user clicks outside all of the floats 2967 // if yes release the grab 2968 bool bInside = false; 2969 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); 2970 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) 2971 { 2972 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); 2973 if( pFrame->IsFloatGrabWindow() && 2974 pFrame->bMapped_ && 2975 pEvent->xbutton.x_root >= pFrame->maGeometry.nX && 2976 pEvent->xbutton.x_root < pFrame->maGeometry.nX + (int)pFrame->maGeometry.nWidth && 2977 pEvent->xbutton.y_root >= pFrame->maGeometry.nY && 2978 pEvent->xbutton.y_root < pFrame->maGeometry.nY + (int)pFrame->maGeometry.nHeight ) 2979 { 2980 bInside = true; 2981 break; 2982 } 2983 } 2984 if( ! bInside ) 2985 { 2986 // need not take care of the XUngrabPointer in Show( sal_False ) 2987 // because XUngrabPointer does not produce errors if pointer 2988 // is not grabbed 2989 XUngrabPointer( GetXDisplay(), CurrentTime ); 2990 bClosePopups = true; 2991 2992 /* #i15246# only close popups if pointer is outside all our frames 2993 * cannot use our own geometry data here because stacking 2994 * is unknown (the above case implicitly assumes 2995 * that floats are on top which should be true) 2996 */ 2997 XLIB_Window aRoot, aChild; 2998 int root_x, root_y, win_x, win_y; 2999 unsigned int mask_return; 3000 if( XQueryPointer( GetXDisplay(), 3001 GetDisplay()->GetRootWindow( m_nScreen ), 3002 &aRoot, &aChild, 3003 &root_x, &root_y, 3004 &win_x, &win_y, 3005 &mask_return ) 3006 && aChild // pointer may not be in any child 3007 ) 3008 { 3009 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) 3010 { 3011 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); 3012 if( ! pFrame->IsFloatGrabWindow() 3013 && ( pFrame->GetWindow() == aChild || 3014 pFrame->GetShellWindow() == aChild || 3015 pFrame->GetStackingWindow() == aChild ) 3016 ) 3017 { 3018 // #i63638# check that pointer is inside window, not 3019 // only inside stacking window 3020 if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) && 3021 root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) ) 3022 { 3023 bClosePopups = false; 3024 } 3025 break; 3026 } 3027 } 3028 } 3029 } 3030 } 3031 3032 if( m_bXEmbed && pEvent->xbutton.button == Button1 ) 3033 askForXEmbedFocus( pEvent->xbutton.time ); 3034 3035 if( pEvent->xbutton.button == Button1 || 3036 pEvent->xbutton.button == Button2 || 3037 pEvent->xbutton.button == Button3 ) 3038 { 3039 aMouseEvt.mnX = pEvent->xbutton.x; 3040 aMouseEvt.mnY = pEvent->xbutton.y; 3041 aMouseEvt.mnTime = pEvent->xbutton.time; 3042 aMouseEvt.mnCode = sal_GetCode( pEvent->xbutton.state ); 3043 3044 if( Button1 == pEvent->xbutton.button ) 3045 aMouseEvt.mnButton = MOUSE_LEFT; 3046 else if( Button2 == pEvent->xbutton.button ) 3047 aMouseEvt.mnButton = MOUSE_MIDDLE; 3048 else if( Button3 == pEvent->xbutton.button ) 3049 aMouseEvt.mnButton = MOUSE_RIGHT; 3050 3051 nEvent = ButtonPress == pEvent->type 3052 ? SALEVENT_MOUSEBUTTONDOWN 3053 : SALEVENT_MOUSEBUTTONUP; 3054 } 3055 else if( pEvent->xbutton.button == Button4 || 3056 pEvent->xbutton.button == Button5 || 3057 pEvent->xbutton.button == Button6 || 3058 pEvent->xbutton.button == Button7 ) 3059 { 3060 const bool bIncrement( 3061 pEvent->xbutton.button == Button4 || 3062 pEvent->xbutton.button == Button6 ); 3063 const bool bHoriz( 3064 pEvent->xbutton.button == Button6 || 3065 pEvent->xbutton.button == Button7 ); 3066 3067 if( pEvent->type == ButtonRelease ) 3068 return 0; 3069 3070 static sal_uLong nLines = 0; 3071 if( ! nLines ) 3072 { 3073 char* pEnv = getenv( "SAL_WHEELLINES" ); 3074 nLines = pEnv ? atoi( pEnv ) : 3; 3075 if( nLines > 10 ) 3076 nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; 3077 } 3078 3079 SalWheelMouseEvent aWheelEvt; 3080 aWheelEvt.mnTime = pEvent->xbutton.time; 3081 aWheelEvt.mnX = pEvent->xbutton.x; 3082 aWheelEvt.mnY = pEvent->xbutton.y; 3083 aWheelEvt.mnDelta = bIncrement ? 120 : -120; 3084 aWheelEvt.mnNotchDelta = bIncrement ? 1 : -1; 3085 aWheelEvt.mnScrollLines = nLines; 3086 aWheelEvt.mnCode = sal_GetCode( pEvent->xbutton.state ); 3087 aWheelEvt.mbHorz = bHoriz; 3088 3089 nEvent = SALEVENT_WHEELMOUSE; 3090 3091 // --- RTL --- (mirror mouse pos) 3092 if( Application::GetSettings().GetLayoutRTL() ) 3093 aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX; 3094 return CallCallback( nEvent, &aWheelEvt ); 3095 } 3096 } 3097 3098 int nRet = 0; 3099 if( nEvent == SALEVENT_MOUSELEAVE 3100 || ( aMouseEvt.mnX < nWidth_ && aMouseEvt.mnX > -1 && 3101 aMouseEvt.mnY < nHeight_ && aMouseEvt.mnY > -1 ) 3102 || pDisplay_->MouseCaptured( this ) 3103 ) 3104 { 3105 // --- RTL --- (mirror mouse pos) 3106 if( Application::GetSettings().GetLayoutRTL() ) 3107 aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX; 3108 nRet = CallCallback( nEvent, &aMouseEvt ); 3109 } 3110 3111 if( bClosePopups ) 3112 { 3113 /* #108213# close popups after dispatching the event outside the popup; 3114 * applications do weird things. 3115 */ 3116 ImplSVData* pSVData = ImplGetSVData(); 3117 if ( pSVData->maWinData.mpFirstFloat ) 3118 { 3119 static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" ); 3120 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) ) 3121 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL ); 3122 } 3123 } 3124 3125 return nRet; 3126 } 3127 3128 // F10 means either KEY_F10 or KEY_MENU, which has to be decided 3129 // in the independent part. 3130 struct KeyAlternate 3131 { 3132 sal_uInt16 nKeyCode; 3133 sal_Unicode nCharCode; 3134 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {} 3135 KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {} 3136 }; 3137 3138 inline KeyAlternate 3139 GetAlternateKeyCode( const sal_uInt16 nKeyCode ) 3140 { 3141 KeyAlternate aAlternate; 3142 3143 switch( nKeyCode ) 3144 { 3145 case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break; 3146 case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break; 3147 } 3148 3149 return aAlternate; 3150 } 3151 3152 void X11SalFrame::beginUnicodeSequence() 3153 { 3154 rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); 3155 DeletionListener aDeleteWatch( this ); 3156 3157 if( rSeq.getLength() ) 3158 endUnicodeSequence(); 3159 3160 rSeq = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "u" ) ); 3161 3162 if( ! aDeleteWatch.isDeleted() ) 3163 { 3164 sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE; 3165 SalExtTextInputEvent aEv; 3166 aEv.mnTime = 0; 3167 aEv.maText = rSeq; 3168 aEv.mpTextAttr = &nTextAttr; 3169 aEv.mnCursorPos = 0; 3170 aEv.mnDeltaStart = 0; 3171 aEv.mnCursorFlags = 0; 3172 aEv.mbOnlyCursor = sal_False; 3173 3174 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); 3175 } 3176 } 3177 3178 bool X11SalFrame::appendUnicodeSequence( sal_Unicode c ) 3179 { 3180 bool bRet = false; 3181 rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); 3182 if( rSeq.getLength() > 0 ) 3183 { 3184 // range check 3185 if( (c >= sal_Unicode('0') && c <= sal_Unicode('9')) || 3186 (c >= sal_Unicode('a') && c <= sal_Unicode('f')) || 3187 (c >= sal_Unicode('A') && c <= sal_Unicode('F')) ) 3188 { 3189 rtl::OUStringBuffer aBuf( rSeq.getLength() + 1 ); 3190 aBuf.append( rSeq ); 3191 aBuf.append( c ); 3192 rSeq = aBuf.makeStringAndClear(); 3193 std::vector<sal_uInt16> attribs( rSeq.getLength(), SAL_EXTTEXTINPUT_ATTR_UNDERLINE ); 3194 3195 SalExtTextInputEvent aEv; 3196 aEv.mnTime = 0; 3197 aEv.maText = rSeq; 3198 aEv.mpTextAttr = &attribs[0]; 3199 aEv.mnCursorPos = 0; 3200 aEv.mnDeltaStart = 0; 3201 aEv.mnCursorFlags = 0; 3202 aEv.mbOnlyCursor = sal_False; 3203 3204 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); 3205 bRet = true; 3206 } 3207 else 3208 bRet = endUnicodeSequence(); 3209 } 3210 else 3211 endUnicodeSequence(); 3212 return bRet; 3213 } 3214 3215 bool X11SalFrame::endUnicodeSequence() 3216 { 3217 rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); 3218 3219 DeletionListener aDeleteWatch( this ); 3220 if( rSeq.getLength() > 1 && rSeq.getLength() < 6 ) 3221 { 3222 // cut the "u" 3223 rtl::OUString aNumbers( rSeq.copy( 1 ) ); 3224 sal_Int32 nValue = aNumbers.toInt32( 16 ); 3225 if( nValue >= 32 ) 3226 { 3227 sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE; 3228 SalExtTextInputEvent aEv; 3229 aEv.mnTime = 0; 3230 aEv.maText = rtl::OUString( sal_Unicode(nValue) ); 3231 aEv.mpTextAttr = &nTextAttr; 3232 aEv.mnCursorPos = 0; 3233 aEv.mnDeltaStart = 0; 3234 aEv.mnCursorFlags = 0; 3235 aEv.mbOnlyCursor = sal_False; 3236 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); 3237 } 3238 } 3239 bool bWasInput = rSeq.getLength() > 0; 3240 rSeq = rtl::OUString(); 3241 if( bWasInput && ! aDeleteWatch.isDeleted() ) 3242 CallCallback(SALEVENT_ENDEXTTEXTINPUT, NULL); 3243 return bWasInput; 3244 } 3245 3246 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3247 long X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent ) 3248 { 3249 KeySym nKeySym; 3250 KeySym nUnmodifiedKeySym; 3251 int nLen = 2048; 3252 unsigned char *pPrintable = (unsigned char*)alloca( nLen ); 3253 3254 // singlebyte code composed by input method, the new default 3255 if (mpInputContext != NULL && mpInputContext->UseContext()) 3256 { 3257 // returns a keysym as well as the pPrintable (in system encoding) 3258 // printable may be empty. 3259 Status nStatus; 3260 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, 3261 &nUnmodifiedKeySym, 3262 &nStatus, mpInputContext->GetContext() ); 3263 if ( nStatus == XBufferOverflow ) 3264 { 3265 nLen *= 2; 3266 pPrintable = (unsigned char*)alloca( nLen ); 3267 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, 3268 &nUnmodifiedKeySym, 3269 &nStatus, mpInputContext->GetContext() ); 3270 } 3271 } 3272 else 3273 { 3274 // fallback, this should never ever be called 3275 Status nStatus = 0; 3276 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus ); 3277 } 3278 3279 SalKeyEvent aKeyEvt; 3280 sal_uInt16 nKeyCode; 3281 sal_uInt16 nModCode = 0; 3282 char aDummy; 3283 3284 if( pEvent->state & ShiftMask ) 3285 nModCode |= KEY_SHIFT; 3286 if( pEvent->state & ControlMask ) 3287 nModCode |= KEY_MOD1; 3288 if( pEvent->state & Mod1Mask ) 3289 nModCode |= KEY_MOD2; 3290 3291 if( nModCode != (KEY_SHIFT|KEY_MOD1) ) 3292 endUnicodeSequence(); 3293 3294 if( nKeySym == XK_Shift_L || nKeySym == XK_Shift_R 3295 || nKeySym == XK_Control_L || nKeySym == XK_Control_R 3296 || nKeySym == XK_Alt_L || nKeySym == XK_Alt_R 3297 || nKeySym == XK_Meta_L || nKeySym == XK_Meta_R 3298 || nKeySym == XK_Super_L || nKeySym == XK_Super_R ) 3299 { 3300 SalKeyModEvent aModEvt; 3301 aModEvt.mnModKeyCode = 0; 3302 if( pEvent->type == XLIB_KeyPress && mnExtKeyMod == 0 ) 3303 mbSendExtKeyModChange = true; 3304 else if( pEvent->type == KeyRelease && mbSendExtKeyModChange ) 3305 { 3306 aModEvt.mnModKeyCode = mnExtKeyMod; 3307 mnExtKeyMod = 0; 3308 } 3309 3310 // pressing just the ctrl key leads to a keysym of XK_Control but 3311 // the event state does not contain ControlMask. In the release 3312 // event its the other way round: it does contain the Control mask. 3313 // The modifier mode therefore has to be adapted manually. 3314 sal_uInt16 nExtModMask = 0; 3315 sal_uInt16 nModMask = 0; 3316 switch( nKeySym ) 3317 { 3318 case XK_Control_L: 3319 nExtModMask = MODKEY_LMOD1; 3320 nModMask = KEY_MOD1; 3321 break; 3322 case XK_Control_R: 3323 nExtModMask = MODKEY_RMOD1; 3324 nModMask = KEY_MOD1; 3325 break; 3326 case XK_Alt_L: 3327 nExtModMask = MODKEY_LMOD2; 3328 nModMask = KEY_MOD2; 3329 break; 3330 case XK_Alt_R: 3331 nExtModMask = MODKEY_RMOD2; 3332 nModMask = KEY_MOD2; 3333 break; 3334 case XK_Shift_L: 3335 nExtModMask = MODKEY_LSHIFT; 3336 nModMask = KEY_SHIFT; 3337 break; 3338 case XK_Shift_R: 3339 nExtModMask = MODKEY_RSHIFT; 3340 nModMask = KEY_SHIFT; 3341 break; 3342 // Map Meta/Super keys to MOD3 modifier on all Unix systems 3343 // except Mac OS X 3344 case XK_Meta_L: 3345 case XK_Super_L: 3346 nExtModMask = MODKEY_LMOD3; 3347 nModMask = KEY_MOD3; 3348 break; 3349 case XK_Meta_R: 3350 case XK_Super_R: 3351 nExtModMask = MODKEY_RMOD3; 3352 nModMask = KEY_MOD3; 3353 break; 3354 } 3355 if( pEvent->type == KeyRelease ) 3356 { 3357 nModCode &= ~nModMask; 3358 mnExtKeyMod &= ~nExtModMask; 3359 } 3360 else 3361 { 3362 nModCode |= nModMask; 3363 mnExtKeyMod |= nExtModMask; 3364 } 3365 3366 aModEvt.mnCode = nModCode; 3367 aModEvt.mnTime = pEvent->time; 3368 3369 int nRet = CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt ); 3370 3371 // emulate KEY_MENU 3372 if ( ( (nKeySym == XK_Alt_L) || (nKeySym == XK_Alt_R) ) && 3373 ( (nModCode & ~(KEY_MOD3|KEY_MOD2)) == 0 ) ) 3374 { 3375 if( pEvent->type == XLIB_KeyPress ) 3376 mbKeyMenu = true; 3377 else if( mbKeyMenu ) 3378 { 3379 // simulate KEY_MENU 3380 aKeyEvt.mnCode = KEY_MENU | nModCode; 3381 aKeyEvt.mnRepeat = 0; 3382 aKeyEvt.mnTime = pEvent->time; 3383 aKeyEvt.mnCharCode = 0; 3384 nRet = CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 3385 nRet = CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3386 } 3387 } 3388 else 3389 mbKeyMenu = false; 3390 return nRet; 3391 } 3392 3393 mbSendExtKeyModChange = mbKeyMenu = false; 3394 3395 // try to figure out the vcl code for the keysym 3396 // #i52338# use the unmodified KeySym if there is none for the real KeySym 3397 // because the independent part has only keycodes for unshifted keys 3398 nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy ); 3399 if( nKeyCode == 0 ) 3400 nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy ); 3401 3402 // try to figure out a printable if XmbLookupString returns only a keysym 3403 // and NOT a printable. Do not store it in pPrintable[0] since it is expected to 3404 // be in system encoding, not unicode. 3405 // #i8988##, if KeySym and printable look equally promising then prefer KeySym 3406 // the printable is bound to the encoding so the KeySym might contain more 3407 // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and 3408 // (the desired) Zcaron in KeySym 3409 sal_Unicode nKeyString = 0x0; 3410 if ( (nLen == 0) 3411 || ((nLen == 1) && (nKeySym > 0)) ) 3412 nKeyString = KeysymToUnicode (nKeySym); 3413 // if we have nothing we give up 3414 if( !nKeyCode && !nLen && !nKeyString) 3415 return 0; 3416 3417 DeletionListener aDeleteWatch( this ); 3418 3419 if( nModCode == (KEY_SHIFT | KEY_MOD1) && pEvent->type == XLIB_KeyPress ) 3420 { 3421 sal_uInt16 nSeqKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy ); 3422 if( nSeqKeyCode == KEY_U ) 3423 { 3424 beginUnicodeSequence(); 3425 return 1; 3426 } 3427 else if( nSeqKeyCode >= KEY_0 && nSeqKeyCode <= KEY_9 ) 3428 { 3429 if( appendUnicodeSequence( sal_Unicode( '0' ) + sal_Unicode(nSeqKeyCode - KEY_0) ) ) 3430 return 1; 3431 } 3432 else if( nSeqKeyCode >= KEY_A && nSeqKeyCode <= KEY_F ) 3433 { 3434 if( appendUnicodeSequence( sal_Unicode( 'a' ) + sal_Unicode(nSeqKeyCode - KEY_A) ) ) 3435 return 1; 3436 } 3437 else 3438 endUnicodeSequence(); 3439 } 3440 3441 if( aDeleteWatch.isDeleted() ) 3442 return 0; 3443 3444 rtl_TextEncoding nEncoding; 3445 3446 if (mpInputContext != NULL && mpInputContext->IsMultiLingual() ) 3447 nEncoding = RTL_TEXTENCODING_UTF8; 3448 else 3449 nEncoding = osl_getThreadTextEncoding(); 3450 3451 sal_Unicode *pBuffer; 3452 sal_Unicode *pString; 3453 sal_Size nBufferSize = nLen * 2; 3454 sal_Size nSize; 3455 pBuffer = (sal_Unicode*) malloc( nBufferSize + 2 ); 3456 pBuffer[ 0 ] = 0; 3457 3458 if (nKeyString != 0) 3459 { 3460 pString = &nKeyString; 3461 nSize = 1; 3462 } 3463 else 3464 if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE) 3465 { 3466 // create text converter 3467 rtl_TextToUnicodeConverter aConverter = 3468 rtl_createTextToUnicodeConverter( nEncoding ); 3469 rtl_TextToUnicodeContext aContext = 3470 rtl_createTextToUnicodeContext( aConverter ); 3471 3472 sal_uInt32 nConversionInfo; 3473 sal_Size nConvertedChars; 3474 3475 // convert to single byte text stream 3476 nSize = rtl_convertTextToUnicode( 3477 aConverter, aContext, 3478 (char*)pPrintable, nLen, 3479 pBuffer, nBufferSize, 3480 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE | 3481 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE, 3482 &nConversionInfo, &nConvertedChars ); 3483 3484 // destroy converter 3485 rtl_destroyTextToUnicodeContext( aConverter, aContext ); 3486 rtl_destroyTextToUnicodeConverter( aConverter ); 3487 3488 pString = pBuffer; 3489 } 3490 else 3491 if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */) 3492 { 3493 pString = (sal_Unicode*)pPrintable; 3494 nSize = nLen; 3495 } 3496 else 3497 { 3498 pString = pBuffer; 3499 nSize = 0; 3500 } 3501 3502 if ( mpInputContext != NULL 3503 && mpInputContext->UseContext() 3504 && KeyRelease != pEvent->type 3505 && ( (nSize > 1) 3506 || (nSize > 0 && mpInputContext->IsPreeditMode())) ) 3507 { 3508 mpInputContext->CommitKeyEvent(pString, nSize); 3509 } 3510 else 3511 // normal single character keyinput 3512 { 3513 aKeyEvt.mnCode = nKeyCode | nModCode; 3514 aKeyEvt.mnRepeat = 0; 3515 aKeyEvt.mnTime = pEvent->time; 3516 aKeyEvt.mnCharCode = pString[ 0 ]; 3517 3518 if( KeyRelease == pEvent->type ) 3519 { 3520 CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3521 } 3522 else 3523 { 3524 if ( ! CallCallback(SALEVENT_KEYINPUT, &aKeyEvt) ) 3525 { 3526 // independent layer doesnt want to handle key-event, so check 3527 // whether the keycode may have an alternate meaning 3528 KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode ); 3529 if ( aAlternate.nKeyCode != 0 ) 3530 { 3531 aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode; 3532 if( aAlternate.nCharCode ) 3533 aKeyEvt.mnCharCode = aAlternate.nCharCode; 3534 CallCallback(SALEVENT_KEYINPUT, &aKeyEvt); 3535 } 3536 } 3537 } 3538 } 3539 3540 // 3541 // update the spot location for PreeditPosition IME style 3542 // 3543 if (! aDeleteWatch.isDeleted()) 3544 { 3545 if (mpInputContext != NULL && mpInputContext->UseContext()) 3546 mpInputContext->UpdateSpotLocation(); 3547 } 3548 3549 free (pBuffer); 3550 return True; 3551 } 3552 3553 3554 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3555 long X11SalFrame::HandleFocusEvent( XFocusChangeEvent *pEvent ) 3556 { 3557 // #107739# ReflectionX in Windows mode changes focus while mouse is grabbed 3558 if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "ReflectionX Windows" ) ) 3559 return 1; 3560 3561 /* #55691# ignore focusout resulting from keyboard grabs 3562 * we do not grab it and are not interested when 3563 * someone else does CDE e.g. does a XGrabKey on arrow keys 3564 * #73179# handle focus events with mode NotifyWhileGrabbed 3565 * because with CDE alt-tab focus changing we do not get 3566 * normal focus events 3567 * #71791# cast focus event to the input context, otherwise the 3568 * status window does not follow the application frame 3569 */ 3570 3571 if ( mpInputContext != NULL ) 3572 { 3573 if( FocusIn == pEvent->type ) 3574 mpInputContext->SetICFocus( this ); 3575 else 3576 { 3577 /* 3578 * do not unset the IC focuse here because would kill 3579 * a lookup choice windows that might have the focus now 3580 * mpInputContext->UnsetICFocus( this ); 3581 */ 3582 I18NStatus::get().show( false, I18NStatus::focus ); 3583 } 3584 } 3585 3586 3587 if ( pEvent->mode == NotifyNormal || pEvent->mode == NotifyWhileGrabbed || 3588 ( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() ) 3589 ) 3590 { 3591 if( hPresentationWindow != None && hPresentationWindow != GetShellWindow() ) 3592 return 0; 3593 3594 if( FocusIn == pEvent->type ) 3595 { 3596 vcl_sal::PrinterUpdate::update(); 3597 mbInputFocus = True; 3598 ImplSVData* pSVData = ImplGetSVData(); 3599 3600 3601 3602 long nRet = CallCallback( SALEVENT_GETFOCUS, 0 ); 3603 if ((mpParent != NULL && nStyle_ == 0) 3604 && pSVData->maWinData.mpFirstFloat ) 3605 { 3606 sal_uLong nMode = pSVData->maWinData.mpFirstFloat->GetPopupModeFlags(); 3607 pSVData->maWinData.mpFirstFloat->SetPopupModeFlags( 3608 nMode & ~(FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE)); 3609 } 3610 return nRet; 3611 } 3612 else 3613 { 3614 mbInputFocus = False; 3615 mbSendExtKeyModChange = mbKeyMenu = false; 3616 mnExtKeyMod = 0; 3617 return CallCallback( SALEVENT_LOSEFOCUS, 0 ); 3618 } 3619 } 3620 3621 return 0; 3622 } 3623 3624 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3625 3626 long X11SalFrame::HandleExposeEvent( XEvent *pEvent ) 3627 { 3628 XRectangle aRect = { 0, 0, 0, 0 }; 3629 sal_uInt16 nCount = 0; 3630 3631 if( pEvent->type == Expose ) 3632 { 3633 aRect.x = pEvent->xexpose.x; 3634 aRect.y = pEvent->xexpose.y; 3635 aRect.width = pEvent->xexpose.width; 3636 aRect.height = pEvent->xexpose.height; 3637 nCount = pEvent->xexpose.count; 3638 } 3639 else if( pEvent->type == GraphicsExpose ) 3640 { 3641 aRect.x = pEvent->xgraphicsexpose.x; 3642 aRect.y = pEvent->xgraphicsexpose.y; 3643 aRect.width = pEvent->xgraphicsexpose.width; 3644 aRect.height = pEvent->xgraphicsexpose.height; 3645 nCount = pEvent->xgraphicsexpose.count; 3646 } 3647 3648 if( IsOverrideRedirect() && mbFullScreen && 3649 aPresentationReparentList.begin() == aPresentationReparentList.end() ) 3650 // we are in fullscreen mode -> override redirect 3651 // focus is possibly lost, so reget it 3652 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone, CurrentTime ); 3653 3654 // width and height are extents, so they are of by one for rectangle 3655 maPaintRegion.Union( Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) ); 3656 3657 if( nCount ) 3658 // wait for last expose rectangle, do not wait for resize timer 3659 // if a completed graphics expose sequence is available 3660 return 1; 3661 3662 SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() ); 3663 3664 CallCallback( SALEVENT_PAINT, &aPEvt ); 3665 maPaintRegion = Rectangle(); 3666 3667 return 1; 3668 } 3669 3670 void X11SalFrame::RestackChildren( XLIB_Window* pTopLevelWindows, int nTopLevelWindows ) 3671 { 3672 if( maChildren.begin() != maChildren.end() ) 3673 { 3674 int nWindow = nTopLevelWindows; 3675 while( nWindow-- ) 3676 if( pTopLevelWindows[nWindow] == GetStackingWindow() ) 3677 break; 3678 if( nWindow < 0 ) 3679 return; 3680 3681 std::list< X11SalFrame* >::const_iterator it; 3682 for( it = maChildren.begin(); it != maChildren.end(); ++it ) 3683 { 3684 X11SalFrame* pData = *it; 3685 if( pData->bMapped_ ) 3686 { 3687 int nChild = nWindow; 3688 while( nChild-- ) 3689 { 3690 if( pTopLevelWindows[nChild] == pData->GetStackingWindow() ) 3691 { 3692 // if a child is behind its parent, place it above the 3693 // parent (for insane WMs like Dtwm and olwm) 3694 XWindowChanges aCfg; 3695 aCfg.sibling = GetStackingWindow(); 3696 aCfg.stack_mode = Above; 3697 XConfigureWindow( GetXDisplay(), pData->GetStackingWindow(), CWSibling|CWStackMode, &aCfg ); 3698 break; 3699 } 3700 } 3701 } 3702 } 3703 for( it = maChildren.begin(); it != maChildren.end(); ++it ) 3704 { 3705 X11SalFrame* pData = *it; 3706 pData->RestackChildren( pTopLevelWindows, nTopLevelWindows ); 3707 } 3708 } 3709 } 3710 3711 void X11SalFrame::RestackChildren() 3712 { 3713 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() 3714 && maChildren.begin() != maChildren.end() ) 3715 { 3716 XLIB_Window aRoot, aParent, *pChildren = NULL; 3717 unsigned int nChildren; 3718 if( XQueryTree( GetXDisplay(), 3719 GetDisplay()->GetRootWindow( m_nScreen ), 3720 &aRoot, 3721 &aParent, 3722 &pChildren, 3723 &nChildren ) ) 3724 { 3725 RestackChildren( pChildren, nChildren ); 3726 XFree( pChildren ); 3727 } 3728 } 3729 } 3730 3731 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3732 long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent ) 3733 { 3734 if ( pEvent->window != GetShellWindow() 3735 && pEvent->window != GetWindow() 3736 && pEvent->window != GetForeignParent() 3737 && pEvent->window != GetStackingWindow() 3738 ) 3739 { 3740 // could be as well a sys-child window (aka SalObject) 3741 return 1; 3742 } 3743 3744 3745 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() ) 3746 { 3747 // just update the children's positions 3748 RestackChildren(); 3749 return 1; 3750 } 3751 3752 if( pEvent->window == GetForeignParent() ) 3753 XResizeWindow( GetXDisplay(), 3754 GetWindow(), 3755 pEvent->width, 3756 pEvent->height ); 3757 3758 XLIB_Window hDummy; 3759 XTranslateCoordinates( GetXDisplay(), 3760 GetWindow(), 3761 pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ), 3762 0, 0, 3763 &pEvent->x, &pEvent->y, 3764 &hDummy ); 3765 3766 if( pEvent->window == GetStackingWindow() ) 3767 { 3768 if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y ) 3769 { 3770 maGeometry.nX = pEvent->x; 3771 maGeometry.nY = pEvent->y; 3772 CallCallback( SALEVENT_MOVE, NULL ); 3773 } 3774 return 1; 3775 } 3776 3777 // check size hints in first time SalFrame::Show 3778 if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ ) 3779 nShowState_ = SHOWSTATE_NORMAL; 3780 3781 nWidth_ = pEvent->width; 3782 nHeight_ = pEvent->height; 3783 3784 bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY ); 3785 bool bSized = ( pEvent->width != (int)maGeometry.nWidth || pEvent->height != (int)maGeometry.nHeight ); 3786 3787 maGeometry.nX = pEvent->x; 3788 maGeometry.nY = pEvent->y; 3789 maGeometry.nWidth = pEvent->width; 3790 maGeometry.nHeight = pEvent->height; 3791 updateScreenNumber(); 3792 3793 // update children's position 3794 RestackChildren(); 3795 3796 if( bSized && ! bMoved ) 3797 CallCallback( SALEVENT_RESIZE, NULL ); 3798 else if( bMoved && ! bSized ) 3799 CallCallback( SALEVENT_MOVE, NULL ); 3800 else if( bMoved && bSized ) 3801 CallCallback( SALEVENT_MOVERESIZE, NULL ); 3802 3803 return 1; 3804 } 3805 3806 IMPL_LINK( X11SalFrame, HandleAlwaysOnTopRaise, void*, EMPTYARG ) 3807 { 3808 if( bMapped_ ) 3809 ToTop( 0 ); 3810 return 0; 3811 } 3812 3813 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3814 long X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent ) 3815 { 3816 Display *pDisplay = pEvent->display; 3817 XLIB_Window hWM_Parent; 3818 XLIB_Window hRoot, *Children, hDummy; 3819 unsigned int nChildren; 3820 sal_Bool bNone = pDisplay_->GetProperties() 3821 & PROPERTY_SUPPORT_WM_Parent_Pixmap_None; 3822 sal_Bool bAccessParentWindow = ! (pDisplay_->GetProperties() 3823 & PROPERTY_FEATURE_TrustedSolaris); 3824 3825 static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" ); 3826 3827 GetDisplay()->GetXLib()->PushXErrorLevel( true ); 3828 3829 /* 3830 * #89186# don't rely on the new parent from the event. 3831 * the event may be "out of date", that is the window manager 3832 * window may not exist anymore. This can happen if someone 3833 * shows a frame and hides it again quickly (not that that would 3834 * be very sensible) 3835 */ 3836 hWM_Parent = GetShellWindow(); 3837 do 3838 { 3839 Children = NULL; 3840 XQueryTree( pDisplay, 3841 hWM_Parent, 3842 &hRoot, 3843 &hDummy, 3844 &Children, 3845 &nChildren ); 3846 if( GetDisplay()->GetXLib()->HasXErrorOccured() ) 3847 { 3848 hWM_Parent = GetShellWindow(); 3849 break; 3850 } 3851 /* #107048# this sometimes happens if a Show(sal_True) is 3852 * immediately followed by Show(sal_False) (which is braindead anyway) 3853 */ 3854 if( hDummy == hWM_Parent ) 3855 hDummy = hRoot; 3856 if( hDummy != hRoot ) 3857 { 3858 hWM_Parent = hDummy; 3859 if( bAccessParentWindow && bNone ) 3860 XSetWindowBackgroundPixmap( pDisplay, hWM_Parent, None ); 3861 } 3862 if( Children ) 3863 XFree( Children ); 3864 } while( hDummy != hRoot ); 3865 3866 if( GetStackingWindow() == None 3867 && hWM_Parent != hPresentationWindow 3868 && hWM_Parent != GetShellWindow() 3869 && ( ! pDisableStackingCheck || ! *pDisableStackingCheck ) 3870 ) 3871 { 3872 mhStackingWindow = hWM_Parent; 3873 if (bAccessParentWindow) 3874 XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask ); 3875 } 3876 3877 if( hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ) 3878 || hWM_Parent == GetForeignParent() 3879 || pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ) 3880 || ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) 3881 { 3882 // Reparenting before Destroy 3883 aPresentationReparentList.remove( GetStackingWindow() ); 3884 mhStackingWindow = None; 3885 GetDisplay()->GetXLib()->PopXErrorLevel(); 3886 return 0; 3887 } 3888 3889 /* 3890 * evil hack to show decorated windows on top 3891 * of override redirect presentation windows: 3892 * reparent the window manager window to the presentation window 3893 * does not work with non-reparenting WMs 3894 * in future this should not be necessary anymore with 3895 * _NET_WM_STATE_FULLSCREEN available 3896 */ 3897 if( hPresentationWindow != None 3898 && hPresentationWindow != GetWindow() 3899 && GetStackingWindow() != None 3900 && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nScreen ) 3901 ) 3902 { 3903 int x = 0, y = 0; 3904 XLIB_Window aChild; 3905 XTranslateCoordinates( GetXDisplay(), 3906 GetStackingWindow(), 3907 GetDisplay()->GetRootWindow( m_nScreen ), 3908 0, 0, 3909 &x, &y, 3910 &aChild 3911 ); 3912 XReparentWindow( GetXDisplay(), 3913 GetStackingWindow(), 3914 hPresentationWindow, 3915 x, y 3916 ); 3917 aPresentationReparentList.push_back( GetStackingWindow() ); 3918 } 3919 3920 int nLeft = 0, nTop = 0; 3921 XTranslateCoordinates( GetXDisplay(), 3922 GetShellWindow(), 3923 hWM_Parent, 3924 0, 0, 3925 &nLeft, 3926 &nTop, 3927 &hDummy ); 3928 maGeometry.nLeftDecoration = nLeft > 0 ? nLeft-1 : 0; 3929 maGeometry.nTopDecoration = nTop > 0 ? nTop-1 : 0; 3930 3931 /* 3932 * decorations are not symmetric, 3933 * so need real geometries here 3934 * (this will fail with virtual roots ?) 3935 */ 3936 GetDisplay()->GetXLib()->ResetXErrorOccured(); 3937 int xp, yp, x, y; 3938 unsigned int wp, w, hp, h, bw, d; 3939 XGetGeometry( GetXDisplay(), 3940 GetShellWindow(), 3941 &hRoot, 3942 &x, &y, &w, &h, &bw, &d ); 3943 XGetGeometry( GetXDisplay(), 3944 hWM_Parent, 3945 &hRoot, 3946 &xp, &yp, &wp, &hp, &bw, &d ); 3947 bool bResized = false; 3948 if( ! GetDisplay()->GetXLib()->HasXErrorOccured() ) 3949 { 3950 maGeometry.nRightDecoration = wp - w - maGeometry.nLeftDecoration; 3951 maGeometry.nBottomDecoration = hp - h - maGeometry.nTopDecoration; 3952 /* 3953 * note: this works because hWM_Parent is direct child of root, 3954 * not necessarily parent of GetShellWindow() 3955 */ 3956 maGeometry.nX = xp + nLeft; 3957 maGeometry.nY = yp + nTop; 3958 bResized = w != maGeometry.nWidth || h != maGeometry.nHeight; 3959 maGeometry.nWidth = w; 3960 maGeometry.nHeight = h; 3961 } 3962 3963 3964 // limit width and height if we are too large: #47757 3965 // olwm and fvwm need this, it doesnt harm the rest 3966 3967 // #i81311# do this only for sizable frames 3968 if( (nStyle_ & SAL_FRAME_STYLE_SIZEABLE) != 0 ) 3969 { 3970 Size aScreenSize = GetDisplay()->GetScreenSize( m_nScreen ); 3971 int nScreenWidth = aScreenSize.Width(); 3972 int nScreenHeight = aScreenSize.Height(); 3973 int nFrameWidth = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration; 3974 int nFrameHeight = maGeometry.nHeight + maGeometry.nTopDecoration + maGeometry.nBottomDecoration; 3975 3976 if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight)) 3977 { 3978 Size aSize(maGeometry.nWidth, maGeometry.nHeight); 3979 3980 if (nFrameWidth > nScreenWidth) 3981 aSize.Width() = nScreenWidth - maGeometry.nRightDecoration - maGeometry.nLeftDecoration; 3982 if (nFrameHeight > nScreenHeight) 3983 aSize.Height() = nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration; 3984 3985 SetSize( aSize ); 3986 bResized = false; 3987 } 3988 } 3989 if( bResized ) 3990 CallCallback( SALEVENT_RESIZE, NULL ); 3991 3992 GetDisplay()->GetXLib()->PopXErrorLevel(); 3993 3994 return 1; 3995 } 3996 3997 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3998 long X11SalFrame::HandleColormapEvent( XColormapEvent* ) 3999 { 4000 return 0; 4001 } 4002 4003 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 4004 long X11SalFrame::HandleStateEvent( XPropertyEvent *pEvent ) 4005 { 4006 Atom actual_type; 4007 int actual_format; 4008 unsigned long nitems, bytes_after; 4009 unsigned char *prop = NULL; 4010 4011 if( 0 != XGetWindowProperty( GetXDisplay(), 4012 GetShellWindow(), 4013 pEvent->atom, // property 4014 0, // long_offset (32bit) 4015 2, // long_length (32bit) 4016 False, // delete 4017 pEvent->atom, // req_type 4018 &actual_type, 4019 &actual_format, 4020 &nitems, 4021 &bytes_after, 4022 &prop ) 4023 || ! prop 4024 ) 4025 return 0; 4026 4027 DBG_ASSERT( actual_type = pEvent->atom 4028 && 32 == actual_format 4029 && 2 == nitems 4030 && 0 == bytes_after, "HandleStateEvent" ); 4031 4032 if( *(unsigned long*)prop == NormalState ) 4033 nShowState_ = SHOWSTATE_NORMAL; 4034 else if( *(unsigned long*)prop == IconicState ) 4035 nShowState_ = SHOWSTATE_MINIMIZED; 4036 4037 XFree( prop ); 4038 return 1; 4039 } 4040 4041 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 4042 long X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent ) 4043 { 4044 const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() ); 4045 4046 #if !defined(__synchronous_extinput__) 4047 if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) ) 4048 { 4049 HandleExtTextEvent (pEvent); 4050 return 1; 4051 } 4052 #endif 4053 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) ) 4054 { 4055 stderr0( "X11SalFrame::Dispatch Quit\n" ); 4056 Close(); // ??? 4057 return 1; 4058 } 4059 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS ) ) 4060 { 4061 if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::NET_WM_PING ) ) 4062 rWMAdaptor.answerPing( this, pEvent ); 4063 else if( ! ( nStyle_ & SAL_FRAME_STYLE_PLUG ) 4064 && ! (( nStyle_ & SAL_FRAME_STYLE_FLOAT ) && (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)) 4065 ) 4066 { 4067 if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) ) 4068 { 4069 Close(); 4070 return 1; 4071 } 4072 else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) ) 4073 { 4074 // do nothing, we set the input focus in ToTop() if necessary 4075 #if OSL_DEBUG_LEVEL > 1 4076 fprintf( stderr, "got WM_TAKE_FOCUS on %s window\n", 4077 (nStyle_&SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? 4078 "ownerdraw" : "NON OWNERDRAW" ); 4079 #endif 4080 } 4081 else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_SAVE_YOURSELF ) ) 4082 { 4083 bool bSession = rWMAdaptor.getWindowManagerName().EqualsAscii( "Dtwm" ); 4084 4085 if( ! bSession ) 4086 { 4087 if( this == s_pSaveYourselfFrame ) 4088 { 4089 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() ); 4090 const char* argv[2]; 4091 argv[0] = "/bin/sh"; 4092 argv[1] = const_cast<char*>(aExec.GetBuffer()); 4093 #if OSL_DEBUG_LEVEL > 1 4094 fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] ); 4095 #endif 4096 XSetCommand( GetXDisplay(), GetShellWindow(), (char**)argv, 2 ); 4097 } 4098 else 4099 // can only happen in race between WM and window closing 4100 XChangeProperty( GetXDisplay(), GetShellWindow(), rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 ); 4101 } 4102 else 4103 { 4104 // save open documents; would be good for non Dtwm, too, 4105 // but there is no real Shutdown message in the ancient 4106 // SM protocol; on Dtwm SaveYourself really means Shutdown, too. 4107 IceSalSession::handleOldX11SaveYourself( this ); 4108 } 4109 } 4110 } 4111 } 4112 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) && 4113 pEvent->window == GetWindow() ) 4114 { 4115 if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE 4116 pEvent->data.l[1] == 2 ) // XEMBED_WINDOW_DEACTIVATE 4117 { 4118 XFocusChangeEvent aEvent; 4119 aEvent.type = (pEvent->data.l[1] == 1 ? FocusIn : FocusOut); 4120 aEvent.serial = pEvent->serial; 4121 aEvent.send_event = True; 4122 aEvent.display = pEvent->display; 4123 aEvent.window = pEvent->window; 4124 aEvent.mode = NotifyNormal; 4125 aEvent.detail = NotifyDetailNone; 4126 HandleFocusEvent( &aEvent ); 4127 } 4128 } 4129 return 0; 4130 } 4131 4132 void X11SalFrame::SaveYourselfDone( SalFrame* pSaveFrame ) 4133 { 4134 // session save was done, inform dtwm 4135 if( s_pSaveYourselfFrame && pSaveFrame ) 4136 { 4137 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() ); 4138 const char* argv[2]; 4139 argv[0] = "/bin/sh"; 4140 argv[1] = const_cast<char*>(aExec.GetBuffer()); 4141 #if OSL_DEBUG_LEVEL > 1 4142 fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] ); 4143 #endif 4144 XSetCommand( s_pSaveYourselfFrame->GetXDisplay(), 4145 s_pSaveYourselfFrame->GetShellWindow(), 4146 (char**)argv, 2 ); 4147 if( pSaveFrame != s_pSaveYourselfFrame ) 4148 { 4149 // check if it still exists 4150 const X11SalFrame* pFrame = NULL; 4151 const std::list< SalFrame* >& rFrames = static_cast<X11SalFrame*>(pSaveFrame)->GetDisplay()->getFrames(); 4152 std::list< SalFrame* >::const_iterator it = rFrames.begin(); 4153 while( it != rFrames.end() ) 4154 { 4155 pFrame = static_cast< const X11SalFrame* >(*it); 4156 if( pFrame == pSaveFrame ) 4157 break; 4158 ++it; 4159 } 4160 if( pFrame == pSaveFrame ) 4161 { 4162 const WMAdaptor& rWMAdaptor( *pFrame->pDisplay_->getWMAdaptor() ); 4163 XChangeProperty( pFrame->GetXDisplay(), 4164 pFrame->GetShellWindow(), 4165 rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 ); 4166 } 4167 } 4168 s_pSaveYourselfFrame->ShutDown(); 4169 } 4170 } 4171 4172 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 4173 4174 extern "C" 4175 { 4176 Bool call_checkKeyReleaseForRepeat( Display* pDisplay, XEvent* pCheck, XPointer pX11SalFrame ) 4177 { 4178 return X11SalFrame::checkKeyReleaseForRepeat( pDisplay, pCheck, pX11SalFrame ); 4179 } 4180 } 4181 4182 Bool X11SalFrame::checkKeyReleaseForRepeat( Display*, XEvent* pCheck, XPointer pX11SalFrame ) 4183 { 4184 X11SalFrame* pThis = (X11SalFrame*)pX11SalFrame; 4185 return 4186 pCheck->type == XLIB_KeyPress && 4187 pCheck->xkey.state == pThis->nKeyState_ && 4188 pCheck->xkey.keycode == pThis->nKeyCode_ && 4189 pCheck->xkey.time == pThis->nReleaseTime_ ? True : False; 4190 } 4191 4192 long X11SalFrame::Dispatch( XEvent *pEvent ) 4193 { 4194 long nRet = 0; 4195 4196 if( -1 == nCaptured_ ) 4197 { 4198 CaptureMouse( sal_True ); 4199 #ifdef DBG_UTIL 4200 if( -1 != nCaptured_ ) 4201 pDisplay_->PrintEvent( "Captured", pEvent ); 4202 #endif 4203 } 4204 4205 if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() ) 4206 { 4207 switch( pEvent->type ) 4208 { 4209 case XLIB_KeyPress: 4210 nKeyCode_ = pEvent->xkey.keycode; 4211 nKeyState_ = pEvent->xkey.state; 4212 nRet = HandleKeyEvent( &pEvent->xkey ); 4213 break; 4214 4215 case KeyRelease: 4216 if( -1 == nCompose_ ) 4217 { 4218 nReleaseTime_ = pEvent->xkey.time; 4219 XEvent aEvent; 4220 if( XCheckIfEvent( pEvent->xkey.display, &aEvent, call_checkKeyReleaseForRepeat, (XPointer)this ) ) 4221 XPutBackEvent( pEvent->xkey.display, &aEvent ); 4222 else 4223 nRet = HandleKeyEvent( &pEvent->xkey ); 4224 } 4225 break; 4226 4227 case ButtonPress: 4228 // #74406# if we loose the focus in presentation mode 4229 // there are good chances that we never get it back 4230 // since the WM ignores us 4231 if( IsOverrideRedirect() ) 4232 { 4233 XSetInputFocus( GetXDisplay(), GetShellWindow(), 4234 RevertToNone, CurrentTime ); 4235 } 4236 4237 case ButtonRelease: 4238 case MotionNotify: 4239 case EnterNotify: 4240 case LeaveNotify: 4241 nRet = HandleMouseEvent( pEvent ); 4242 break; 4243 4244 case FocusIn: 4245 case FocusOut: 4246 nRet = HandleFocusEvent( &pEvent->xfocus ); 4247 break; 4248 4249 case Expose: 4250 case GraphicsExpose: 4251 nRet = HandleExposeEvent( pEvent ); 4252 break; 4253 4254 case MapNotify: 4255 if( pEvent->xmap.window == GetShellWindow() ) 4256 { 4257 if( nShowState_ == SHOWSTATE_HIDDEN ) 4258 { 4259 /* 4260 * #95097# workaround for (at least) KWin 2.2.2 4261 * which will map windows that were once transient 4262 * even if they are withdrawn when the respective 4263 * document is mapped. 4264 */ 4265 if( ! (nStyle_ & SAL_FRAME_STYLE_PLUG) ) 4266 XUnmapWindow( GetXDisplay(), GetShellWindow() ); 4267 break; 4268 } 4269 bMapped_ = sal_True; 4270 bViewable_ = sal_True; 4271 nRet = sal_True; 4272 if ( mpInputContext != NULL ) 4273 mpInputContext->Map( this ); 4274 CallCallback( SALEVENT_RESIZE, NULL ); 4275 if( pDisplay_->GetServerVendor() == vendor_hummingbird ) 4276 { 4277 /* 4278 * With Exceed sometimes there does not seem to be 4279 * an Expose after the MapNotify. 4280 * so start a delayed paint here 4281 */ 4282 maPaintRegion.Union( Rectangle( Point( 0, 0 ), Size( maGeometry.nWidth, maGeometry.nHeight ) ) ); 4283 XEvent aEvent; 4284 aEvent.xexpose.type = Expose; 4285 aEvent.xexpose.display = pDisplay_->GetDisplay(); 4286 aEvent.xexpose.x = 0; 4287 aEvent.xexpose.y = 0; 4288 aEvent.xexpose.width = maGeometry.nWidth; 4289 aEvent.xexpose.height = maGeometry.nHeight; 4290 aEvent.xexpose.count = 0; 4291 XSendEvent( pDisplay_->GetDisplay(), 4292 GetWindow(), 4293 True, 4294 ExposureMask, 4295 &aEvent ); 4296 } 4297 4298 bool bSetFocus = m_bSetFocusOnMap; 4299 /* #99570# another workaround for sawfish: if a transient window for the same parent is shown 4300 * sawfish does not set the focus to it. Applies only for click to focus mode. 4301 */ 4302 if( ! (nStyle_ & SAL_FRAME_STYLE_FLOAT ) && mbInShow && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Sawfish" ) ) 4303 { 4304 // #101775# don't set the focus into the IME status window 4305 // since this will lead to a parent loose-focus, close status, 4306 // reget focus, open status, .... flicker loop 4307 if ( (I18NStatus::get().getStatusFrame() != this) ) 4308 bSetFocus = true; 4309 } 4310 4311 /* 4312 * sometimes a message box/dialogue is brought up when a frame is not mapped 4313 * the corresponding TRANSIENT_FOR hint is then set to the root window 4314 * so that the dialogue shows in all cases. Correct it here if the 4315 * frame is shown afterwards. 4316 */ 4317 if( ! IsChildWindow() 4318 && ! IsOverrideRedirect() 4319 && ! IsFloatGrabWindow() 4320 ) 4321 { 4322 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); 4323 it != maChildren.end(); ++it ) 4324 { 4325 if( (*it)->mbTransientForRoot ) 4326 pDisplay_->getWMAdaptor()->changeReferenceFrame( *it, this ); 4327 } 4328 } 4329 4330 if( hPresentationWindow != None && GetShellWindow() == hPresentationWindow ) 4331 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime ); 4332 /* For unknown reasons Dtwm does respect the input_hint 4333 * set to False, but not when mapping the window. So 4334 * emulate the correct behaviour and set the focus back 4335 * to where it most probably should have been. 4336 */ 4337 if( (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) && 4338 mpParent && 4339 GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Dtwm" ) 4340 ) 4341 { 4342 XSetInputFocus( GetXDisplay(), 4343 mpParent->GetShellWindow(), 4344 RevertToParent, 4345 CurrentTime ); 4346 bSetFocus = false; 4347 } 4348 4349 if( bSetFocus ) 4350 { 4351 XSetInputFocus( GetXDisplay(), 4352 GetShellWindow(), 4353 RevertToParent, 4354 CurrentTime ); 4355 } 4356 4357 4358 RestackChildren(); 4359 mbInShow = sal_False; 4360 m_bSetFocusOnMap = false; 4361 } 4362 break; 4363 4364 case UnmapNotify: 4365 if( pEvent->xunmap.window == GetShellWindow() ) 4366 { 4367 bMapped_ = sal_False; 4368 bViewable_ = sal_False; 4369 nRet = sal_True; 4370 if ( mpInputContext != NULL ) 4371 mpInputContext->Unmap( this ); 4372 CallCallback( SALEVENT_RESIZE, NULL ); 4373 } 4374 break; 4375 4376 case ConfigureNotify: 4377 if( pEvent->xconfigure.window == GetShellWindow() 4378 || pEvent->xconfigure.window == GetWindow() ) 4379 nRet = HandleSizeEvent( &pEvent->xconfigure ); 4380 break; 4381 4382 case VisibilityNotify: 4383 nVisibility_ = pEvent->xvisibility.state; 4384 nRet = sal_True; 4385 if( bAlwaysOnTop_ 4386 && bMapped_ 4387 && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK() 4388 && nVisibility_ != VisibilityUnobscured ) 4389 maAlwaysOnTopRaiseTimer.Start(); 4390 break; 4391 4392 case ReparentNotify: 4393 nRet = HandleReparentEvent( &pEvent->xreparent ); 4394 break; 4395 4396 case MappingNotify: 4397 if( MappingPointer != pEvent->xmapping.request ) 4398 nRet = CallCallback( SALEVENT_KEYBOARDCHANGED, 0 ); 4399 break; 4400 4401 case ColormapNotify: 4402 nRet = HandleColormapEvent( &pEvent->xcolormap ); 4403 break; 4404 4405 case PropertyNotify: 4406 { 4407 if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) ) 4408 nRet = HandleStateEvent( &pEvent->xproperty ); 4409 else 4410 nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty ); 4411 break; 4412 } 4413 4414 case ClientMessage: 4415 nRet = HandleClientMessage( &pEvent->xclient ); 4416 break; 4417 } 4418 } 4419 else 4420 { 4421 switch( pEvent->type ) 4422 { 4423 case FocusIn: 4424 case FocusOut: 4425 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) 4426 && ( pEvent->xfocus.window == GetShellWindow() 4427 || pEvent->xfocus.window == GetForeignParent() ) 4428 ) 4429 { 4430 nRet = HandleFocusEvent( &pEvent->xfocus ); 4431 } 4432 break; 4433 4434 case ConfigureNotify: 4435 if( pEvent->xconfigure.window == GetForeignParent() || 4436 pEvent->xconfigure.window == GetShellWindow() ) 4437 nRet = HandleSizeEvent( &pEvent->xconfigure ); 4438 4439 if( pEvent->xconfigure.window == GetStackingWindow() ) 4440 nRet = HandleSizeEvent( &pEvent->xconfigure ); 4441 4442 RestackChildren(); 4443 break; 4444 } 4445 } 4446 4447 return nRet; 4448 } 4449 4450 void X11SalFrame::ResetClipRegion() 4451 { 4452 delete [] m_pClipRectangles; 4453 m_pClipRectangles = NULL; 4454 m_nCurClipRect = m_nMaxClipRect = 0; 4455 4456 const int dest_kind = ShapeBounding; 4457 const int op = ShapeSet; 4458 const int ordering = YSorted; 4459 4460 XWindowAttributes win_attrib; 4461 XRectangle win_size; 4462 4463 XLIB_Window aShapeWindow = mhShellWindow; 4464 4465 XGetWindowAttributes ( GetDisplay()->GetDisplay(), 4466 aShapeWindow, 4467 &win_attrib ); 4468 4469 win_size.x = 0; 4470 win_size.y = 0; 4471 win_size.width = win_attrib.width; 4472 win_size.height = win_attrib.height; 4473 4474 XShapeCombineRectangles ( GetDisplay()->GetDisplay(), 4475 aShapeWindow, 4476 dest_kind, 4477 0, 0, // x_off, y_off 4478 &win_size, // list of rectangles 4479 1, // number of rectangles 4480 op, ordering ); 4481 } 4482 4483 void X11SalFrame::BeginSetClipRegion( sal_uLong nRects ) 4484 { 4485 if( m_pClipRectangles ) 4486 delete [] m_pClipRectangles; 4487 if( nRects ) 4488 m_pClipRectangles = new XRectangle[nRects]; 4489 else 4490 m_pClipRectangles = NULL; 4491 m_nMaxClipRect = static_cast<int>(nRects); 4492 m_nCurClipRect = 0; 4493 } 4494 4495 void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 4496 { 4497 if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect ) 4498 { 4499 m_pClipRectangles[m_nCurClipRect].x = nX; 4500 m_pClipRectangles[m_nCurClipRect].y = nY; 4501 m_pClipRectangles[m_nCurClipRect].width = nWidth; 4502 m_pClipRectangles[m_nCurClipRect].height = nHeight; 4503 m_nCurClipRect++; 4504 } 4505 } 4506 4507 void X11SalFrame::EndSetClipRegion() 4508 { 4509 const int dest_kind = ShapeBounding; 4510 const int ordering = YSorted; 4511 const int op = ShapeSet; 4512 4513 XLIB_Window aShapeWindow = mhShellWindow; 4514 XShapeCombineRectangles ( GetDisplay()->GetDisplay(), 4515 aShapeWindow, 4516 dest_kind, 4517 0, 0, // x_off, y_off 4518 m_pClipRectangles, 4519 m_nCurClipRect, 4520 op, ordering ); 4521 4522 } 4523 4524