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