merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / window / salframe.cxx
blob5d0d6f90485318db912513c5ec38ade846873bc0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salframe.cxx,v $
10 * $Revision: 1.225 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
39 #include <tools/prex.h>
40 #include <X11/Xatom.h>
41 #include <X11/keysym.h>
42 #include "FWS.hxx"
43 #include <X11/extensions/shape.h>
44 #ifndef SOLARIS
45 #include <X11/extensions/dpms.h>
46 #endif
47 #include <tools/postx.h>
49 #include "salunx.h"
50 #include "saldata.hxx"
51 #include "saldisp.hxx"
52 #include "salgdi.h"
53 #include "salframe.h"
54 #include "soicon.hxx"
55 #include "dtint.hxx"
56 #include "sm.hxx"
57 #include "wmadaptor.hxx"
58 #include "salprn.h"
59 #include "salbmp.h"
60 #include "i18n_ic.hxx"
61 #include "i18n_keysym.hxx"
62 #include "i18n_status.hxx"
64 #include "vcl/salinst.hxx"
65 #include "vcl/floatwin.hxx"
66 #include "vcl/sallayout.hxx"
67 #include "vcl/svapp.hxx"
68 #include "vcl/keycodes.hxx"
69 #include "vcl/printerinfomanager.hxx"
70 #include "vcl/settings.hxx"
72 #include "tools/debug.hxx"
74 #include "sal/alloca.h"
75 #include <com/sun/star/uno/Exception.hpp>
77 #include <algorithm>
79 #ifndef Button6
80 # define Button6 6
81 #endif
82 #ifndef Button7
83 # define Button7 7
84 #endif
86 using namespace vcl_sal;
87 using namespace vcl;
89 // -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
90 #define CLIENT_EVENTS StructureNotifyMask \
91 | SubstructureNotifyMask \
92 | KeyPressMask \
93 | KeyReleaseMask \
94 | ButtonPressMask \
95 | ButtonReleaseMask \
96 | PointerMotionMask \
97 | EnterWindowMask \
98 | LeaveWindowMask \
99 | FocusChangeMask \
100 | ExposureMask \
101 | VisibilityChangeMask \
102 | PropertyChangeMask \
103 | ColormapChangeMask
105 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
107 static XLIB_Window hPresentationWindow = None, hPresFocusWindow = None;
108 static ::std::list< XLIB_Window > aPresentationReparentList;
109 static int nVisibleFloats = 0;
111 X11SalFrame* X11SalFrame::s_pSaveYourselfFrame = NULL;
113 // -=-= C++ statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
114 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
115 static void doReparentPresentationDialogues( SalDisplay* pDisplay )
117 pDisplay->GetXLib()->PushXErrorLevel( true );
118 while( aPresentationReparentList.begin() != aPresentationReparentList.end() )
120 int x, y;
121 XLIB_Window aRoot, aChild;
122 unsigned int w, h, bw, d;
123 XGetGeometry( pDisplay->GetDisplay(),
124 aPresentationReparentList.front(),
125 &aRoot,
126 &x, &y, &w, &h, &bw, &d );
127 XTranslateCoordinates( pDisplay->GetDisplay(),
128 hPresentationWindow,
129 aRoot,
130 x, y,
131 &x, &y,
132 &aChild );
133 XReparentWindow( pDisplay->GetDisplay(),
134 aPresentationReparentList.front(),
135 aRoot,
136 x, y );
137 aPresentationReparentList.pop_front();
139 if( hPresFocusWindow )
140 XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot, CurrentTime );
141 XSync( pDisplay->GetDisplay(), False );
142 pDisplay->GetXLib()->PopXErrorLevel();
145 // -=-= SalFrame / X11SalFrame =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
146 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
148 bool X11SalFrame::IsOverrideRedirect() const
150 return
151 ((nStyle_ & SAL_FRAME_STYLE_INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash())
153 (!( nStyle_ & ~SAL_FRAME_STYLE_DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen())
157 bool X11SalFrame::IsFloatGrabWindow() const
159 static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" );
161 return
162 ( ( !pDisableGrab || !*pDisableGrab ) &&
164 (nStyle_ & SAL_FRAME_STYLE_FLOAT) &&
165 ! (nStyle_ & SAL_FRAME_STYLE_TOOLTIP) &&
166 ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
171 void X11SalFrame::setXEmbedInfo()
173 if( m_bXEmbed )
175 long aInfo[2];
176 aInfo[0] = 1; // XEMBED protocol version
177 aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED
178 XChangeProperty( pDisplay_->GetDisplay(),
179 mhWindow,
180 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
181 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
183 PropModeReplace,
184 reinterpret_cast<unsigned char*>(aInfo),
185 sizeof(aInfo)/sizeof(aInfo[0]) );
189 void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
191 XEvent aEvent;
193 rtl_zeroMemory( &aEvent, sizeof(aEvent) );
194 aEvent.xclient.window = mhForeignParent;
195 aEvent.xclient.type = ClientMessage;
196 aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED );
197 aEvent.xclient.format = 32;
198 aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
199 aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
200 aEvent.xclient.data.l[2] = 0;
201 aEvent.xclient.data.l[3] = 0;
202 aEvent.xclient.data.l[4] = 0;
204 GetDisplay()->GetXLib()->PushXErrorLevel( true );
205 XSendEvent( pDisplay_->GetDisplay(),
206 mhForeignParent,
207 False, NoEventMask, &aEvent );
208 XSync( pDisplay_->GetDisplay(), False );
209 GetDisplay()->GetXLib()->PopXErrorLevel();
213 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
215 void X11SalFrame::Init( ULONG nSalFrameStyle, int nScreen, SystemParentData* pParentData, bool bUseGeometry )
217 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
218 nScreen = GetDisplay()->GetDefaultScreenNumber();
219 if( mpParent )
220 nScreen = mpParent->m_nScreen;
222 m_nScreen = nScreen;
223 nStyle_ = nSalFrameStyle;
224 XWMHints Hints;
225 Hints.flags = InputHint;
226 Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True;
228 int x = 0, y = 0;
229 unsigned int w = 500, h = 500;
230 XSetWindowAttributes Attributes;
232 int nAttrMask = CWBorderPixel
233 | CWBackPixmap
234 | CWColormap
235 | CWOverrideRedirect
236 | CWEventMask
238 Attributes.border_pixel = 0;
239 Attributes.background_pixmap = None;
240 Attributes.colormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap();
241 Attributes.override_redirect = False;
242 Attributes.event_mask = CLIENT_EVENTS;
244 const SalVisual& rVis = GetDisplay()->GetVisual( m_nScreen );
245 XLIB_Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nScreen );
246 XLIB_Window aClientLeader = None;
248 if( bUseGeometry )
250 x = maGeometry.nX;
251 y = maGeometry.nY;
252 w = maGeometry.nWidth;
253 h = maGeometry.nHeight;
256 if( (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT) &&
257 ! (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
260 if( nShowState_ == SHOWSTATE_UNKNOWN )
262 w = 10;
263 h = 10;
265 Attributes.override_redirect = True;
267 else if( (nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) )
269 DBG_ASSERT( mpParent, "SAL_FRAME_STYLE_SYSTEMCHILD window without parent" );
270 if( mpParent )
272 aFrameParent = mpParent->mhWindow;
273 // FIXME: since with SAL_FRAME_STYLE_SYSTEMCHILD
274 // multiple X11SalFrame objects can have the same shell window
275 // dispatching events in saldisp.cxx is unclear (the first frame)
276 // wins. HTH this correctly is unclear yet
277 // for the time being, treat set the shell window to own window
278 // like for a normal frame
279 // mhShellWindow = mpParent->GetShellWindow();
282 else if( pParentData )
284 // plugin parent may be killed unexpectedly by
285 // plugging process; ignore XErrors in that case
286 GetDisplay()->setHaveSystemChildFrame();
288 nStyle_ |= SAL_FRAME_STYLE_PLUG;
289 Attributes.override_redirect = True;
290 if( pParentData->nSize >= sizeof(SystemParentData) )
291 m_bXEmbed = pParentData->bXEmbedSupport;
293 int x_ret, y_ret;
294 unsigned int bw, d;
295 XLIB_Window aRoot, aParent;
297 XGetGeometry( GetXDisplay(), pParentData->aWindow,
298 &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
299 mhForeignParent = pParentData->aWindow;
301 mhShellWindow = aParent = mhForeignParent;
302 XLIB_Window* pChildren;
303 unsigned int nChildren;
304 bool bBreak = false;
307 XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow,
308 &aRoot, &aParent, &pChildren, &nChildren );
309 XFree( pChildren );
310 if( aParent != aRoot )
311 mhShellWindow = aParent;
312 int nCount = 0;
313 Atom* pProps = XListProperties( GetDisplay()->GetDisplay(),
314 mhShellWindow,
315 &nCount );
316 for( int i = 0; i < nCount && ! bBreak; ++i )
317 bBreak = (pProps[i] == XA_WM_HINTS);
318 if( pProps )
319 XFree( pProps );
320 } while( aParent != aRoot && ! bBreak );
322 // check if this is really one of our own frames
323 // do not change the input mask in that case
324 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
325 std::list< SalFrame* >::const_iterator it = rFrames.begin();
326 while( it != rFrames.end() && mhForeignParent != static_cast<const X11SalFrame*>(*it)->GetWindow() )
327 ++it;
329 if( it == rFrames.end() )
331 XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask | FocusChangeMask );
332 XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask | FocusChangeMask );
335 else
337 if( ! bUseGeometry )
339 Size aScreenSize( GetDisplay()->getDataForScreen( m_nScreen ).m_aSize );
340 w = aScreenSize.Width();
341 h = aScreenSize.Height();
342 if( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE &&
343 nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
345 // fill in holy default values brought to us by product management
346 if( aScreenSize.Width() >= 800 )
347 w = 785;
348 if( aScreenSize.Width() >= 1024 )
349 w = 920;
351 if( aScreenSize.Height() >= 600 )
352 h = 550;
353 if( aScreenSize.Height() >= 768 )
354 h = 630;
355 if( aScreenSize.Height() >= 1024 )
356 h = 875;
358 if( ! mpParent )
360 // find the last document window (if any)
361 const X11SalFrame* pFrame = NULL;
362 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
363 std::list< SalFrame* >::const_iterator it = rFrames.begin();
364 while( it != rFrames.end() )
366 pFrame = static_cast< const X11SalFrame* >(*it);
367 if( ! ( pFrame->mpParent
368 || pFrame->mbFullScreen
369 || ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
370 || ! pFrame->GetUnmirroredGeometry().nWidth
371 || ! pFrame->GetUnmirroredGeometry().nHeight
374 break;
375 ++it;
378 if( it != rFrames.end() )
380 // set a document position and size
381 // the first frame gets positioned by the window manager
382 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
383 x = rGeom.nX;
384 y = rGeom.nY;
385 if( x+(int)w+40 <= (int)aScreenSize.Width() &&
386 y+(int)h+40 <= (int)aScreenSize.Height()
389 y += 40;
390 x += 40;
392 else
394 x = 10; // leave some space for decoration
395 y = 20;
398 else if( GetDisplay()->IsXinerama() )
400 // place frame on same screen as mouse pointer
401 XLIB_Window aRoot, aChild;
402 int root_x = 0, root_y = 0, lx, ly;
403 unsigned int mask;
404 XQueryPointer( GetXDisplay(),
405 GetDisplay()->GetRootWindow( m_nScreen ),
406 &aRoot, &aChild,
407 &root_x, &root_y, &lx, &ly, &mask );
408 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
409 for( unsigned int i = 0; i < rScreens.size(); i++ )
410 if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
412 x = rScreens[i].Left();
413 y = rScreens[i].Top();
414 break;
419 Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity();
420 nAttrMask |= CWWinGravity;
421 if( mpParent )
423 Attributes.save_under = True;
424 nAttrMask |= CWSaveUnder;
426 if( IsOverrideRedirect() )
427 Attributes.override_redirect = True;
428 // default icon
429 if( (nStyle_ & SAL_FRAME_STYLE_INTRO) == 0 )
431 bool bOk=false;
434 bOk=SelectAppIconPixmap( pDisplay_, m_nScreen,
435 mnIconID != 1 ? mnIconID :
436 (mpParent ? mpParent->mnIconID : 1), 32,
437 Hints.icon_pixmap, Hints.icon_mask );
439 catch( com::sun::star::uno::Exception& )
441 // can happen - no ucb during early startup
443 if( bOk )
445 Hints.flags |= IconPixmapHint;
446 if( Hints.icon_mask )
447 Hints.flags |= IconMaskHint;
451 // find the top level frame of the transience hierarchy
452 X11SalFrame* pFrame = this;
453 while( pFrame->mpParent )
454 pFrame = pFrame->mpParent;
455 if( (pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) )
457 // if the top level window is a plugin window,
458 // then we should place us in the same window group as
459 // the parent application (or none if there is no window group
460 // hint in the parent).
461 if( pFrame->GetShellWindow() )
463 XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(),
464 pFrame->GetShellWindow() );
465 if( pWMHints )
467 if( (pWMHints->flags & WindowGroupHint) )
469 Hints.flags |= WindowGroupHint;
470 Hints.window_group = pWMHints->window_group;
472 XFree( pWMHints );
476 else
478 Hints.flags |= WindowGroupHint;
479 Hints.window_group = pFrame->GetShellWindow();
480 // note: for a normal document window this will produce None
481 // as the window is not yet created and the shell window is
482 // initialized to None. This must be corrected after window creation.
483 aClientLeader = GetDisplay()->GetDrawable( m_nScreen );
487 nShowState_ = SHOWSTATE_UNKNOWN;
488 bViewable_ = TRUE;
489 bMapped_ = FALSE;
490 nVisibility_ = VisibilityFullyObscured;
491 mhWindow = XCreateWindow( GetXDisplay(),
492 aFrameParent,
493 x, y,
494 w, h,
496 rVis.GetDepth(),
497 InputOutput,
498 rVis.GetVisual(),
499 nAttrMask,
500 &Attributes );
501 // FIXME: see above: fake shell window for now to own window
502 if( /*! IsSysChildWindow() &&*/ pParentData == NULL )
504 mhShellWindow = mhWindow;
507 // correct window group if necessary
508 if( (Hints.flags & WindowGroupHint) == WindowGroupHint )
510 if( Hints.window_group == None )
511 Hints.window_group = GetShellWindow();
514 maGeometry.nX = x;
515 maGeometry.nY = y;
516 maGeometry.nWidth = w;
517 maGeometry.nHeight = h;
518 updateScreenNumber();
520 XSync( GetXDisplay(), False );
521 setXEmbedInfo();
523 XLIB_Time nUserTime = (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_TOOLWINDOW) ) == 0 ?
524 pDisplay_->GetLastUserEventTime() : 0;
525 pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime );
527 if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect )
529 XSetWMHints( GetXDisplay(), mhWindow, &Hints );
530 // WM Protocols && internals
531 Atom a[4];
532 int n = 0;
533 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
534 if( ! s_pSaveYourselfFrame && ! mpParent)
536 // at all times have only one frame with SaveYourself
537 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF );
538 s_pSaveYourselfFrame = this;
540 if( (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
541 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS );
542 XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n );
544 XClassHint* pClass = XAllocClassHint();
545 pClass->res_name = const_cast<char*>(X11SalData::getFrameResName());
546 pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName());
547 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
548 XFree( pClass );
550 XSizeHints* pHints = XAllocSizeHints();
551 pHints->flags = PWinGravity | PPosition;
552 pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity();
553 pHints->x = 0;
554 pHints->y = 0;
555 XSetWMNormalHints( GetXDisplay(),
556 GetShellWindow(),
557 pHints );
558 XFree (pHints);
560 // set client leader
561 if( aClientLeader )
563 XChangeProperty( GetXDisplay(),
564 mhWindow,
565 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER),
566 XA_WINDOW,
568 PropModeReplace,
569 (unsigned char*)&aClientLeader,
573 #define DECOFLAGS (SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE)
574 int nDecoFlags = WMAdaptor::decoration_All;
575 if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ||
576 (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
578 nDecoFlags = 0;
579 else if( (nStyle_ & DECOFLAGS ) != DECOFLAGS || (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
581 if( nStyle_ & DECOFLAGS )
582 // if any decoration, then show a border
583 nDecoFlags = WMAdaptor::decoration_Border;
584 else
585 nDecoFlags = 0;
587 if( ! mpParent && (nStyle_ & DECOFLAGS) )
588 // don't add a min button if window should be decorationless
589 nDecoFlags |= WMAdaptor::decoration_MinimizeBtn;
590 if( nStyle_ & SAL_FRAME_STYLE_CLOSEABLE )
591 nDecoFlags |= WMAdaptor::decoration_CloseBtn;
592 if( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
594 nDecoFlags |= WMAdaptor::decoration_Resize;
595 if( ! (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
596 nDecoFlags |= WMAdaptor::decoration_MaximizeBtn;
598 if( nStyle_ & SAL_FRAME_STYLE_MOVEABLE )
599 nDecoFlags |= WMAdaptor::decoration_Title;
602 WMAdaptor::WMWindowType eType = WMAdaptor::windowType_Normal;
603 if( nStyle_ & SAL_FRAME_STYLE_INTRO )
604 eType = WMAdaptor::windowType_Splash;
605 if( (nStyle_ & SAL_FRAME_STYLE_DIALOG) && hPresentationWindow == None )
606 eType = WMAdaptor::windowType_ModelessDialogue;
607 if( nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW )
608 eType = WMAdaptor::windowType_Utility;
609 if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
610 eType = WMAdaptor::windowType_Toolbar;
611 if( nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN )
612 eType = WMAdaptor::windowType_Dock;
614 GetDisplay()->getWMAdaptor()->
615 setFrameTypeAndDecoration( this,
616 eType,
617 nDecoFlags,
618 hPresentationWindow ? NULL : mpParent );
620 if( (nStyle_ & (SAL_FRAME_STYLE_DEFAULT |
621 SAL_FRAME_STYLE_OWNERDRAWDECORATION|
622 SAL_FRAME_STYLE_FLOAT |
623 SAL_FRAME_STYLE_INTRO |
624 SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) )
625 == SAL_FRAME_STYLE_DEFAULT )
626 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
629 m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea();
631 // Pointer
632 SetPointer( POINTER_ARROW );
635 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
636 X11SalFrame::X11SalFrame( SalFrame *pParent, ULONG nSalFrameStyle, SystemParentData* pSystemParent )
638 X11SalData* pSalData = GetX11SalData();
640 // initialize frame geometry
641 memset( &maGeometry, 0, sizeof(maGeometry) );
643 mpParent = static_cast< X11SalFrame* >( pParent );
645 mbTransientForRoot = false;
647 pDisplay_ = pSalData->GetDisplay();
648 // insert frame in framelist
649 pDisplay_->registerFrame( this );
651 mhWindow = None;
652 mhShellWindow = None;
653 mhStackingWindow = None;
654 mhForeignParent = None;
655 mhBackgroundPixmap = None;
657 pGraphics_ = NULL;
658 pFreeGraphics_ = NULL;
660 hCursor_ = None;
661 nCaptured_ = 0;
663 nReleaseTime_ = 0;
664 nKeyCode_ = 0;
665 nKeyState_ = 0;
666 nCompose_ = -1;
667 mbKeyMenu = false;
668 mbSendExtKeyModChange = false;
669 mnExtKeyMod = 0;
671 nShowState_ = SHOWSTATE_UNKNOWN;
672 nWidth_ = 0;
673 nHeight_ = 0;
674 nStyle_ = 0;
675 mnExtStyle = 0;
676 bAlwaysOnTop_ = FALSE;
678 // set bViewable_ to TRUE: hack GetClientSize to report something
679 // different to 0/0 before first map
680 bViewable_ = TRUE;
681 bMapped_ = FALSE;
682 bDefaultPosition_ = TRUE;
683 nVisibility_ = VisibilityFullyObscured;
684 m_nWorkArea = 0;
685 mbInShow = FALSE;
686 m_bXEmbed = false;
688 nScreenSaversTimeout_ = 0;
690 mpInputContext = NULL;
691 mbInputFocus = False;
693 maAlwaysOnTopRaiseTimer.SetTimeoutHdl( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise ) );
694 maAlwaysOnTopRaiseTimer.SetTimeout( 100 );
696 meWindowType = WMAdaptor::windowType_Normal;
697 mnDecorationFlags = WMAdaptor::decoration_All;
698 mbMaximizedVert = false;
699 mbMaximizedHorz = false;
700 mbShaded = false;
701 mbFullScreen = false;
703 mnIconID = 1; // ICON_DEFAULT
705 m_pClipRectangles = NULL;
706 m_nCurClipRect = 0;
707 m_nMaxClipRect = 0;
709 if( mpParent )
710 mpParent->maChildren.push_back( this );
712 Init( nSalFrameStyle, GetDisplay()->GetDefaultScreenNumber(), pSystemParent );
715 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
717 void X11SalFrame::passOnSaveYourSelf()
719 if( this == s_pSaveYourselfFrame )
721 // pass on SaveYourself
722 const X11SalFrame* pFrame = NULL;
723 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
724 std::list< SalFrame* >::const_iterator it = rFrames.begin();
725 while( it != rFrames.end() )
727 pFrame = static_cast< const X11SalFrame* >(*it);
728 if( ! ( IsChildWindow() || pFrame->mpParent )
729 && pFrame != s_pSaveYourselfFrame )
730 break;
731 ++it;
734 s_pSaveYourselfFrame = (it != rFrames.end() ) ? const_cast<X11SalFrame*>(pFrame) : NULL;
735 if( s_pSaveYourselfFrame )
737 Atom a[4];
738 int n = 0;
739 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
740 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF );
741 XSetWMProtocols( GetXDisplay(), s_pSaveYourselfFrame->GetShellWindow(), a, n );
746 X11SalFrame::~X11SalFrame()
748 notifyDelete();
750 if( m_pClipRectangles )
752 delete [] m_pClipRectangles;
753 m_pClipRectangles = NULL;
754 m_nCurClipRect = m_nMaxClipRect = 0;
757 if( mhBackgroundPixmap )
759 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None );
760 XFreePixmap( GetXDisplay(), mhBackgroundPixmap );
763 if( mhStackingWindow )
764 aPresentationReparentList.remove( mhStackingWindow );
766 // remove from parent's list
767 if( mpParent )
768 mpParent->maChildren.remove( this );
770 // deregister on SalDisplay
771 pDisplay_->deregisterFrame( this );
773 // unselect all events, some may be still in the queue anyway
774 if( ! IsSysChildWindow() )
775 XSelectInput( GetXDisplay(), GetShellWindow(), 0 );
776 XSelectInput( GetXDisplay(), GetWindow(), 0 );
778 ShowFullScreen( FALSE, 0 );
780 if( bMapped_ )
781 Show( FALSE );
783 if( mpInputContext )
785 mpInputContext->UnsetICFocus( this );
786 mpInputContext->Unmap( this );
787 delete mpInputContext;
790 if( GetWindow() == hPresentationWindow )
792 hPresentationWindow = None;
793 doReparentPresentationDialogues( GetDisplay() );
796 if( pGraphics_ )
798 pGraphics_->DeInit();
799 delete pGraphics_;
802 if( pFreeGraphics_ )
804 pFreeGraphics_->DeInit();
805 delete pFreeGraphics_;
809 XDestroyWindow( GetXDisplay(), mhWindow );
812 * check if there is only the status frame left
813 * if so, free it
815 if( ! GetDisplay()->getFrames().empty() && I18NStatus::exists() )
817 SalFrame* pStatusFrame = I18NStatus::get().getStatusFrame();
818 std::list< SalFrame* >::const_iterator sit = GetDisplay()->getFrames().begin();
819 if( pStatusFrame
820 && *sit == pStatusFrame
821 && ++sit == GetDisplay()->getFrames().end() )
822 vcl::I18NStatus::free();
825 passOnSaveYourSelf();
828 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
830 void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
832 if( nStyle != mnExtStyle && ! IsChildWindow() )
834 mnExtStyle = nStyle;
836 XClassHint* pClass = XAllocClassHint();
837 rtl::OString aResHint = X11SalData::getFrameResName( mnExtStyle );
838 pClass->res_name = const_cast<char*>(aResHint.getStr());
839 pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName());
840 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
841 XFree( pClass );
845 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
847 void X11SalFrame::SetBackgroundBitmap( SalBitmap* pBitmap )
849 if( mhBackgroundPixmap )
851 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None );
852 XFreePixmap( GetXDisplay(), mhBackgroundPixmap );
853 mhBackgroundPixmap = None;
855 if( pBitmap )
857 X11SalBitmap* pBM = static_cast<X11SalBitmap*>(pBitmap);
858 Size aSize = pBM->GetSize();
859 if( aSize.Width() && aSize.Height() )
861 mhBackgroundPixmap =
862 XCreatePixmap( GetXDisplay(),
863 GetWindow(),
864 aSize.Width(),
865 aSize.Height(),
866 GetDisplay()->GetVisual( m_nScreen ).GetDepth() );
867 if( mhBackgroundPixmap )
869 SalTwoRect aTwoRect;
870 aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
871 aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
872 aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
873 pBM->ImplDraw( mhBackgroundPixmap,
874 m_nScreen,
875 GetDisplay()->GetVisual( m_nScreen ).GetDepth(),
876 aTwoRect, GetDisplay()->GetCopyGC( m_nScreen ) );
877 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), mhBackgroundPixmap );
883 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
885 const SystemChildData* X11SalFrame::GetSystemData() const
887 X11SalFrame *pFrame = const_cast<X11SalFrame*>(this);
888 pFrame->maSystemChildData.nSize = sizeof( SystemChildData );
889 pFrame->maSystemChildData.pDisplay = GetXDisplay();
890 pFrame->maSystemChildData.aWindow = pFrame->GetWindow();
891 pFrame->maSystemChildData.pSalFrame = pFrame;
892 pFrame->maSystemChildData.pWidget = NULL;
893 pFrame->maSystemChildData.pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual();
894 pFrame->maSystemChildData.nScreen = m_nScreen;
895 pFrame->maSystemChildData.nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth();
896 pFrame->maSystemChildData.aColormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap();
897 pFrame->maSystemChildData.pAppContext = NULL;
898 pFrame->maSystemChildData.aShellWindow = pFrame->GetShellWindow();
899 pFrame->maSystemChildData.pShellWidget = NULL;
900 return &maSystemChildData;
903 SalGraphics *X11SalFrame::GetGraphics()
905 if( pGraphics_ )
906 return NULL;
908 if( pFreeGraphics_ )
910 pGraphics_ = pFreeGraphics_;
911 pFreeGraphics_ = NULL;
913 else
915 pGraphics_ = new X11SalGraphics();
916 pGraphics_->Init( this, GetWindow(), m_nScreen );
919 return pGraphics_;
922 void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics )
924 DBG_ASSERT( pGraphics == pGraphics_, "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" );
926 if( pGraphics != pGraphics_ )
927 return;
929 pFreeGraphics_ = pGraphics_;
930 pGraphics_ = NULL;
933 void X11SalFrame::updateGraphics()
935 if( pGraphics_ )
936 pGraphics_->SetDrawable( GetWindow(), m_nScreen );
937 if( pFreeGraphics_ )
938 pFreeGraphics_->SetDrawable( GetWindow(), m_nScreen );
941 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
943 void X11SalFrame::Enable( BOOL /*bEnable*/ )
945 // NYI: enable/disable frame
948 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
950 void X11SalFrame::SetIcon( USHORT nIcon )
952 if ( ! IsChildWindow() )
954 // 0 == default icon -> #1
955 if ( nIcon == 0 )
956 nIcon = 1;
958 mnIconID = nIcon;
960 XIconSize *pIconSize = NULL;
961 int nSizes = 0;
962 int iconSize = 32;
963 if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ), &pIconSize, &nSizes ) )
965 #if OSL_DEBUG_LEVEL > 1
966 fprintf(stderr, "X11SalFrame::SetIcon(): found %d IconSizes:\n", nSizes);
967 #endif
969 const int ourLargestIconSize = 48;
970 bool bFoundIconSize = false;
972 int i;
973 for( i=0; i<nSizes; i++)
975 // select largest supported icon
977 // Note: olwm/olvwm reports a huge max icon size of
978 // 160x160 pixels; always choosing the max as the
979 // preferred icon size is apparently wrong under olvwm
980 // - so we keep the safe default |iconSize| when we see
981 // unreasonable large max icon sizes (> twice of our
982 // largest available icon) reported by XGetIconSizes.
983 if( pIconSize[i].max_width > iconSize
984 && pIconSize[i].max_width <= 2*ourLargestIconSize )
986 iconSize = pIconSize[i].max_width;
987 bFoundIconSize = true;
989 iconSize = pIconSize[i].max_width;
991 #if OSL_DEBUG_LEVEL > 1
992 fprintf(stderr, "min: %d, %d\nmax: %d, %d\ninc: %d, %d\n\n",
993 pIconSize[i].min_width, pIconSize[i].min_height,
994 pIconSize[i].max_width, pIconSize[i].max_height,
995 pIconSize[i].width_inc, pIconSize[i].height_inc);
996 #endif
999 if ( !bFoundIconSize )
1001 // Unless someone has fixed olwm/olvwm, we have rejected
1002 // the max icon size from |XGetIconSizes()|. Provide a
1003 // better icon size default value, in case our window manager
1004 // is olwm/olvwm.
1005 const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );
1007 if ( rWM.EqualsAscii( "Olwm" ) )
1008 iconSize = 48;
1011 XFree( pIconSize );
1013 else
1015 const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );
1016 if( rWM.EqualsAscii( "KWin" ) ) // assume KDE is running
1017 iconSize = 48;
1018 static bool bGnomeIconSize = false;
1019 static bool bGnomeChecked = false;
1020 if( ! bGnomeChecked )
1022 bGnomeChecked=true;
1023 int nCount = 0;
1024 Atom* pProps = XListProperties( GetXDisplay(),
1025 GetDisplay()->GetRootWindow( m_nScreen ),
1026 &nCount );
1027 for( int i = 0; i < nCount && !bGnomeIconSize; i++ )
1029 char* pName = XGetAtomName( GetXDisplay(), pProps[i] );
1030 if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) )
1031 bGnomeIconSize = true;
1032 if( pName )
1033 XFree( pName );
1035 if( pProps )
1036 XFree( pProps );
1038 if( bGnomeIconSize )
1039 iconSize = 48;
1042 XWMHints Hints;
1043 Hints.flags = 0;
1044 XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() );
1045 if( pHints )
1047 memcpy(&Hints, pHints, sizeof( XWMHints ));
1048 XFree( pHints );
1050 pHints = &Hints;
1052 BOOL bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen,
1053 nIcon, iconSize,
1054 pHints->icon_pixmap, pHints->icon_mask );
1055 if ( !bOk )
1057 // load default icon (0)
1058 bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen,
1059 0, iconSize,
1060 pHints->icon_pixmap, pHints->icon_mask );
1062 if( bOk )
1064 pHints->flags |= IconPixmapHint;
1065 if( pHints->icon_mask )
1066 pHints->flags |= IconMaskHint;
1068 XSetWMHints( GetXDisplay(), GetShellWindow(), pHints );
1073 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1075 void X11SalFrame::SetMaxClientSize( long nWidth, long nHeight )
1077 if( ! IsChildWindow() )
1079 if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
1081 XSizeHints* pHints = XAllocSizeHints();
1082 long nSupplied = 0;
1083 XGetWMNormalHints( GetXDisplay(),
1084 GetShellWindow(),
1085 pHints,
1086 &nSupplied
1088 pHints->max_width = nWidth;
1089 pHints->max_height = nHeight;
1090 pHints->flags |= PMaxSize;
1091 XSetWMNormalHints( GetXDisplay(),
1092 GetShellWindow(),
1093 pHints );
1094 XFree( pHints );
1099 void X11SalFrame::SetMinClientSize( long nWidth, long nHeight )
1101 if( ! IsChildWindow() )
1103 if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
1105 XSizeHints* pHints = XAllocSizeHints();
1106 long nSupplied = 0;
1107 XGetWMNormalHints( GetXDisplay(),
1108 GetShellWindow(),
1109 pHints,
1110 &nSupplied
1112 pHints->min_width = nWidth;
1113 pHints->min_height = nHeight;
1114 pHints->flags |= PMinSize;
1115 XSetWMNormalHints( GetXDisplay(),
1116 GetShellWindow(),
1117 pHints );
1118 XFree( pHints );
1123 // Show + Pos (x,y,z) + Size (width,height)
1124 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1125 void X11SalFrame::Show( BOOL bVisible, BOOL bNoActivate )
1127 if( ( bVisible && bMapped_ )
1128 || ( !bVisible && !bMapped_ ) )
1129 return;
1131 // HACK: this is a workaround for (at least) kwin
1132 // even though transient frames should be kept above their parent
1133 // this does not necessarily hold true for DOCK type windows
1134 // so artificially set ABOVE and remove it again on hide
1135 if( mpParent && (mpParent->nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) )
1136 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible );
1138 bMapped_ = bVisible;
1139 bViewable_ = bVisible;
1140 setXEmbedInfo();
1141 if( bVisible )
1143 SessionManagerClient::open(); // will simply return after the first time
1145 mbInShow = TRUE;
1146 if( ! (nStyle_ & SAL_FRAME_STYLE_INTRO) )
1148 // hide all INTRO frames
1149 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
1150 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
1152 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
1153 // look for intro bit map; if present, hide it
1154 if( pFrame->nStyle_ & SAL_FRAME_STYLE_INTRO )
1156 if( pFrame->bMapped_ )
1157 const_cast<X11SalFrame*>(pFrame)->Show( FALSE );
1162 // update NET_WM_STATE which may have been deleted due to earlier Show(FALSE)
1163 if( nShowState_ == SHOWSTATE_HIDDEN )
1164 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1167 * #95097#
1168 * Actually this is rather exotic and currently happens only in conjunction
1169 * with the basic dialogue editor,
1170 * which shows a frame and instantly hides it again. After that the
1171 * editor window is shown and the WM takes this as an opportunity
1172 * to show our hidden transient frame also. So Show( FALSE ) must
1173 * withdraw the frame AND delete the WM_TRANSIENT_FOR property.
1174 * In case the frame is shown again, the transient hint must be restored here.
1176 if( ! IsChildWindow()
1177 && ! IsOverrideRedirect()
1178 && ! IsFloatGrabWindow()
1179 && mpParent
1182 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
1185 // #i45160# switch to desktop where a dialog with parent will appear
1186 if( mpParent && mpParent->m_nWorkArea != m_nWorkArea )
1187 GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea );
1189 if( IsFloatGrabWindow() &&
1190 mpParent &&
1191 nVisibleFloats == 0 &&
1192 ! GetDisplay()->GetCaptureFrame() )
1194 /* #i39420#
1195 * outsmart KWin's "focus strictly under mouse" mode
1196 * which insists on taking the focus from the document
1197 * to the new float. Grab focus to parent frame BEFORE
1198 * showing the float (cannot grab it to the float
1199 * before show).
1201 XGrabPointer( GetXDisplay(),
1202 mpParent->GetWindow(),
1203 True,
1204 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1205 GrabModeAsync,
1206 GrabModeAsync,
1207 None,
1208 mpParent ? mpParent->GetCursor() : None,
1209 CurrentTime
1213 XLIB_Time nUserTime = 0;
1214 if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
1216 if( GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") )
1217 nUserTime = pDisplay_->GetLastUserEventTime( true );
1218 else
1219 nUserTime = pDisplay_->GetLastUserEventTime();
1221 GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime );
1223 // actually map the window
1224 if( m_bXEmbed )
1225 askForXEmbedFocus( 0 );
1226 else
1228 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1230 if( IsChildWindow() )
1231 XMapWindow( GetXDisplay(), GetShellWindow() );
1232 XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS );
1234 if( nStyle_ & SAL_FRAME_STYLE_FLOAT )
1235 XMapRaised( GetXDisplay(), GetWindow() );
1236 else
1237 XMapWindow( GetXDisplay(), GetWindow() );
1239 XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS );
1241 if( maGeometry.nWidth > 0
1242 && maGeometry.nHeight > 0
1243 && ( nWidth_ != (int)maGeometry.nWidth
1244 || nHeight_ != (int)maGeometry.nHeight ) )
1246 nWidth_ = maGeometry.nWidth;
1247 nHeight_ = maGeometry.nHeight;
1250 XSync( GetXDisplay(), False );
1252 if( IsFloatGrabWindow() )
1255 * #95453#
1256 * Sawfish and twm can be switched to enter-exit focus behaviour. In this case
1257 * we must grab the pointer else the dumb WM will put the focus to the
1258 * override-redirect float window. The application window will be deactivated
1259 * which causes that the floats are destroyed, so the user can never click on
1260 * a menu because it vanishes as soon as he enters it.
1262 nVisibleFloats++;
1263 if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() )
1265 /* #i39420# now move grab to the new float window */
1266 XGrabPointer( GetXDisplay(),
1267 GetWindow(),
1268 True,
1269 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1270 GrabModeAsync,
1271 GrabModeAsync,
1272 None,
1273 mpParent ? mpParent->GetCursor() : None,
1274 CurrentTime
1278 CallCallback( SALEVENT_RESIZE, NULL );
1281 * sometimes a message box/dialogue is brought up when a frame is not mapped
1282 * the corresponding TRANSIENT_FOR hint is then set to the root window
1283 * so that the dialogue shows in all cases. Correct it here if the
1284 * frame is shown afterwards.
1286 if( ! IsChildWindow()
1287 && ! IsOverrideRedirect()
1288 && ! IsFloatGrabWindow()
1291 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
1292 it != maChildren.end(); ++it )
1294 if( (*it)->mbTransientForRoot )
1295 GetDisplay()->getWMAdaptor()->changeReferenceFrame( *it, this );
1299 * leave SHOWSTATE_UNKNOWN as this indicates first mapping
1300 * and is only reset int HandleSizeEvent
1302 if( nShowState_ != SHOWSTATE_UNKNOWN )
1303 nShowState_ = SHOWSTATE_NORMAL;
1306 * #98107# plugged windows don't necessarily get the
1307 * focus on show because the parent may already be mapped
1308 * and have the focus. So try to set the focus
1309 * to the child on Show(TRUE)
1311 if( (nStyle_ & SAL_FRAME_STYLE_PLUG) && ! m_bXEmbed )
1312 XSetInputFocus( GetXDisplay(),
1313 GetWindow(),
1314 RevertToParent,
1315 CurrentTime );
1317 if( mpParent )
1319 // push this frame so it will be in front of its siblings
1320 // only necessary for insane transient behaviour of Dtwm/olwm
1321 mpParent->maChildren.remove( this );
1322 mpParent->maChildren.push_front(this);
1325 else
1327 #if OSL_DEBUG_LEVEL > 1
1328 if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
1329 fprintf( stderr, "hide on ownerdraw\n" );
1330 #endif
1332 if( getInputContext() )
1333 getInputContext()->Unmap( this );
1335 if( ! IsChildWindow() )
1337 /* FIXME: Is deleting the property really necessary ? It hurts
1338 * owner drawn windows at least.
1340 if( mpParent && ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
1341 XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) );
1342 XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nScreen );
1344 else if( ! m_bXEmbed )
1345 XUnmapWindow( GetXDisplay(), GetWindow() );
1347 nShowState_ = SHOWSTATE_HIDDEN;
1348 if( IsFloatGrabWindow() && nVisibleFloats )
1350 nVisibleFloats--;
1351 if( nVisibleFloats == 0 && ! GetDisplay()->GetCaptureFrame() )
1352 XUngrabPointer( GetXDisplay(),
1353 CurrentTime );
1355 // flush here; there may be a very seldom race between
1356 // the display connection used for clipboard and our connection
1357 Flush();
1361 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1362 void X11SalFrame::ToTop( USHORT nFlags )
1364 if( ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
1365 && ! ( nStyle_ & SAL_FRAME_STYLE_FLOAT )
1366 && nShowState_ != SHOWSTATE_HIDDEN
1367 && nShowState_ != SHOWSTATE_UNKNOWN
1370 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1371 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1372 XMapWindow( GetXDisplay(), GetShellWindow() );
1373 XMapWindow( GetXDisplay(), GetWindow() );
1376 XLIB_Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow();
1377 if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) )
1379 XRaiseWindow( GetXDisplay(), aToTopWindow );
1380 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() )
1381 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
1382 it != maChildren.end(); ++it )
1383 (*it)->ToTop( nFlags & ~SAL_FRAME_TOTOP_GRABFOCUS );
1386 if( ( ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) || ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY ) )
1387 && bMapped_ )
1389 if( m_bXEmbed )
1390 askForXEmbedFocus( 0 );
1391 else
1392 XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent, CurrentTime );
1395 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1396 void X11SalFrame::GetWorkArea( Rectangle& rWorkArea )
1398 rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 );
1400 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1401 void X11SalFrame::GetClientSize( long &rWidth, long &rHeight )
1403 if( ! bViewable_ )
1405 rWidth = rHeight = 0;
1406 return;
1409 rWidth = maGeometry.nWidth;
1410 rHeight = maGeometry.nHeight;
1412 if( !rWidth || !rHeight )
1414 XWindowAttributes aAttrib;
1416 XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib );
1418 maGeometry.nWidth = rWidth = aAttrib.width;
1419 maGeometry.nHeight = rHeight = aAttrib.height;
1423 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1425 void X11SalFrame::SetWindowGravity (int nGravity) const
1427 if( ! IsChildWindow() )
1429 XSizeHints* pHint = XAllocSizeHints();
1430 long nFlag;
1432 XGetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint, &nFlag);
1433 pHint->flags |= PWinGravity;
1434 pHint->win_gravity = nGravity;
1436 XSetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint);
1437 XSync (GetXDisplay(), False);
1439 XFree (pHint);
1443 void X11SalFrame::Center( )
1445 int nX, nY, nScreenWidth, nScreenHeight;
1446 int nRealScreenWidth, nRealScreenHeight;
1447 int nScreenX = 0, nScreenY = 0;
1449 const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize;
1450 nScreenWidth = aScreenSize.Width();
1451 nScreenHeight = aScreenSize.Height();
1452 nRealScreenWidth = nScreenWidth;
1453 nRealScreenHeight = nScreenHeight;
1455 if( GetDisplay()->IsXinerama() )
1457 // get xinerama screen we are on
1458 // if there is a parent, use its center for screen determination
1459 // else use the pointer
1460 XLIB_Window aRoot, aChild;
1461 int root_x, root_y, x, y;
1462 unsigned int mask;
1463 if( mpParent )
1465 root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2;
1466 root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2;
1468 else
1469 XQueryPointer( GetXDisplay(),
1470 GetShellWindow(),
1471 &aRoot, &aChild,
1472 &root_x, &root_y,
1473 &x, &y,
1474 &mask );
1475 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
1476 for( unsigned int i = 0; i < rScreens.size(); i++ )
1477 if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
1479 nScreenX = rScreens[i].Left();
1480 nScreenY = rScreens[i].Top();
1481 nRealScreenWidth = rScreens[i].GetWidth();
1482 nRealScreenHeight = rScreens[i].GetHeight();
1483 break;
1487 if( mpParent )
1489 X11SalFrame* pFrame = mpParent;
1490 while( pFrame->mpParent )
1491 pFrame = pFrame->mpParent;
1492 if( pFrame->maGeometry.nWidth < 1 || pFrame->maGeometry.nHeight < 1 )
1494 Rectangle aRect;
1495 pFrame->GetPosSize( aRect );
1496 pFrame->maGeometry.nX = aRect.Left();
1497 pFrame->maGeometry.nY = aRect.Top();
1498 pFrame->maGeometry.nWidth = aRect.GetWidth();
1499 pFrame->maGeometry.nHeight = aRect.GetHeight();
1502 if( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG )
1504 XLIB_Window aRoot;
1505 unsigned int bw, depth;
1506 XGetGeometry( GetXDisplay(),
1507 pFrame->GetShellWindow(),
1508 &aRoot,
1509 &nScreenX, &nScreenY,
1510 (unsigned int*)&nScreenWidth,
1511 (unsigned int*)&nScreenHeight,
1512 &bw, &depth );
1514 else
1516 nScreenX = pFrame->maGeometry.nX;
1517 nScreenY = pFrame->maGeometry.nY;
1518 nScreenWidth = pFrame->maGeometry.nWidth;
1519 nScreenHeight = pFrame->maGeometry.nHeight;
1523 if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL )
1525 if( maGeometry.nWidth >= mpParent->maGeometry.nWidth &&
1526 maGeometry.nHeight >= mpParent->maGeometry.nHeight )
1528 nX = nScreenX + 40;
1529 nY = nScreenY + 40;
1531 else
1533 // center the window relative to the top level frame
1534 nX = (nScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX;
1535 nY = (nScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
1538 else
1540 // center the window relative to screen
1541 nX = (nRealScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX;
1542 nY = (nRealScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
1544 nX = nX < 0 ? 0 : nX;
1545 nY = nY < 0 ? 0 : nY;
1547 bDefaultPosition_ = False;
1548 if( mpParent )
1550 nX -= mpParent->maGeometry.nX;
1551 nY -= mpParent->maGeometry.nY;
1554 Point aPoint(nX, nY);
1555 SetPosSize( Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
1558 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1559 void X11SalFrame::updateScreenNumber()
1561 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
1563 Point aPoint( maGeometry.nX, maGeometry.nY );
1564 const std::vector<Rectangle>& rScreenRects( GetDisplay()->GetXineramaScreens() );
1565 size_t nScreens = rScreenRects.size();
1566 for( size_t i = 0; i < nScreens; i++ )
1568 if( rScreenRects[i].IsInside( aPoint ) )
1570 maGeometry.nScreenNumber = static_cast<unsigned int>(i);
1571 break;
1575 else
1576 maGeometry.nScreenNumber = static_cast<unsigned int>(m_nScreen);
1579 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1580 void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, USHORT nFlags )
1582 if( nStyle_ & SAL_FRAME_STYLE_PLUG )
1583 return;
1585 // relative positioning in X11SalFrame::SetPosSize
1586 Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) );
1587 aPosSize.Justify();
1589 if( ! ( nFlags & SAL_FRAME_POSSIZE_X ) )
1591 nX = aPosSize.Left();
1592 if( mpParent )
1593 nX -= mpParent->maGeometry.nX;
1595 if( ! ( nFlags & SAL_FRAME_POSSIZE_Y ) )
1597 nY = aPosSize.Top();
1598 if( mpParent )
1599 nY -= mpParent->maGeometry.nY;
1601 if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH ) )
1602 nWidth = aPosSize.GetWidth();
1603 if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT ) )
1604 nHeight = aPosSize.GetHeight();
1606 aPosSize = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1608 if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) ) )
1610 if( bDefaultPosition_ )
1612 maGeometry.nWidth = aPosSize.GetWidth();
1613 maGeometry.nHeight = aPosSize.GetHeight();
1614 Center();
1616 else
1617 SetSize( Size( nWidth, nHeight ) );
1619 else
1620 SetPosSize( aPosSize );
1621 bDefaultPosition_ = False;
1624 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1625 void X11SalFrame::SetAlwaysOnTop( BOOL bOnTop )
1627 if( ! IsOverrideRedirect() )
1629 bAlwaysOnTop_ = bOnTop;
1630 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop );
1634 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1636 #define _FRAMESTATE_MASK_GEOMETRY \
1637 (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y | \
1638 SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)
1639 #define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \
1640 (SAL_FRAMESTATE_MASK_MAXIMIZED_X | SAL_FRAMESTATE_MASK_MAXIMIZED_Y | \
1641 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT)
1643 void X11SalFrame::SetWindowState( const SalFrameState *pState )
1645 if (pState == NULL)
1646 return;
1648 // Request for position or size change
1649 if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY)
1651 Rectangle aPosSize;
1652 bool bDoAdjust = false;
1654 /* #i44325#
1655 * if maximized, set restore size and guess maximized size from last time
1656 * in state change below maximize window
1658 if( ! IsChildWindow() &&
1659 (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) &&
1660 (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) &&
1661 (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) == _FRAMESTATE_MASK_GEOMETRY &&
1662 (pState->mnMask & _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY
1665 XSizeHints* pHints = XAllocSizeHints();
1666 long nSupplied = 0;
1667 XGetWMNormalHints( GetXDisplay(),
1668 GetShellWindow(),
1669 pHints,
1670 &nSupplied );
1671 pHints->flags |= PPosition | PWinGravity;
1672 pHints->x = pState->mnX;
1673 pHints->y = pState->mnY;
1674 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
1675 XSetWMNormalHints( GetXDisplay(),
1676 GetShellWindow(),
1677 pHints );
1678 XFree( pHints );
1680 XMoveResizeWindow( GetXDisplay(), GetShellWindow(),
1681 pState->mnX, pState->mnY,
1682 pState->mnWidth, pState->mnHeight );
1683 // guess maximized geometry from last time
1684 maGeometry.nX = pState->mnMaximizedX;
1685 maGeometry.nY = pState->mnMaximizedY;
1686 maGeometry.nWidth = pState->mnMaximizedWidth;
1687 maGeometry.nHeight = pState->mnMaximizedHeight;
1688 updateScreenNumber();
1690 else
1692 // initialize with current geometry
1693 if ((pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) != _FRAMESTATE_MASK_GEOMETRY)
1694 GetPosSize (aPosSize);
1696 // change requested properties
1697 if (pState->mnMask & SAL_FRAMESTATE_MASK_X)
1699 aPosSize.setX (pState->mnX);
1701 if (pState->mnMask & SAL_FRAMESTATE_MASK_Y)
1703 aPosSize.setY (pState->mnY);
1705 if (pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH)
1707 long nWidth = pState->mnWidth > 0 ? pState->mnWidth - 1 : 0;
1708 aPosSize.setWidth (nWidth);
1709 bDoAdjust = true;
1711 if (pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT)
1713 int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0;
1714 aPosSize.setHeight (nHeight);
1715 bDoAdjust = true;
1718 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize;
1719 const WMAdaptor *pWM = GetDisplay()->getWMAdaptor();
1721 if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width()
1722 && aPosSize.GetHeight() <= aScreenSize.Height() )
1724 SalFrameGeometry aGeom = maGeometry;
1726 if( ! (nStyle_ & ( SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_PLUG ) ) &&
1727 mpParent &&
1728 aGeom.nLeftDecoration == 0 &&
1729 aGeom.nTopDecoration == 0 )
1731 aGeom = mpParent->maGeometry;
1732 if( aGeom.nLeftDecoration == 0 &&
1733 aGeom.nTopDecoration == 0 )
1735 aGeom.nLeftDecoration = 5;
1736 aGeom.nTopDecoration = 20;
1737 aGeom.nRightDecoration = 5;
1738 aGeom.nBottomDecoration = 5;
1742 // adjust position so that frame fits onto screen
1743 if( aPosSize.Right()+(long)aGeom.nRightDecoration > aScreenSize.Width()-1 )
1744 aPosSize.Move( (long)aScreenSize.Width() - (long)aPosSize.Right() - (long)aGeom.nRightDecoration, 0 );
1745 if( aPosSize.Bottom()+(long)aGeom.nBottomDecoration > aScreenSize.Height()-1 )
1746 aPosSize.Move( 0, (long)aScreenSize.Height() - (long)aPosSize.Bottom() - (long)aGeom.nBottomDecoration );
1747 if( aPosSize.Left() < (long)aGeom.nLeftDecoration )
1748 aPosSize.Move( (long)aGeom.nLeftDecoration - (long)aPosSize.Left(), 0 );
1749 if( aPosSize.Top() < (long)aGeom.nTopDecoration )
1750 aPosSize.Move( 0, (long)aGeom.nTopDecoration - (long)aPosSize.Top() );
1753 // resize with new args
1754 if (pWM->supportsICCCMPos())
1756 if( mpParent )
1757 aPosSize.Move( -mpParent->maGeometry.nX,
1758 -mpParent->maGeometry.nY );
1759 SetPosSize( aPosSize );
1760 bDefaultPosition_ = False;
1762 else
1763 SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
1767 // request for status change
1768 if (pState->mnMask & SAL_FRAMESTATE_MASK_STATE)
1770 if (pState->mnState & SAL_FRAMESTATE_MAXIMIZED)
1772 nShowState_ = SHOWSTATE_NORMAL;
1773 if( ! (pState->mnState & (SAL_FRAMESTATE_MAXIMIZED_HORZ|SAL_FRAMESTATE_MAXIMIZED_VERT) ) )
1774 Maximize();
1775 else
1777 bool bHorz = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_HORZ) ? true : false;
1778 bool bVert = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_VERT) ? true : false;
1779 GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert );
1781 maRestorePosSize.Left() = pState->mnX;
1782 maRestorePosSize.Top() = pState->mnY;
1783 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnWidth;
1784 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnHeight;
1786 else if( mbMaximizedHorz || mbMaximizedVert )
1787 GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false );
1789 if (pState->mnState & SAL_FRAMESTATE_MINIMIZED)
1791 if (nShowState_ == SHOWSTATE_UNKNOWN)
1792 nShowState_ = SHOWSTATE_NORMAL;
1793 Minimize();
1795 if (pState->mnState & SAL_FRAMESTATE_NORMAL)
1797 if (nShowState_ != SHOWSTATE_NORMAL)
1798 Restore();
1800 if (pState->mnState & SAL_FRAMESTATE_ROLLUP)
1801 GetDisplay()->getWMAdaptor()->shade( this, true );
1805 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1806 BOOL X11SalFrame::GetWindowState( SalFrameState* pState )
1808 if( SHOWSTATE_MINIMIZED == nShowState_ )
1809 pState->mnState = SAL_FRAMESTATE_MINIMIZED;
1810 else
1811 pState->mnState = SAL_FRAMESTATE_NORMAL;
1813 Rectangle aPosSize;
1814 if( maRestorePosSize.IsEmpty() )
1815 GetPosSize( aPosSize );
1816 else
1817 aPosSize = maRestorePosSize;
1819 if( mbMaximizedHorz )
1820 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_HORZ;
1821 if( mbMaximizedVert )
1822 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_VERT;
1823 if( mbShaded )
1824 pState->mnState |= SAL_FRAMESTATE_ROLLUP;
1826 pState->mnX = aPosSize.Left();
1827 pState->mnY = aPosSize.Top();
1828 pState->mnWidth = aPosSize.GetWidth();
1829 pState->mnHeight = aPosSize.GetHeight();
1831 pState->mnMask = _FRAMESTATE_MASK_GEOMETRY | SAL_FRAMESTATE_MASK_STATE;
1834 if (! maRestorePosSize.IsEmpty() )
1836 GetPosSize( aPosSize );
1837 pState->mnState |= SAL_FRAMESTATE_MAXIMIZED;
1838 pState->mnMaximizedX = aPosSize.Left();
1839 pState->mnMaximizedY = aPosSize.Top();
1840 pState->mnMaximizedWidth = aPosSize.GetWidth();
1841 pState->mnMaximizedHeight = aPosSize.GetHeight();
1842 pState->mnMask |= _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY;
1845 return TRUE;
1848 // ----------------------------------------------------------------------------
1849 // get a screenshot of the current frame including window manager decoration
1850 SalBitmap* X11SalFrame::SnapShot()
1852 Display* pDisplay = GetXDisplay();
1854 // make sure the frame has been reparented and all paint timer have been
1855 // expired
1858 XSync(pDisplay, False);
1859 Application::Reschedule ();
1861 while (XPending(pDisplay));
1862 TimeValue aVal;
1863 aVal.Seconds = 0;
1864 aVal.Nanosec = 50000000;
1865 osl_waitThread( &aVal );
1868 XSync(pDisplay, False);
1869 Application::Reschedule ();
1871 while (XPending(pDisplay));
1873 // get the most outer window, usually the window manager decoration
1874 Drawable hWindow = None;
1875 if (IsOverrideRedirect())
1876 hWindow = GetDrawable();
1877 else
1878 if (hPresentationWindow != None)
1879 hWindow = hPresentationWindow;
1880 else
1881 hWindow = GetStackingWindow();
1883 // query the contents of the window
1884 if (hWindow != None)
1886 X11SalBitmap *pBmp = new X11SalBitmap;
1887 if (pBmp->SnapShot (pDisplay, hWindow))
1888 return pBmp;
1889 else
1890 delete pBmp;
1893 return NULL;
1896 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1898 // native menu implementation - currently empty
1899 void X11SalFrame::DrawMenuBar()
1903 void X11SalFrame::SetMenu( SalMenu* )
1907 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1908 void X11SalFrame::GetPosSize( Rectangle &rPosSize )
1910 if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 )
1912 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize;
1913 long w = aScreenSize.Width() - maGeometry.nLeftDecoration - maGeometry.nRightDecoration;
1914 long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration;
1916 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) );
1918 else
1919 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
1920 Size( maGeometry.nWidth, maGeometry.nHeight ) );
1923 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1924 void X11SalFrame::SetSize( const Size &rSize )
1926 if( rSize.Width() > 0 && rSize.Height() > 0 )
1928 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
1929 && ! IsChildWindow()
1930 && ( nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
1932 XSizeHints* pHints = XAllocSizeHints();
1933 long nSupplied = 0;
1934 XGetWMNormalHints( GetXDisplay(),
1935 GetShellWindow(),
1936 pHints,
1937 &nSupplied
1939 pHints->min_width = rSize.Width();
1940 pHints->min_height = rSize.Height();
1941 pHints->max_width = rSize.Width();
1942 pHints->max_height = rSize.Height();
1943 pHints->flags |= PMinSize | PMaxSize;
1944 XSetWMNormalHints( GetXDisplay(),
1945 GetShellWindow(),
1946 pHints );
1947 XFree( pHints );
1949 XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() );
1950 if( GetWindow() != GetShellWindow() )
1952 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
1953 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() );
1954 else
1955 XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() );
1958 maGeometry.nWidth = rSize.Width();
1959 maGeometry.nHeight = rSize.Height();
1961 // allow the external status window to reposition
1962 if (mbInputFocus && mpInputContext != NULL)
1963 mpInputContext->SetICFocus ( this );
1967 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1969 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1971 void X11SalFrame::SetPosSize( const Rectangle &rPosSize )
1973 XWindowChanges values;
1974 values.x = rPosSize.Left();
1975 values.y = rPosSize.Top();
1976 values.width = rPosSize.GetWidth();
1977 values.height = rPosSize.GetHeight();
1979 if( !values.width || !values.height )
1980 return;
1982 if( mpParent && ! IsSysChildWindow() )
1984 // --- RTL --- (mirror window pos)
1985 if( Application::GetSettings().GetLayoutRTL() )
1986 values.x = mpParent->maGeometry.nWidth-values.width-1-values.x;
1988 XLIB_Window aChild;
1989 // coordinates are relative to parent, so translate to root coordinates
1990 XTranslateCoordinates( GetDisplay()->GetDisplay(),
1991 mpParent->GetWindow(),
1992 GetDisplay()->GetRootWindow( m_nScreen ),
1993 values.x, values.y,
1994 &values.x, &values.y,
1995 & aChild );
1998 bool bMoved = false;
1999 bool bSized = false;
2000 if( values.x != maGeometry.nX || values.y != maGeometry.nY )
2001 bMoved = true;
2002 if( values.width != (int)maGeometry.nWidth || values.height != (int)maGeometry.nHeight )
2003 bSized = true;
2005 if( ! ( nStyle_ & ( SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_FLOAT ) )
2006 && !(pDisplay_->GetProperties() & PROPERTY_SUPPORT_WM_ClientPos) )
2008 values.x -= maGeometry.nLeftDecoration;
2009 values.y -= maGeometry.nTopDecoration;
2012 // do net set WMNormalHints for ..
2014 // child windows
2015 ! IsChildWindow()
2016 // popups (menu, help window, etc.)
2017 && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT
2018 // shown, sizeable windows
2019 && ( nShowState_ == SHOWSTATE_UNKNOWN ||
2020 nShowState_ == SHOWSTATE_HIDDEN ||
2021 ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
2025 XSizeHints* pHints = XAllocSizeHints();
2026 long nSupplied = 0;
2027 XGetWMNormalHints( GetXDisplay(),
2028 GetShellWindow(),
2029 pHints,
2030 &nSupplied
2032 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
2034 pHints->min_width = rPosSize.GetWidth();
2035 pHints->min_height = rPosSize.GetHeight();
2036 pHints->max_width = rPosSize.GetWidth();
2037 pHints->max_height = rPosSize.GetHeight();
2038 pHints->flags |= PMinSize | PMaxSize;
2040 if( nShowState_ == SHOWSTATE_UNKNOWN || nShowState_ == SHOWSTATE_HIDDEN )
2042 pHints->flags |= PPosition | PWinGravity;
2043 pHints->x = values.x;
2044 pHints->y = values.y;
2045 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
2047 XSetWMNormalHints( GetXDisplay(),
2048 GetShellWindow(),
2049 pHints );
2050 XFree( pHints );
2053 XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height );
2054 if( GetShellWindow() != GetWindow() )
2056 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
2057 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height );
2058 else
2059 XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height );
2062 maGeometry.nX = values.x;
2063 maGeometry.nY = values.y;
2064 maGeometry.nWidth = values.width;
2065 maGeometry.nHeight = values.height;
2066 if( IsSysChildWindow() && mpParent )
2068 // translate back to root coordinates
2069 maGeometry.nX += mpParent->maGeometry.nX;
2070 maGeometry.nY += mpParent->maGeometry.nY;
2073 updateScreenNumber();
2074 if( bSized && ! bMoved )
2075 CallCallback( SALEVENT_RESIZE, NULL );
2076 else if( bMoved && ! bSized )
2077 CallCallback( SALEVENT_MOVE, NULL );
2078 else
2079 CallCallback( SALEVENT_MOVERESIZE, NULL );
2081 // allow the external status window to reposition
2082 if (mbInputFocus && mpInputContext != NULL)
2083 mpInputContext->SetICFocus ( this );
2086 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2087 void X11SalFrame::Minimize()
2089 if( IsSysChildWindow() )
2090 return;
2092 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
2094 stderr0( "X11SalFrame::Minimize on withdrawn window\n" );
2095 return;
2098 if( XIconifyWindow( GetXDisplay(),
2099 GetShellWindow(),
2100 pDisplay_->GetDefaultScreenNumber() ) )
2101 nShowState_ = SHOWSTATE_MINIMIZED;
2104 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2105 void X11SalFrame::Maximize()
2107 if( IsSysChildWindow() )
2108 return;
2110 if( SHOWSTATE_MINIMIZED == nShowState_ )
2112 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2113 XMapWindow( GetXDisplay(), GetShellWindow() );
2114 nShowState_ = SHOWSTATE_NORMAL;
2117 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
2120 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2121 void X11SalFrame::Restore()
2123 if( IsSysChildWindow() )
2124 return;
2126 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
2128 stderr0( "X11SalFrame::Restore on withdrawn window\n" );
2129 return;
2132 if( SHOWSTATE_MINIMIZED == nShowState_ )
2134 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2135 XMapWindow( GetXDisplay(), GetShellWindow() );
2136 nShowState_ = SHOWSTATE_NORMAL;
2139 pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false );
2142 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2144 void X11SalFrame::SetScreenNumber( unsigned int nNewScreen )
2146 if( nNewScreen == maGeometry.nScreenNumber )
2147 return;
2149 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2151 if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() )
2152 return;
2154 Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nScreenNumber] );
2155 Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] );
2156 bool bVisible = bMapped_;
2157 if( bVisible )
2158 Show( FALSE );
2159 maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left());
2160 maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top());
2161 createNewWindow( None, m_nScreen );
2162 if( bVisible )
2163 Show( TRUE );
2164 maGeometry.nScreenNumber = nNewScreen;
2166 else if( sal_Int32(nNewScreen) < GetDisplay()->GetScreenCount() )
2168 bool bVisible = bMapped_;
2169 if( bVisible )
2170 Show( FALSE );
2171 createNewWindow( None, nNewScreen );
2172 if( bVisible )
2173 Show( TRUE );
2174 maGeometry.nScreenNumber = nNewScreen;
2178 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2180 void X11SalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nScreen )
2182 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2184 if( mbFullScreen == (bool)bFullScreen )
2185 return;
2186 if( bFullScreen )
2188 maRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
2189 Size( maGeometry.nWidth, maGeometry.nHeight ) );
2190 Rectangle aRect;
2191 if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) )
2192 aRect = Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nScreen ) );
2193 else
2194 aRect = GetDisplay()->GetXineramaScreens()[nScreen];
2195 nStyle_ |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
2196 bool bVisible = bMapped_;
2197 if( bVisible )
2198 Show( FALSE );
2199 maGeometry.nX = aRect.Left();
2200 maGeometry.nY = aRect.Top();
2201 maGeometry.nWidth = aRect.GetWidth();
2202 maGeometry.nHeight = aRect.GetHeight();
2203 mbMaximizedHorz = mbMaximizedVert = false;
2204 createNewWindow( None, m_nScreen );
2205 GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true );
2206 #if 0
2207 // this would give additional intent to the window
2208 // manager to force the positioning of the window;
2209 // alas all other windows will be expunged from that
2210 // region, leaving us in a pity state afterwards
2211 Size aScreenSize = pDisplay_->GetScreenSize( m_nScreen );
2212 pDisplay_->getWMAdaptor()->setFrameStruts( this,
2213 aRect.Left(), aRect.Top(),
2214 aScreenSize.Width() - aRect.Right(),
2215 aScreenSize.Height() - aRect.Bottom(),
2216 aRect.Left(), aRect.Right(),
2217 aRect.Top(), aRect.Bottom(),
2218 aRect.Left(), aRect.Right(),
2219 aRect.Top(), aRect.Bottom()
2221 #endif
2223 if( bVisible )
2224 Show(TRUE);
2225 mbFullScreen = true;
2227 else
2229 mbFullScreen = false;
2230 nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
2231 bool bVisible = bMapped_;
2232 Rectangle aRect = maRestorePosSize;
2233 maRestorePosSize = Rectangle();
2234 if( bVisible )
2235 Show( FALSE );
2236 createNewWindow( None, m_nScreen );
2237 if( !aRect.IsEmpty() )
2238 SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
2239 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y |
2240 SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
2241 if( bVisible )
2242 Show( TRUE );
2245 else
2247 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
2248 nScreen = m_nScreen;
2249 if( nScreen != m_nScreen )
2251 bool bVisible = bMapped_;
2252 if( mbFullScreen )
2253 pDisplay_->getWMAdaptor()->showFullScreen( this, false );
2254 if( bVisible )
2255 Show( FALSE );
2256 createNewWindow( None, nScreen );
2257 if( mbFullScreen )
2258 pDisplay_->getWMAdaptor()->showFullScreen( this, true );
2259 if( bVisible )
2260 Show( TRUE );
2262 if( mbFullScreen == (bool)bFullScreen )
2263 return;
2265 pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen );
2266 if( IsOverrideRedirect()
2267 && WMSupportsFWS( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ) ) )
2269 AddFwsProtocols( GetXDisplay(), GetShellWindow() );
2270 RegisterFwsWindow( GetXDisplay(), GetShellWindow() );
2275 /* ---------------------------------------------------------------------
2276 the xautolock pseudo screen saver needs special treatment since it
2277 doesn't cooperate with XxxxScreenSaver settings
2278 ------------------------------------------------------------------- */
2280 static Bool
2281 IsRunningXAutoLock( Display *p_display, XLIB_Window a_window )
2283 const char *p_atomname = "XAUTOLOCK_SEMAPHORE_PID";
2284 Atom a_pidatom;
2286 // xautolock interns this atom
2287 a_pidatom = XInternAtom( p_display, p_atomname, True );
2288 if ( a_pidatom == None )
2289 return False;
2291 Atom a_type;
2292 int n_format;
2293 unsigned long n_items;
2294 unsigned long n_bytes_after;
2295 pid_t *p_pid;
2296 pid_t n_pid;
2297 // get pid of running xautolock
2298 XGetWindowProperty (p_display, a_window, a_pidatom, 0L, 2L, False,
2299 AnyPropertyType, &a_type, &n_format, &n_items, &n_bytes_after,
2300 (unsigned char**) &p_pid );
2301 n_pid = *p_pid;
2302 XFree( p_pid );
2304 if ( a_type == XA_INTEGER )
2306 // check if xautolock pid points to a running process
2307 if ( kill(n_pid, 0) == -1 )
2308 return False;
2309 else
2310 return True;
2313 return False;
2316 /* definitions from xautolock.c (pl15) */
2317 #define XAUTOLOCK_DISABLE 1
2318 #define XAUTOLOCK_ENABLE 2
2320 static Bool
2321 MessageToXAutoLock( Display *p_display, int n_message )
2323 const char *p_atomname = "XAUTOLOCK_MESSAGE" ;
2324 Atom a_messageatom;
2325 XLIB_Window a_rootwindow;
2327 a_rootwindow = RootWindowOfScreen( ScreenOfDisplay(p_display, 0) );
2328 if ( ! IsRunningXAutoLock(p_display, a_rootwindow) )
2330 // remove any pending messages
2331 a_messageatom = XInternAtom( p_display, p_atomname, True );
2332 if ( a_messageatom != None )
2333 XDeleteProperty( p_display, a_rootwindow, a_messageatom );
2334 return False;
2337 a_messageatom = XInternAtom( p_display, p_atomname, False );
2338 XChangeProperty (p_display, a_rootwindow, a_messageatom, XA_INTEGER,
2339 8, PropModeReplace, (unsigned char*)&n_message, sizeof(n_message) );
2341 return True;
2344 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2345 void X11SalFrame::StartPresentation( BOOL bStart )
2347 I18NStatus::get().show( !bStart, I18NStatus::presentation );
2348 if ( bStart )
2349 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_DISABLE );
2350 else
2351 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_ENABLE );
2353 if( ! bStart && hPresentationWindow != None )
2354 doReparentPresentationDialogues( GetDisplay() );
2355 hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None;
2358 // needs static here to save DPMS settings
2359 int dummy;
2360 static bool DPMSExtensionAvailable =
2361 #ifndef SOLARIS
2362 (DPMSQueryExtension(GetXDisplay(), &dummy, &dummy) != 0);
2363 static XLIB_BOOL DPMSEnabled = false;
2364 #else
2365 false;
2366 bool DPMSEnabled = false;
2367 (void)dummy;
2368 #define CARD16 unsigned short
2369 #endif
2370 static CARD16 dpms_standby_timeout=0;
2371 static CARD16 dpms_suspend_timeout=0;
2372 static CARD16 dpms_off_timeout=0;
2375 if( bStart || nScreenSaversTimeout_ || DPMSEnabled)
2377 if( hPresentationWindow )
2379 /* #i10559# workaround for WindowMaker: try to restore
2380 * current focus after presentation window is gone
2382 int revert_to = 0;
2383 XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to );
2385 int timeout, interval, prefer_blanking, allow_exposures;
2386 XGetScreenSaver( GetXDisplay(),
2387 &timeout,
2388 &interval,
2389 &prefer_blanking,
2390 &allow_exposures );
2393 // get the DPMS state right before the start
2394 if (DPMSExtensionAvailable)
2396 #ifndef SOLARIS
2397 CARD16 state; // card16 is defined in Xdm.h
2398 DPMSInfo( GetXDisplay(),
2399 &state,
2400 &DPMSEnabled);
2401 #endif
2403 if( bStart ) // start show
2405 if ( timeout )
2407 nScreenSaversTimeout_ = timeout;
2408 XResetScreenSaver( GetXDisplay() );
2409 XSetScreenSaver( GetXDisplay(),
2411 interval,
2412 prefer_blanking,
2413 allow_exposures );
2415 #ifndef SOLARIS
2416 if( DPMSEnabled )
2418 if ( DPMSExtensionAvailable )
2420 DPMSGetTimeouts( GetXDisplay(),
2421 &dpms_standby_timeout,
2422 &dpms_suspend_timeout,
2423 &dpms_off_timeout);
2424 DPMSSetTimeouts(GetXDisplay(), 0,0,0);
2427 #endif
2429 else // if( !bStart ) // end of show
2431 if( nScreenSaversTimeout_ )
2433 XSetScreenSaver( GetXDisplay(),
2434 nScreenSaversTimeout_,
2435 interval,
2436 prefer_blanking,
2437 allow_exposures );
2438 nScreenSaversTimeout_ = 0;
2440 #ifndef SOLARIS
2441 if ( DPMSEnabled )
2443 if ( DPMSExtensionAvailable )
2445 // restore timeouts
2446 DPMSSetTimeouts(GetXDisplay(), dpms_standby_timeout,
2447 dpms_suspend_timeout, dpms_off_timeout);
2450 #endif
2455 // Pointer
2456 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2457 void X11SalFrame::SetPointer( PointerStyle ePointerStyle )
2459 hCursor_ = pDisplay_->GetPointer( ePointerStyle );
2460 XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ );
2462 if( IsCaptured() || nVisibleFloats > 0 )
2463 XChangeActivePointerGrab( GetXDisplay(),
2464 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
2465 hCursor_,
2466 CurrentTime );
2469 void X11SalFrame::SetPointerPos(long nX, long nY)
2471 /* #87921# when the application tries to center the mouse in the dialog the
2472 * window isn't mapped already. So use coordinates relative to the root window.
2474 unsigned int nWindowLeft = maGeometry.nX + nX;
2475 unsigned int nWindowTop = maGeometry.nY + nY;
2477 XWarpPointer( GetXDisplay(), None, pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ),
2478 0, 0, 0, 0, nWindowLeft, nWindowTop);
2481 // delay handling of extended text input
2482 #if !defined(__synchronous_extinput__)
2483 void
2484 X11SalFrame::PostExtTextEvent (sal_uInt16 nExtTextEventType, void *pExtTextEvent)
2486 XLIB_Window nFocusWindow = GetWindow();
2487 Atom nEventAtom = GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::SAL_EXTTEXTEVENT );
2489 XEvent aEvent;
2490 aEvent.xclient.type = ClientMessage;
2491 aEvent.xclient.serial = 0;
2492 aEvent.xclient.send_event = True;
2493 aEvent.xclient.display = GetXDisplay();
2494 aEvent.xclient.window = nFocusWindow;
2495 aEvent.xclient.message_type = nEventAtom;
2496 aEvent.xclient.format = 32;
2498 #if SAL_TYPES_SIZEOFLONG > 4
2499 aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent & 0xffffffff);
2500 aEvent.xclient.data.l[1] = (sal_uInt32)((long)pExtTextEvent >> 32);
2501 #else
2502 aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent);
2503 aEvent.xclient.data.l[1] = 0;
2504 #endif
2505 aEvent.xclient.data.l[2] = (sal_uInt32)nExtTextEventType;
2506 aEvent.xclient.data.l[3] = 0;
2507 aEvent.xclient.data.l[4] = 0;
2509 XPutBackEvent( GetXDisplay(), &aEvent );
2512 void
2513 X11SalFrame::HandleExtTextEvent (XClientMessageEvent *pEvent)
2515 #if SAL_TYPES_SIZEOFLONG > 4
2516 void* pExtTextEvent = (void*)( (pEvent->data.l[0] & 0xffffffff)
2517 | (pEvent->data.l[1] << 32) );
2518 #else
2519 void* pExtTextEvent = (void*)(pEvent->data.l[0]);
2520 #endif
2521 sal_uInt16 nExtTextEventType = sal_uInt16(pEvent->data.l[2]);
2523 CallCallback(nExtTextEventType, pExtTextEvent);
2525 switch (nExtTextEventType)
2527 case SALEVENT_ENDEXTTEXTINPUT:
2528 break;
2530 case SALEVENT_EXTTEXTINPUT:
2531 break;
2533 default:
2535 fprintf(stderr, "X11SalFrame::HandleExtTextEvent: invalid extended input\n");
2538 #endif /* defined(__synchronous_extinput__) */
2540 // PostEvent
2541 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2542 BOOL X11SalFrame::PostEvent( void *pData )
2544 GetDisplay()->SendInternalEvent( this, pData );
2545 return TRUE;
2548 // Title
2549 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2550 void X11SalFrame::SetTitle( const XubString& rTitle )
2552 if( ! ( IsChildWindow() || (nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) )
2554 m_aTitle = rTitle;
2555 GetDisplay()->getWMAdaptor()->setWMName( this, rTitle );
2559 // -----------------------------------------------------------------------
2561 void X11SalFrame::Flush()
2563 XFlush( GetDisplay()->GetDisplay() );
2566 // -----------------------------------------------------------------------
2568 void X11SalFrame::Sync()
2570 XSync( GetDisplay()->GetDisplay(), False );
2573 // Keyboard
2574 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2576 // -----------------------------------------------------------------------
2578 void X11SalFrame::SetInputContext( SalInputContext* pContext )
2580 if (pContext == NULL)
2581 return;
2583 // 1. We should create an input context for this frame
2584 // only when SAL_INPUTCONTEXT_TEXT is set.
2586 if (!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT))
2588 if( mpInputContext )
2589 mpInputContext->Unmap( this );
2590 return;
2593 // 2. We should use on-the-spot inputstyle
2594 // only when SAL_INPUTCONTEXT_EXTTEXTINPUT is set.
2596 if (mpInputContext == NULL)
2598 I18NStatus& rStatus( I18NStatus::get() );
2599 rStatus.setParent( this );
2600 mpInputContext = new SalI18N_InputContext( this );
2601 if (mpInputContext->UseContext())
2603 mpInputContext->ExtendEventMask( GetShellWindow() );
2604 if (pContext->mnOptions & SAL_INPUTCONTEXT_CHANGELANGUAGE)
2605 mpInputContext->SetLanguage(pContext->meLanguage);
2606 if (mbInputFocus)
2607 mpInputContext->SetICFocus( this );
2610 else
2611 mpInputContext->Map( this );
2612 return;
2615 // -----------------------------------------------------------------------
2617 void X11SalFrame::EndExtTextInput( USHORT nFlags )
2619 if (mpInputContext != NULL)
2620 mpInputContext->EndExtTextInput( nFlags );
2623 // -----------------------------------------------------------------------
2625 XubString X11SalFrame::GetKeyName( USHORT nKeyCode )
2627 return GetDisplay()->GetKeyName( nKeyCode );
2630 XubString X11SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
2632 return GetKeyName( nKeyCode );
2635 BOOL X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
2637 // not supported yet
2638 return FALSE;
2641 LanguageType X11SalFrame::GetInputLanguage()
2643 // could be improved by checking unicode ranges of the last input
2644 return LANGUAGE_DONTKNOW;
2647 // Settings
2648 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2650 inline Color getColorFromLong( long nColor )
2652 return Color( (nColor & 0xff), (nColor & 0xff00)>>8, (nColor & 0xff0000)>>16);
2655 void X11SalFrame::UpdateSettings( AllSettings& rSettings )
2658 DtIntegrator* pIntegrator = GetDisplay()->getDtIntegrator();
2659 #if OSL_DEBUG_LEVEL > 1
2660 fprintf( stderr, "DtIntegrator: %d\n", pIntegrator ? pIntegrator->GetDtType() : -1 );
2661 #endif
2662 if( pIntegrator )
2663 pIntegrator->GetSystemLook( rSettings );
2666 void X11SalFrame::CaptureMouse( BOOL bCapture )
2668 nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : NULL );
2671 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2673 void X11SalFrame::SetParent( SalFrame* pNewParent )
2675 if( mpParent != pNewParent )
2677 if( mpParent )
2678 mpParent->maChildren.remove( this );
2680 mpParent = static_cast<X11SalFrame*>(pNewParent);
2681 mpParent->maChildren.push_back( this );
2682 if( mpParent->m_nScreen != m_nScreen )
2683 createNewWindow( None, mpParent->m_nScreen );
2684 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2688 SalFrame* X11SalFrame::GetParent() const
2690 return mpParent;
2693 void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen )
2695 bool bWasVisible = bMapped_;
2696 if( bWasVisible )
2697 Show( FALSE );
2699 if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
2700 nScreen = m_nScreen;
2702 SystemParentData aParentData;
2703 aParentData.aWindow = aNewParent;
2704 aParentData.bXEmbedSupport = (aNewParent != None && m_bXEmbed); // caution: this is guesswork
2705 if( aNewParent == None )
2707 aNewParent = GetDisplay()->GetRootWindow(nScreen);
2708 aParentData.aWindow = None;
2709 m_bXEmbed = false;
2711 else
2713 // is new parent a root window ?
2714 Display* pDisp = GetDisplay()->GetDisplay();
2715 int nScreens = GetDisplay()->GetScreenCount();
2716 for( int i = 0; i < nScreens; i++ )
2718 if( aNewParent == RootWindow( pDisp, i ) )
2720 nScreen = i;
2721 aParentData.aWindow = None;
2722 m_bXEmbed = false;
2723 break;
2728 // first deinit frame
2729 if( mpInputContext )
2731 mpInputContext->UnsetICFocus( this );
2732 mpInputContext->Unmap( this );
2734 if( GetWindow() == hPresentationWindow )
2736 hPresentationWindow = None;
2737 doReparentPresentationDialogues( GetDisplay() );
2739 XDestroyWindow( GetXDisplay(), mhWindow );
2740 mhWindow = None;
2742 passOnSaveYourSelf();
2744 // now init with new parent again
2745 if ( aParentData.aWindow != None )
2746 Init( nStyle_ | SAL_FRAME_STYLE_PLUG, nScreen, &aParentData );
2747 else
2748 Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nScreen, NULL, true );
2750 // update graphics if necessary
2751 updateGraphics();
2753 if( m_aTitle.Len() )
2754 SetTitle( m_aTitle );
2756 if( mpParent )
2758 if( mpParent->m_nScreen != m_nScreen )
2759 SetParent( NULL );
2760 else
2761 pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2764 if( bWasVisible )
2765 Show( TRUE );
2767 std::list< X11SalFrame* > aChildren = maChildren;
2768 for( std::list< X11SalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
2769 (*it)->createNewWindow( None, m_nScreen );
2771 // FIXME: SalObjects
2774 bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent )
2776 if( pNewParent->nSize >= sizeof(SystemParentData) )
2777 m_bXEmbed = pNewParent->aWindow != None && pNewParent->bXEmbedSupport;
2778 createNewWindow( pNewParent ? pNewParent->aWindow : None );
2780 return true;
2783 // Sound
2784 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2785 void X11SalFrame::Beep( SoundType eSoundType ) // not fully suported
2787 switch( eSoundType )
2789 case SOUND_DEFAULT:
2790 case SOUND_ERROR:
2791 GetDisplay()->Beep();
2792 break;
2793 default:
2794 // Excessive beeping averted
2795 break;
2799 // Event Handling
2800 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2801 static USHORT sal_GetCode( int state )
2803 USHORT nCode = 0;
2805 if( state & Button1Mask )
2806 nCode |= MOUSE_LEFT;
2807 if( state & Button2Mask )
2808 nCode |= MOUSE_MIDDLE;
2809 if( state & Button3Mask )
2810 nCode |= MOUSE_RIGHT;
2812 if( state & ShiftMask )
2813 nCode |= KEY_SHIFT;
2814 if( state & ControlMask )
2815 nCode |= KEY_MOD1;
2816 if( state & Mod1Mask )
2817 nCode |= KEY_MOD2;
2819 // Map Meta/Super modifier to MOD3 on all Unix systems
2820 // except Mac OS X
2821 if( (state & Mod3Mask) )
2822 nCode |= KEY_MOD3;
2824 return nCode;
2827 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2829 SalFrame::SalPointerState X11SalFrame::GetPointerState()
2831 SalPointerState aState;
2832 XLIB_Window aRoot, aChild;
2833 int rx, ry, wx, wy;
2834 unsigned int nMask = 0;
2835 XQueryPointer( GetXDisplay(),
2836 GetShellWindow(),
2837 &aRoot,
2838 &aChild,
2839 &rx, &ry,
2840 &wx, &wy,
2841 &nMask
2844 aState.maPos = Point(wx, wy);
2845 aState.mnState = sal_GetCode( nMask );
2846 return aState;
2849 SalFrame::SalIndicatorState X11SalFrame::GetIndicatorState()
2851 SalIndicatorState aState;
2852 aState.mnState = GetX11SalData()->GetDisplay()->GetIndicatorState();
2853 return aState;
2856 void X11SalFrame::SimulateKeyPress( USHORT nKeyCode )
2858 GetX11SalData()->GetDisplay()->SimulateKeyPress(nKeyCode);
2861 long X11SalFrame::HandleMouseEvent( XEvent *pEvent )
2863 SalMouseEvent aMouseEvt;
2864 USHORT nEvent = 0;
2865 bool bClosePopups = false;
2867 if( nVisibleFloats && pEvent->type == EnterNotify )
2868 return 0;
2870 // Solaris X86: clicking the right button on a two-button mouse
2871 // generates a button2 event not a button3 event
2872 if (pDisplay_->GetProperties() & PROPERTY_SUPPORT_3ButtonMouse )
2874 switch (pEvent->type)
2876 case EnterNotify:
2877 case LeaveNotify:
2878 if ( pEvent->xcrossing.state & Button2Mask )
2880 pEvent->xcrossing.state &= ~Button2Mask;
2881 pEvent->xcrossing.state |= Button3Mask;
2883 break;
2885 case MotionNotify:
2886 if ( pEvent->xmotion.state & Button2Mask )
2888 pEvent->xmotion.state &= ~Button2Mask;
2889 pEvent->xmotion.state |= Button3Mask;
2891 break;
2893 default:
2894 if ( Button2 == pEvent->xbutton.button )
2896 pEvent->xbutton.state &= ~Button2Mask;
2897 pEvent->xbutton.state |= Button3Mask;
2898 pEvent->xbutton.button = Button3;
2900 break;
2905 if( LeaveNotify == pEvent->type || EnterNotify == pEvent->type )
2908 * #89075# #89335#
2910 * some WMs (and/or) applications have a passive grab on
2911 * mouse buttons (XGrabButton). This leads to enter/leave notifies
2912 * with mouse buttons pressed in the state mask before the actual
2913 * ButtonPress event gets dispatched. But EnterNotify
2914 * is reported in vcl as MouseMove event. Some office code
2915 * decides that a pressed button in a MouseMove belongs to
2916 * a drag operation which leads to doing things differently.
2918 * #95901#
2919 * ignore Enter/LeaveNotify resulting from grabs so that
2920 * help windows do not disappear just after appearing
2922 * hopefully this workaround will not break anything.
2924 if( pEvent->xcrossing.mode == NotifyGrab || pEvent->xcrossing.mode == NotifyUngrab )
2925 return 0;
2927 aMouseEvt.mnX = pEvent->xcrossing.x;
2928 aMouseEvt.mnY = pEvent->xcrossing.y;
2929 aMouseEvt.mnTime = pEvent->xcrossing.time;
2930 aMouseEvt.mnCode = sal_GetCode( pEvent->xcrossing.state );
2931 aMouseEvt.mnButton = 0;
2933 nEvent = LeaveNotify == pEvent->type
2934 ? SALEVENT_MOUSELEAVE
2935 : SALEVENT_MOUSEMOVE;
2937 else if( pEvent->type == MotionNotify )
2939 aMouseEvt.mnX = pEvent->xmotion.x;
2940 aMouseEvt.mnY = pEvent->xmotion.y;
2941 aMouseEvt.mnTime = pEvent->xmotion.time;
2942 aMouseEvt.mnCode = sal_GetCode( pEvent->xmotion.state );
2944 aMouseEvt.mnButton = 0;
2946 nEvent = SALEVENT_MOUSEMOVE;
2947 if( nVisibleFloats > 0 && mpParent )
2949 XLIB_Cursor aCursor = mpParent->GetCursor();
2950 if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < (int)maGeometry.nWidth &&
2951 pEvent->xmotion.y >= 0 && pEvent->xmotion.y < (int)maGeometry.nHeight )
2952 aCursor = None;
2954 XChangeActivePointerGrab( GetXDisplay(),
2955 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
2956 aCursor,
2957 CurrentTime );
2960 else
2962 // let mouse events reach the correct window
2963 if( nVisibleFloats < 1 )
2965 if( ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
2966 XUngrabPointer( GetXDisplay(), CurrentTime );
2968 else if( pEvent->type == ButtonPress )
2970 // see if the user clicks outside all of the floats
2971 // if yes release the grab
2972 bool bInside = false;
2973 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
2974 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
2976 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
2977 if( pFrame->IsFloatGrabWindow() &&
2978 pFrame->bMapped_ &&
2979 pEvent->xbutton.x_root >= pFrame->maGeometry.nX &&
2980 pEvent->xbutton.x_root < pFrame->maGeometry.nX + (int)pFrame->maGeometry.nWidth &&
2981 pEvent->xbutton.y_root >= pFrame->maGeometry.nY &&
2982 pEvent->xbutton.y_root < pFrame->maGeometry.nY + (int)pFrame->maGeometry.nHeight )
2984 bInside = true;
2985 break;
2988 if( ! bInside )
2990 // need not take care of the XUngrabPointer in Show( FALSE )
2991 // because XUngrabPointer does not produce errors if pointer
2992 // is not grabbed
2993 XUngrabPointer( GetXDisplay(), CurrentTime );
2994 bClosePopups = true;
2996 /* #i15246# only close popups if pointer is outside all our frames
2997 * cannot use our own geometry data here because stacking
2998 * is unknown (the above case implicitly assumes
2999 * that floats are on top which should be true)
3001 XLIB_Window aRoot, aChild;
3002 int root_x, root_y, win_x, win_y;
3003 unsigned int mask_return;
3004 if( XQueryPointer( GetXDisplay(),
3005 GetDisplay()->GetRootWindow( m_nScreen ),
3006 &aRoot, &aChild,
3007 &root_x, &root_y,
3008 &win_x, &win_y,
3009 &mask_return )
3010 && aChild // pointer may not be in any child
3013 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
3015 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
3016 if( ! pFrame->IsFloatGrabWindow()
3017 && ( pFrame->GetWindow() == aChild ||
3018 pFrame->GetShellWindow() == aChild ||
3019 pFrame->GetStackingWindow() == aChild )
3022 // #i63638# check that pointer is inside window, not
3023 // only inside stacking window
3024 if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) &&
3025 root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) )
3027 bClosePopups = false;
3029 break;
3036 if( m_bXEmbed && pEvent->xbutton.button == Button1 )
3037 askForXEmbedFocus( pEvent->xbutton.time );
3039 if( pEvent->xbutton.button == Button1 ||
3040 pEvent->xbutton.button == Button2 ||
3041 pEvent->xbutton.button == Button3 )
3043 aMouseEvt.mnX = pEvent->xbutton.x;
3044 aMouseEvt.mnY = pEvent->xbutton.y;
3045 aMouseEvt.mnTime = pEvent->xbutton.time;
3046 aMouseEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
3048 if( Button1 == pEvent->xbutton.button )
3049 aMouseEvt.mnButton = MOUSE_LEFT;
3050 else if( Button2 == pEvent->xbutton.button )
3051 aMouseEvt.mnButton = MOUSE_MIDDLE;
3052 else if( Button3 == pEvent->xbutton.button )
3053 aMouseEvt.mnButton = MOUSE_RIGHT;
3055 nEvent = ButtonPress == pEvent->type
3056 ? SALEVENT_MOUSEBUTTONDOWN
3057 : SALEVENT_MOUSEBUTTONUP;
3059 else if( pEvent->xbutton.button == Button4 ||
3060 pEvent->xbutton.button == Button5 ||
3061 pEvent->xbutton.button == Button6 ||
3062 pEvent->xbutton.button == Button7 )
3064 const bool bIncrement(
3065 pEvent->xbutton.button == Button4 ||
3066 pEvent->xbutton.button == Button6 );
3067 const bool bHoriz(
3068 pEvent->xbutton.button == Button6 ||
3069 pEvent->xbutton.button == Button7 );
3071 if( pEvent->type == ButtonRelease )
3072 return 0;
3074 static ULONG nLines = 0;
3075 if( ! nLines )
3077 char* pEnv = getenv( "SAL_WHEELLINES" );
3078 nLines = pEnv ? atoi( pEnv ) : 3;
3079 if( nLines > 10 )
3080 nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
3083 SalWheelMouseEvent aWheelEvt;
3084 aWheelEvt.mnTime = pEvent->xbutton.time;
3085 aWheelEvt.mnX = pEvent->xbutton.x;
3086 aWheelEvt.mnY = pEvent->xbutton.y;
3087 aWheelEvt.mnDelta = bIncrement ? 120 : -120;
3088 aWheelEvt.mnNotchDelta = bIncrement ? 1 : -1;
3089 aWheelEvt.mnScrollLines = nLines;
3090 aWheelEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
3091 aWheelEvt.mbHorz = bHoriz;
3093 nEvent = SALEVENT_WHEELMOUSE;
3095 // --- RTL --- (mirror mouse pos)
3096 if( Application::GetSettings().GetLayoutRTL() )
3097 aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX;
3098 return CallCallback( nEvent, &aWheelEvt );
3102 int nRet = 0;
3103 if( nEvent == SALEVENT_MOUSELEAVE
3104 || ( aMouseEvt.mnX < nWidth_ && aMouseEvt.mnX > -1 &&
3105 aMouseEvt.mnY < nHeight_ && aMouseEvt.mnY > -1 )
3106 || pDisplay_->MouseCaptured( this )
3109 // --- RTL --- (mirror mouse pos)
3110 if( Application::GetSettings().GetLayoutRTL() )
3111 aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX;
3112 nRet = CallCallback( nEvent, &aMouseEvt );
3115 if( bClosePopups )
3117 /* #108213# close popups after dispatching the event outside the popup;
3118 * applications do weird things.
3120 ImplSVData* pSVData = ImplGetSVData();
3121 if ( pSVData->maWinData.mpFirstFloat )
3123 static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
3124 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) )
3125 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
3129 return nRet;
3132 // F10 means either KEY_F10 or KEY_MENU, which has to be decided
3133 // in the independent part.
3134 struct KeyAlternate
3136 USHORT nKeyCode;
3137 sal_Unicode nCharCode;
3138 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
3139 KeyAlternate( USHORT nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
3142 inline KeyAlternate
3143 GetAlternateKeyCode( const USHORT nKeyCode )
3145 KeyAlternate aAlternate;
3147 switch( nKeyCode )
3149 case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
3150 case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
3153 return aAlternate;
3156 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3157 long X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent )
3159 KeySym nKeySym;
3160 KeySym nUnmodifiedKeySym;
3161 int nLen = 2048;
3162 unsigned char *pPrintable = (unsigned char*)alloca( nLen );
3164 // singlebyte code composed by input method, the new default
3165 if (mpInputContext != NULL && mpInputContext->UseContext())
3167 // returns a keysym as well as the pPrintable (in system encoding)
3168 // printable may be empty.
3169 Status nStatus;
3170 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3171 &nUnmodifiedKeySym,
3172 &nStatus, mpInputContext->GetContext() );
3173 if ( nStatus == XBufferOverflow )
3175 nLen *= 2;
3176 pPrintable = (unsigned char*)alloca( nLen );
3177 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3178 &nUnmodifiedKeySym,
3179 &nStatus, mpInputContext->GetContext() );
3182 else
3184 // fallback, this should never ever be called
3185 Status nStatus = 0;
3186 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus );
3189 SalKeyEvent aKeyEvt;
3190 USHORT nKeyCode;
3191 USHORT nModCode = 0;
3192 char aDummy;
3194 if( pEvent->state & ShiftMask )
3195 nModCode |= KEY_SHIFT;
3196 if( pEvent->state & ControlMask )
3197 nModCode |= KEY_MOD1;
3198 if( pEvent->state & Mod1Mask )
3199 nModCode |= KEY_MOD2;
3201 if( nKeySym == XK_Shift_L || nKeySym == XK_Shift_R
3202 || nKeySym == XK_Control_L || nKeySym == XK_Control_R
3203 || nKeySym == XK_Alt_L || nKeySym == XK_Alt_R
3204 || nKeySym == XK_Meta_L || nKeySym == XK_Meta_R
3205 || nKeySym == XK_Super_L || nKeySym == XK_Super_R )
3207 SalKeyModEvent aModEvt;
3208 aModEvt.mnModKeyCode = 0;
3209 if( pEvent->type == XLIB_KeyPress && mnExtKeyMod == 0 )
3210 mbSendExtKeyModChange = true;
3211 else if( pEvent->type == KeyRelease && mbSendExtKeyModChange )
3213 aModEvt.mnModKeyCode = mnExtKeyMod;
3214 mnExtKeyMod = 0;
3217 // pressing just the ctrl key leads to a keysym of XK_Control but
3218 // the event state does not contain ControlMask. In the release
3219 // event its the other way round: it does contain the Control mask.
3220 // The modifier mode therefore has to be adapted manually.
3221 USHORT nExtModMask = 0;
3222 USHORT nModMask = 0;
3223 switch( nKeySym )
3225 case XK_Control_L:
3226 nExtModMask = MODKEY_LMOD1;
3227 nModMask = KEY_MOD1;
3228 break;
3229 case XK_Control_R:
3230 nExtModMask = MODKEY_RMOD1;
3231 nModMask = KEY_MOD1;
3232 break;
3233 case XK_Alt_L:
3234 nExtModMask = MODKEY_LMOD2;
3235 nModMask = KEY_MOD2;
3236 break;
3237 case XK_Alt_R:
3238 nExtModMask = MODKEY_RMOD2;
3239 nModMask = KEY_MOD2;
3240 break;
3241 case XK_Shift_L:
3242 nExtModMask = MODKEY_LSHIFT;
3243 nModMask = KEY_SHIFT;
3244 break;
3245 case XK_Shift_R:
3246 nExtModMask = MODKEY_RSHIFT;
3247 nModMask = KEY_SHIFT;
3248 break;
3249 // Map Meta/Super keys to MOD3 modifier on all Unix systems
3250 // except Mac OS X
3251 case XK_Meta_L:
3252 case XK_Super_L:
3253 nExtModMask = MODKEY_LMOD3;
3254 nModMask = KEY_MOD3;
3255 break;
3256 case XK_Meta_R:
3257 case XK_Super_R:
3258 nExtModMask = MODKEY_RMOD3;
3259 nModMask = KEY_MOD3;
3260 break;
3262 if( pEvent->type == KeyRelease )
3264 nModCode &= ~nModMask;
3265 mnExtKeyMod &= ~nExtModMask;
3267 else
3269 nModCode |= nModMask;
3270 mnExtKeyMod |= nExtModMask;
3273 aModEvt.mnCode = nModCode;
3274 aModEvt.mnTime = pEvent->time;
3276 int nRet = CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3278 // emulate KEY_MENU
3279 if ( ( (nKeySym == XK_Alt_L) || (nKeySym == XK_Alt_R) ) &&
3280 ( (nModCode & ~(KEY_MOD3|KEY_MOD2)) == 0 ) )
3282 if( pEvent->type == XLIB_KeyPress )
3283 mbKeyMenu = true;
3284 else if( mbKeyMenu )
3286 // simulate KEY_MENU
3287 aKeyEvt.mnCode = KEY_MENU | nModCode;
3288 aKeyEvt.mnRepeat = 0;
3289 aKeyEvt.mnTime = pEvent->time;
3290 aKeyEvt.mnCharCode = 0;
3291 nRet = CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3292 nRet = CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3295 else
3296 mbKeyMenu = false;
3297 return nRet;
3300 mbSendExtKeyModChange = mbKeyMenu = false;
3302 // try to figure out the vcl code for the keysym
3303 // #i52338# use the unmodified KeySym if there is none for the real KeySym
3304 // because the independent part has only keycodes for unshifted keys
3305 nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy );
3306 if( nKeyCode == 0 )
3307 nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
3309 // try to figure out a printable if XmbLookupString returns only a keysym
3310 // and NOT a printable. Do not store it in pPrintable[0] since it is expected to
3311 // be in system encoding, not unicode.
3312 // #i8988##, if KeySym and printable look equally promising then prefer KeySym
3313 // the printable is bound to the encoding so the KeySym might contain more
3314 // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and
3315 // (the desired) Zcaron in KeySym
3316 sal_Unicode nKeyString = 0x0;
3317 if ( (nLen == 0)
3318 || ((nLen == 1) && (nKeySym > 0)) )
3319 nKeyString = KeysymToUnicode (nKeySym);
3320 // if we have nothing we give up
3321 if( !nKeyCode && !nLen && !nKeyString)
3322 return 0;
3324 rtl_TextEncoding nEncoding;
3326 if (mpInputContext != NULL && mpInputContext->IsMultiLingual() )
3327 nEncoding = RTL_TEXTENCODING_UTF8;
3328 else
3329 nEncoding = osl_getThreadTextEncoding();
3331 sal_Unicode *pBuffer;
3332 sal_Unicode *pString;
3333 sal_Size nBufferSize = nLen * 2;
3334 sal_Size nSize;
3335 pBuffer = (sal_Unicode*) malloc( nBufferSize + 2 );
3336 pBuffer[ 0 ] = 0;
3338 if (nKeyString != 0)
3340 pString = &nKeyString;
3341 nSize = 1;
3343 else
3344 if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE)
3346 // create text converter
3347 rtl_TextToUnicodeConverter aConverter =
3348 rtl_createTextToUnicodeConverter( nEncoding );
3349 rtl_TextToUnicodeContext aContext =
3350 rtl_createTextToUnicodeContext( aConverter );
3352 sal_uInt32 nConversionInfo;
3353 sal_Size nConvertedChars;
3355 // convert to single byte text stream
3356 nSize = rtl_convertTextToUnicode(
3357 aConverter, aContext,
3358 (char*)pPrintable, nLen,
3359 pBuffer, nBufferSize,
3360 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
3361 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE,
3362 &nConversionInfo, &nConvertedChars );
3364 // destroy converter
3365 rtl_destroyTextToUnicodeContext( aConverter, aContext );
3366 rtl_destroyTextToUnicodeConverter( aConverter );
3368 pString = pBuffer;
3370 else
3371 if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */)
3373 pString = (sal_Unicode*)pPrintable;
3374 nSize = nLen;
3376 else
3378 pString = pBuffer;
3379 nSize = 0;
3382 DeletionListener aDeleteWatch( this );
3384 if ( mpInputContext != NULL
3385 && mpInputContext->UseContext()
3386 && KeyRelease != pEvent->type
3387 && ( (nSize > 1)
3388 || (nSize > 0 && mpInputContext->IsPreeditMode())) )
3390 mpInputContext->CommitKeyEvent(pString, nSize);
3392 else
3393 // normal single character keyinput
3395 aKeyEvt.mnCode = nKeyCode | nModCode;
3396 aKeyEvt.mnRepeat = 0;
3397 aKeyEvt.mnTime = pEvent->time;
3398 aKeyEvt.mnCharCode = pString[ 0 ];
3400 if( KeyRelease == pEvent->type )
3402 CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3404 else
3406 if ( ! CallCallback(SALEVENT_KEYINPUT, &aKeyEvt) )
3408 // independent layer doesnt want to handle key-event, so check
3409 // whether the keycode may have an alternate meaning
3410 KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode );
3411 if ( aAlternate.nKeyCode != 0 )
3413 aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode;
3414 if( aAlternate.nCharCode )
3415 aKeyEvt.mnCharCode = aAlternate.nCharCode;
3416 CallCallback(SALEVENT_KEYINPUT, &aKeyEvt);
3423 // update the spot location for PreeditPosition IME style
3425 if (! aDeleteWatch.isDeleted())
3427 if (mpInputContext != NULL && mpInputContext->UseContext())
3428 mpInputContext->UpdateSpotLocation();
3431 free (pBuffer);
3432 return True;
3436 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3437 long X11SalFrame::HandleFocusEvent( XFocusChangeEvent *pEvent )
3439 // #107739# ReflectionX in Windows mode changes focus while mouse is grabbed
3440 if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "ReflectionX Windows" ) )
3441 return 1;
3443 /* #55691# ignore focusout resulting from keyboard grabs
3444 * we do not grab it and are not interested when
3445 * someone else does CDE e.g. does a XGrabKey on arrow keys
3446 * #73179# handle focus events with mode NotifyWhileGrabbed
3447 * because with CDE alt-tab focus changing we do not get
3448 * normal focus events
3449 * #71791# cast focus event to the input context, otherwise the
3450 * status window does not follow the application frame
3453 if ( mpInputContext != NULL )
3455 if( FocusIn == pEvent->type )
3456 mpInputContext->SetICFocus( this );
3457 else
3460 * do not unset the IC focuse here because would kill
3461 * a lookup choice windows that might have the focus now
3462 * mpInputContext->UnsetICFocus( this );
3464 I18NStatus::get().show( false, I18NStatus::focus );
3469 if ( pEvent->mode == NotifyNormal || pEvent->mode == NotifyWhileGrabbed ||
3470 ( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
3473 if( hPresentationWindow != None && hPresentationWindow != GetShellWindow() )
3474 return 0;
3476 if( FocusIn == pEvent->type )
3478 #ifndef _USE_PRINT_EXTENSION_
3479 vcl_sal::PrinterUpdate::update();
3480 #endif
3481 mbInputFocus = True;
3482 ImplSVData* pSVData = ImplGetSVData();
3486 long nRet = CallCallback( SALEVENT_GETFOCUS, 0 );
3487 if ((mpParent != NULL && nStyle_ == 0)
3488 && pSVData->maWinData.mpFirstFloat )
3490 ULONG nMode = pSVData->maWinData.mpFirstFloat->GetPopupModeFlags();
3491 pSVData->maWinData.mpFirstFloat->SetPopupModeFlags(
3492 nMode & ~(FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE));
3494 return nRet;
3496 else
3498 mbInputFocus = False;
3499 mbSendExtKeyModChange = mbKeyMenu = false;
3500 mnExtKeyMod = 0;
3501 return CallCallback( SALEVENT_LOSEFOCUS, 0 );
3505 return 0;
3508 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3510 long X11SalFrame::HandleExposeEvent( XEvent *pEvent )
3512 XRectangle aRect = { 0, 0, 0, 0 };
3513 USHORT nCount = 0;
3515 if( pEvent->type == Expose )
3517 aRect.x = pEvent->xexpose.x;
3518 aRect.y = pEvent->xexpose.y;
3519 aRect.width = pEvent->xexpose.width;
3520 aRect.height = pEvent->xexpose.height;
3521 nCount = pEvent->xexpose.count;
3523 else if( pEvent->type == GraphicsExpose )
3525 aRect.x = pEvent->xgraphicsexpose.x;
3526 aRect.y = pEvent->xgraphicsexpose.y;
3527 aRect.width = pEvent->xgraphicsexpose.width;
3528 aRect.height = pEvent->xgraphicsexpose.height;
3529 nCount = pEvent->xgraphicsexpose.count;
3532 if( IsOverrideRedirect() && mbFullScreen &&
3533 aPresentationReparentList.begin() == aPresentationReparentList.end() )
3534 // we are in fullscreen mode -> override redirect
3535 // focus is possibly lost, so reget it
3536 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone, CurrentTime );
3538 // width and height are extents, so they are of by one for rectangle
3539 maPaintRegion.Union( Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) );
3541 if( nCount )
3542 // wait for last expose rectangle, do not wait for resize timer
3543 // if a completed graphics expose sequence is available
3544 return 1;
3546 SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() );
3548 CallCallback( SALEVENT_PAINT, &aPEvt );
3549 maPaintRegion = Rectangle();
3551 return 1;
3554 void X11SalFrame::RestackChildren( XLIB_Window* pTopLevelWindows, int nTopLevelWindows )
3556 if( maChildren.begin() != maChildren.end() )
3558 int nWindow = nTopLevelWindows;
3559 while( nWindow-- )
3560 if( pTopLevelWindows[nWindow] == GetStackingWindow() )
3561 break;
3562 if( nWindow < 0 )
3563 return;
3565 std::list< X11SalFrame* >::const_iterator it;
3566 for( it = maChildren.begin(); it != maChildren.end(); ++it )
3568 X11SalFrame* pData = *it;
3569 if( pData->bMapped_ )
3571 int nChild = nWindow;
3572 while( nChild-- )
3574 if( pTopLevelWindows[nChild] == pData->GetStackingWindow() )
3576 // if a child is behind its parent, place it above the
3577 // parent (for insane WMs like Dtwm and olwm)
3578 XWindowChanges aCfg;
3579 aCfg.sibling = GetStackingWindow();
3580 aCfg.stack_mode = Above;
3581 XConfigureWindow( GetXDisplay(), pData->GetStackingWindow(), CWSibling|CWStackMode, &aCfg );
3582 break;
3587 for( it = maChildren.begin(); it != maChildren.end(); ++it )
3589 X11SalFrame* pData = *it;
3590 pData->RestackChildren( pTopLevelWindows, nTopLevelWindows );
3595 void X11SalFrame::RestackChildren()
3597 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected()
3598 && maChildren.begin() != maChildren.end() )
3600 XLIB_Window aRoot, aParent, *pChildren = NULL;
3601 unsigned int nChildren;
3602 if( XQueryTree( GetXDisplay(),
3603 GetDisplay()->GetRootWindow( m_nScreen ),
3604 &aRoot,
3605 &aParent,
3606 &pChildren,
3607 &nChildren ) )
3609 RestackChildren( pChildren, nChildren );
3610 XFree( pChildren );
3615 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3616 long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
3618 if ( pEvent->window != GetShellWindow()
3619 && pEvent->window != GetWindow()
3620 && pEvent->window != GetForeignParent()
3621 && pEvent->window != GetStackingWindow()
3624 // could be as well a sys-child window (aka SalObject)
3625 return 1;
3629 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
3631 // just update the children's positions
3632 RestackChildren();
3633 return 1;
3636 if( pEvent->window == GetForeignParent() )
3637 XResizeWindow( GetXDisplay(),
3638 GetWindow(),
3639 pEvent->width,
3640 pEvent->height );
3642 XLIB_Window hDummy;
3643 XTranslateCoordinates( GetXDisplay(),
3644 GetWindow(),
3645 pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ),
3646 0, 0,
3647 &pEvent->x, &pEvent->y,
3648 &hDummy );
3650 if( pEvent->window == GetStackingWindow() )
3652 if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y )
3654 maGeometry.nX = pEvent->x;
3655 maGeometry.nY = pEvent->y;
3656 CallCallback( SALEVENT_MOVE, NULL );
3658 return 1;
3661 // check size hints in first time SalFrame::Show
3662 if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ )
3663 nShowState_ = SHOWSTATE_NORMAL;
3665 nWidth_ = pEvent->width;
3666 nHeight_ = pEvent->height;
3668 bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY );
3669 bool bSized = ( pEvent->width != (int)maGeometry.nWidth || pEvent->height != (int)maGeometry.nHeight );
3671 maGeometry.nX = pEvent->x;
3672 maGeometry.nY = pEvent->y;
3673 maGeometry.nWidth = pEvent->width;
3674 maGeometry.nHeight = pEvent->height;
3675 updateScreenNumber();
3677 // update children's position
3678 RestackChildren();
3680 if( bSized && ! bMoved )
3681 CallCallback( SALEVENT_RESIZE, NULL );
3682 else if( bMoved && ! bSized )
3683 CallCallback( SALEVENT_MOVE, NULL );
3684 else if( bMoved && bSized )
3685 CallCallback( SALEVENT_MOVERESIZE, NULL );
3687 return 1;
3690 IMPL_LINK( X11SalFrame, HandleAlwaysOnTopRaise, void*, EMPTYARG )
3692 if( bMapped_ )
3693 ToTop( 0 );
3694 return 0;
3697 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3698 long X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent )
3700 Display *pDisplay = pEvent->display;
3701 XLIB_Window hWM_Parent;
3702 XLIB_Window hRoot, *Children, hDummy;
3703 unsigned int nChildren;
3704 BOOL bNone = pDisplay_->GetProperties()
3705 & PROPERTY_SUPPORT_WM_Parent_Pixmap_None;
3706 BOOL bAccessParentWindow = ! (pDisplay_->GetProperties()
3707 & PROPERTY_FEATURE_TrustedSolaris);
3709 static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" );
3711 GetDisplay()->GetXLib()->PushXErrorLevel( true );
3714 * #89186# don't rely on the new parent from the event.
3715 * the event may be "out of date", that is the window manager
3716 * window may not exist anymore. This can happen if someone
3717 * shows a frame and hides it again quickly (not that that would
3718 * be very sensible)
3720 hWM_Parent = GetShellWindow();
3723 Children = NULL;
3724 XQueryTree( pDisplay,
3725 hWM_Parent,
3726 &hRoot,
3727 &hDummy,
3728 &Children,
3729 &nChildren );
3730 if( GetDisplay()->GetXLib()->HasXErrorOccured() )
3732 hWM_Parent = GetShellWindow();
3733 break;
3735 /* #107048# this sometimes happens if a Show(TRUE) is
3736 * immediately followed by Show(FALSE) (which is braindead anyway)
3738 if( hDummy == hWM_Parent )
3739 hDummy = hRoot;
3740 if( hDummy != hRoot )
3742 hWM_Parent = hDummy;
3743 if( bAccessParentWindow && bNone )
3744 XSetWindowBackgroundPixmap( pDisplay, hWM_Parent, None );
3746 if( Children )
3747 XFree( Children );
3748 } while( hDummy != hRoot );
3750 if( GetStackingWindow() == None
3751 && hWM_Parent != hPresentationWindow
3752 && hWM_Parent != GetShellWindow()
3753 && ( ! pDisableStackingCheck || ! *pDisableStackingCheck )
3756 mhStackingWindow = hWM_Parent;
3757 if (bAccessParentWindow)
3758 XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask );
3761 if( hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() )
3762 || hWM_Parent == GetForeignParent()
3763 || pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() )
3764 || ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) )
3766 // Reparenting before Destroy
3767 aPresentationReparentList.remove( GetStackingWindow() );
3768 mhStackingWindow = None;
3769 GetDisplay()->GetXLib()->PopXErrorLevel();
3770 return 0;
3774 * evil hack to show decorated windows on top
3775 * of override redirect presentation windows:
3776 * reparent the window manager window to the presentation window
3777 * does not work with non-reparenting WMs
3778 * in future this should not be necessary anymore with
3779 * _NET_WM_STATE_FULLSCREEN available
3781 if( hPresentationWindow != None
3782 && hPresentationWindow != GetWindow()
3783 && GetStackingWindow() != None
3784 && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nScreen )
3787 int x = 0, y = 0;
3788 XLIB_Window aChild;
3789 XTranslateCoordinates( GetXDisplay(),
3790 GetStackingWindow(),
3791 GetDisplay()->GetRootWindow( m_nScreen ),
3792 0, 0,
3793 &x, &y,
3794 &aChild
3796 XReparentWindow( GetXDisplay(),
3797 GetStackingWindow(),
3798 hPresentationWindow,
3799 x, y
3801 aPresentationReparentList.push_back( GetStackingWindow() );
3804 int nLeft = 0, nTop = 0;
3805 XTranslateCoordinates( GetXDisplay(),
3806 GetShellWindow(),
3807 hWM_Parent,
3808 0, 0,
3809 &nLeft,
3810 &nTop,
3811 &hDummy );
3812 maGeometry.nLeftDecoration = nLeft > 0 ? nLeft-1 : 0;
3813 maGeometry.nTopDecoration = nTop > 0 ? nTop-1 : 0;
3816 * decorations are not symmetric,
3817 * so need real geometries here
3818 * (this will fail with virtual roots ?)
3820 GetDisplay()->GetXLib()->ResetXErrorOccured();
3821 int xp, yp, x, y;
3822 unsigned int wp, w, hp, h, bw, d;
3823 XGetGeometry( GetXDisplay(),
3824 GetShellWindow(),
3825 &hRoot,
3826 &x, &y, &w, &h, &bw, &d );
3827 XGetGeometry( GetXDisplay(),
3828 hWM_Parent,
3829 &hRoot,
3830 &xp, &yp, &wp, &hp, &bw, &d );
3831 bool bResized = false;
3832 if( ! GetDisplay()->GetXLib()->HasXErrorOccured() )
3834 maGeometry.nRightDecoration = wp - w - maGeometry.nLeftDecoration;
3835 maGeometry.nBottomDecoration = hp - h - maGeometry.nTopDecoration;
3837 * note: this works because hWM_Parent is direct child of root,
3838 * not necessarily parent of GetShellWindow()
3840 maGeometry.nX = xp + nLeft;
3841 maGeometry.nY = yp + nTop;
3842 bResized = w != maGeometry.nWidth || h != maGeometry.nHeight;
3843 maGeometry.nWidth = w;
3844 maGeometry.nHeight = h;
3848 // limit width and height if we are too large: #47757
3849 // olwm and fvwm need this, it doesnt harm the rest
3851 // #i81311# do this only for sizable frames
3852 if( (nStyle_ & SAL_FRAME_STYLE_SIZEABLE) != 0 )
3854 Size aScreenSize = GetDisplay()->GetScreenSize( m_nScreen );
3855 int nScreenWidth = aScreenSize.Width();
3856 int nScreenHeight = aScreenSize.Height();
3857 int nFrameWidth = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
3858 int nFrameHeight = maGeometry.nHeight + maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
3860 if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight))
3862 Size aSize(maGeometry.nWidth, maGeometry.nHeight);
3864 if (nFrameWidth > nScreenWidth)
3865 aSize.Width() = nScreenWidth - maGeometry.nRightDecoration - maGeometry.nLeftDecoration;
3866 if (nFrameHeight > nScreenHeight)
3867 aSize.Height() = nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration;
3869 SetSize( aSize );
3870 bResized = false;
3873 if( bResized )
3874 CallCallback( SALEVENT_RESIZE, NULL );
3876 GetDisplay()->GetXLib()->PopXErrorLevel();
3878 return 1;
3881 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3882 long X11SalFrame::HandleColormapEvent( XColormapEvent* )
3884 return 0;
3887 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3888 long X11SalFrame::HandleStateEvent( XPropertyEvent *pEvent )
3890 Atom actual_type;
3891 int actual_format;
3892 unsigned long nitems, bytes_after;
3893 unsigned char *prop = NULL;
3895 if( 0 != XGetWindowProperty( GetXDisplay(),
3896 GetShellWindow(),
3897 pEvent->atom, // property
3898 0, // long_offset (32bit)
3899 2, // long_length (32bit)
3900 False, // delete
3901 pEvent->atom, // req_type
3902 &actual_type,
3903 &actual_format,
3904 &nitems,
3905 &bytes_after,
3906 &prop )
3907 || ! prop
3909 return 0;
3911 DBG_ASSERT( actual_type = pEvent->atom
3912 && 32 == actual_format
3913 && 2 == nitems
3914 && 0 == bytes_after, "HandleStateEvent" );
3916 if( *(unsigned long*)prop == NormalState )
3917 nShowState_ = SHOWSTATE_NORMAL;
3918 else if( *(unsigned long*)prop == IconicState )
3919 nShowState_ = SHOWSTATE_MINIMIZED;
3921 XFree( prop );
3922 return 1;
3925 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3926 long X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent )
3928 const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() );
3930 #if !defined(__synchronous_extinput__)
3931 if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) )
3933 HandleExtTextEvent (pEvent);
3934 return 1;
3936 #endif
3937 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) )
3939 stderr0( "X11SalFrame::Dispatch Quit\n" );
3940 Close(); // ???
3941 return 1;
3943 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS )
3944 && ! ( nStyle_ & SAL_FRAME_STYLE_PLUG )
3945 && ! (( nStyle_ & SAL_FRAME_STYLE_FLOAT ) && (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION))
3948 if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) )
3950 Close();
3951 return 1;
3953 else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) )
3955 // do nothing, we set the input focus in ToTop() if necessary
3956 #if OSL_DEBUG_LEVEL > 1
3957 fprintf( stderr, "got WM_TAKE_FOCUS on %s window\n",
3958 (nStyle_&SAL_FRAME_STYLE_OWNERDRAWDECORATION) ?
3959 "ownerdraw" : "NON OWNERDRAW" );
3960 #endif
3962 else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_SAVE_YOURSELF ) )
3964 bool bSession = rWMAdaptor.getWindowManagerName().EqualsAscii( "Dtwm" );
3966 if( ! bSession )
3968 if( this == s_pSaveYourselfFrame )
3970 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
3971 const char* argv[2];
3972 argv[0] = "/bin/sh";
3973 argv[1] = const_cast<char*>(aExec.GetBuffer());
3974 #if OSL_DEBUG_LEVEL > 1
3975 fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] );
3976 #endif
3977 XSetCommand( GetXDisplay(), GetShellWindow(), (char**)argv, 2 );
3979 else
3980 // can only happen in race between WM and window closing
3981 XChangeProperty( GetXDisplay(), GetShellWindow(), rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 );
3983 else
3985 // save open documents; would be good for non Dtwm, too,
3986 // but there is no real Shutdown message in the ancient
3987 // SM protocol; on Dtwm SaveYourself really means Shutdown, too.
3988 IceSalSession::handleOldX11SaveYourself( this );
3992 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) &&
3993 pEvent->window == GetWindow() )
3995 if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
3996 pEvent->data.l[1] == 2 ) // XEMBED_WINDOW_DEACTIVATE
3998 XFocusChangeEvent aEvent;
3999 aEvent.type = (pEvent->data.l[1] == 1 ? FocusIn : FocusOut);
4000 aEvent.serial = pEvent->serial;
4001 aEvent.send_event = True;
4002 aEvent.display = pEvent->display;
4003 aEvent.window = pEvent->window;
4004 aEvent.mode = NotifyNormal;
4005 aEvent.detail = NotifyDetailNone;
4006 HandleFocusEvent( &aEvent );
4009 return 0;
4012 void X11SalFrame::SaveYourselfDone( SalFrame* pSaveFrame )
4014 // session save was done, inform dtwm
4015 if( s_pSaveYourselfFrame && pSaveFrame )
4017 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
4018 const char* argv[2];
4019 argv[0] = "/bin/sh";
4020 argv[1] = const_cast<char*>(aExec.GetBuffer());
4021 #if OSL_DEBUG_LEVEL > 1
4022 fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] );
4023 #endif
4024 XSetCommand( s_pSaveYourselfFrame->GetXDisplay(),
4025 s_pSaveYourselfFrame->GetShellWindow(),
4026 (char**)argv, 2 );
4027 if( pSaveFrame != s_pSaveYourselfFrame )
4029 // check if it still exists
4030 const X11SalFrame* pFrame = NULL;
4031 const std::list< SalFrame* >& rFrames = static_cast<X11SalFrame*>(pSaveFrame)->GetDisplay()->getFrames();
4032 std::list< SalFrame* >::const_iterator it = rFrames.begin();
4033 while( it != rFrames.end() )
4035 pFrame = static_cast< const X11SalFrame* >(*it);
4036 if( pFrame == pSaveFrame )
4037 break;
4038 ++it;
4040 if( pFrame == pSaveFrame )
4042 const WMAdaptor& rWMAdaptor( *pFrame->pDisplay_->getWMAdaptor() );
4043 XChangeProperty( pFrame->GetXDisplay(),
4044 pFrame->GetShellWindow(),
4045 rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 );
4048 s_pSaveYourselfFrame->ShutDown();
4052 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
4054 extern "C"
4056 Bool call_checkKeyReleaseForRepeat( Display* pDisplay, XEvent* pCheck, XPointer pX11SalFrame )
4058 return X11SalFrame::checkKeyReleaseForRepeat( pDisplay, pCheck, pX11SalFrame );
4062 Bool X11SalFrame::checkKeyReleaseForRepeat( Display*, XEvent* pCheck, XPointer pX11SalFrame )
4064 X11SalFrame* pThis = (X11SalFrame*)pX11SalFrame;
4065 return
4066 pCheck->type == XLIB_KeyPress &&
4067 pCheck->xkey.state == pThis->nKeyState_ &&
4068 pCheck->xkey.keycode == pThis->nKeyCode_ &&
4069 pCheck->xkey.time == pThis->nReleaseTime_ ? True : False;
4072 long X11SalFrame::Dispatch( XEvent *pEvent )
4074 long nRet = 0;
4076 if( -1 == nCaptured_ )
4078 CaptureMouse( TRUE );
4079 #ifdef DBG_UTIL
4080 if( -1 != nCaptured_ )
4081 pDisplay_->PrintEvent( "Captured", pEvent );
4082 #endif
4085 if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() )
4087 switch( pEvent->type )
4089 case XLIB_KeyPress:
4090 nKeyCode_ = pEvent->xkey.keycode;
4091 nKeyState_ = pEvent->xkey.state;
4092 nRet = HandleKeyEvent( &pEvent->xkey );
4093 break;
4095 case KeyRelease:
4096 if( -1 == nCompose_ )
4098 nReleaseTime_ = pEvent->xkey.time;
4099 XEvent aEvent;
4100 if( XCheckIfEvent( pEvent->xkey.display, &aEvent, call_checkKeyReleaseForRepeat, (XPointer)this ) )
4101 XPutBackEvent( pEvent->xkey.display, &aEvent );
4102 else
4103 nRet = HandleKeyEvent( &pEvent->xkey );
4105 break;
4107 case ButtonPress:
4108 // #74406# if we loose the focus in presentation mode
4109 // there are good chances that we never get it back
4110 // since the WM ignores us
4111 if( IsOverrideRedirect() )
4113 XSetInputFocus( GetXDisplay(), GetShellWindow(),
4114 RevertToNone, CurrentTime );
4117 case ButtonRelease:
4118 case MotionNotify:
4119 case EnterNotify:
4120 case LeaveNotify:
4121 nRet = HandleMouseEvent( pEvent );
4122 break;
4124 case FocusIn:
4125 case FocusOut:
4126 nRet = HandleFocusEvent( &pEvent->xfocus );
4127 break;
4129 case Expose:
4130 case GraphicsExpose:
4131 nRet = HandleExposeEvent( pEvent );
4132 break;
4134 case MapNotify:
4135 if( pEvent->xmap.window == GetShellWindow() )
4137 if( nShowState_ == SHOWSTATE_HIDDEN )
4140 * #95097# workaround for (at least) KWin 2.2.2
4141 * which will map windows that were once transient
4142 * even if they are withdrawn when the respective
4143 * document is mapped.
4145 if( ! (nStyle_ & SAL_FRAME_STYLE_PLUG) )
4146 XUnmapWindow( GetXDisplay(), GetShellWindow() );
4147 break;
4149 bMapped_ = TRUE;
4150 bViewable_ = TRUE;
4151 nRet = TRUE;
4152 if ( mpInputContext != NULL )
4153 mpInputContext->Map( this );
4154 CallCallback( SALEVENT_RESIZE, NULL );
4155 if( pDisplay_->GetServerVendor() == vendor_hummingbird )
4158 * With Exceed sometimes there does not seem to be
4159 * an Expose after the MapNotify.
4160 * so start a delayed paint here
4162 maPaintRegion.Union( Rectangle( Point( 0, 0 ), Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
4163 XEvent aEvent;
4164 aEvent.xexpose.type = Expose;
4165 aEvent.xexpose.display = pDisplay_->GetDisplay();
4166 aEvent.xexpose.x = 0;
4167 aEvent.xexpose.y = 0;
4168 aEvent.xexpose.width = maGeometry.nWidth;
4169 aEvent.xexpose.height = maGeometry.nHeight;
4170 aEvent.xexpose.count = 0;
4171 XSendEvent( pDisplay_->GetDisplay(),
4172 GetWindow(),
4173 True,
4174 ExposureMask,
4175 &aEvent );
4178 /* #99570# another workaround for sawfish: if a transient window for the same parent is shown
4179 * sawfish does not set the focus to it. Applies only for click to focus mode.
4181 if( ! (nStyle_ & SAL_FRAME_STYLE_FLOAT ) && mbInShow && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Sawfish" ) )
4183 // #101775# don't set the focus into the IME status window
4184 // since this will lead to a parent loose-focus, close status,
4185 // reget focus, open status, .... flicker loop
4186 if ( (I18NStatus::get().getStatusFrame() != this) )
4187 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime );
4191 * sometimes a message box/dialogue is brought up when a frame is not mapped
4192 * the corresponding TRANSIENT_FOR hint is then set to the root window
4193 * so that the dialogue shows in all cases. Correct it here if the
4194 * frame is shown afterwards.
4196 if( ! IsChildWindow()
4197 && ! IsOverrideRedirect()
4198 && ! IsFloatGrabWindow()
4201 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
4202 it != maChildren.end(); ++it )
4204 if( (*it)->mbTransientForRoot )
4205 pDisplay_->getWMAdaptor()->changeReferenceFrame( *it, this );
4209 if( hPresentationWindow != None && GetShellWindow() == hPresentationWindow )
4210 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime );
4211 /* For unknown reasons Dtwm does respect the input_hint
4212 * set to False, but not when mapping the window. So
4213 * emulate the correct behaviour and set the focus back
4214 * to where it most probably should have been.
4216 if( (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) &&
4217 mpParent &&
4218 GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Dtwm" )
4221 XSetInputFocus( GetXDisplay(),
4222 mpParent->GetShellWindow(),
4223 RevertToParent,
4224 CurrentTime );
4227 RestackChildren();
4228 mbInShow = FALSE;
4230 break;
4232 case UnmapNotify:
4233 if( pEvent->xunmap.window == GetShellWindow() )
4235 bMapped_ = FALSE;
4236 bViewable_ = FALSE;
4237 nRet = TRUE;
4238 if ( mpInputContext != NULL )
4239 mpInputContext->Unmap( this );
4240 CallCallback( SALEVENT_RESIZE, NULL );
4242 break;
4244 case ConfigureNotify:
4245 if( pEvent->xconfigure.window == GetShellWindow()
4246 || pEvent->xconfigure.window == GetWindow() )
4247 nRet = HandleSizeEvent( &pEvent->xconfigure );
4248 break;
4250 case VisibilityNotify:
4251 nVisibility_ = pEvent->xvisibility.state;
4252 nRet = TRUE;
4253 if( bAlwaysOnTop_
4254 && bMapped_
4255 && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK()
4256 && nVisibility_ != VisibilityUnobscured )
4257 maAlwaysOnTopRaiseTimer.Start();
4258 break;
4260 case ReparentNotify:
4261 nRet = HandleReparentEvent( &pEvent->xreparent );
4262 break;
4264 case MappingNotify:
4265 if( MappingPointer != pEvent->xmapping.request )
4266 nRet = CallCallback( SALEVENT_KEYBOARDCHANGED, 0 );
4267 break;
4269 case ColormapNotify:
4270 nRet = HandleColormapEvent( &pEvent->xcolormap );
4271 break;
4273 case PropertyNotify:
4275 if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) )
4276 nRet = HandleStateEvent( &pEvent->xproperty );
4277 else
4278 nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty );
4279 break;
4282 case ClientMessage:
4283 nRet = HandleClientMessage( &pEvent->xclient );
4284 break;
4287 else
4289 switch( pEvent->type )
4291 case FocusIn:
4292 case FocusOut:
4293 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG )
4294 && ( pEvent->xfocus.window == GetShellWindow()
4295 || pEvent->xfocus.window == GetForeignParent() )
4298 nRet = HandleFocusEvent( &pEvent->xfocus );
4300 break;
4302 case ConfigureNotify:
4303 if( pEvent->xconfigure.window == GetForeignParent() ||
4304 pEvent->xconfigure.window == GetShellWindow() )
4305 nRet = HandleSizeEvent( &pEvent->xconfigure );
4307 if( pEvent->xconfigure.window == GetStackingWindow() )
4308 nRet = HandleSizeEvent( &pEvent->xconfigure );
4310 RestackChildren();
4311 break;
4315 return nRet;
4318 void X11SalFrame::ResetClipRegion()
4320 delete [] m_pClipRectangles;
4321 m_pClipRectangles = NULL;
4322 m_nCurClipRect = m_nMaxClipRect = 0;
4324 const int dest_kind = ShapeBounding;
4325 const int op = ShapeSet;
4326 const int ordering = YSorted;
4328 XWindowAttributes win_attrib;
4329 XRectangle win_size;
4331 XLIB_Window aShapeWindow = mhShellWindow;
4333 XGetWindowAttributes ( GetDisplay()->GetDisplay(),
4334 aShapeWindow,
4335 &win_attrib );
4337 win_size.x = 0;
4338 win_size.y = 0;
4339 win_size.width = win_attrib.width;
4340 win_size.height = win_attrib.height;
4342 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4343 aShapeWindow,
4344 dest_kind,
4345 0, 0, // x_off, y_off
4346 &win_size, // list of rectangles
4347 1, // number of rectangles
4348 op, ordering );
4351 void X11SalFrame::BeginSetClipRegion( ULONG nRects )
4353 if( m_pClipRectangles )
4354 delete [] m_pClipRectangles;
4355 if( nRects )
4356 m_pClipRectangles = new XRectangle[nRects];
4357 else
4358 m_pClipRectangles = NULL;
4359 m_nMaxClipRect = static_cast<int>(nRects);
4360 m_nCurClipRect = 0;
4363 void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
4365 if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect )
4367 m_pClipRectangles[m_nCurClipRect].x = nX;
4368 m_pClipRectangles[m_nCurClipRect].y = nY;
4369 m_pClipRectangles[m_nCurClipRect].width = nWidth;
4370 m_pClipRectangles[m_nCurClipRect].height = nHeight;
4371 m_nCurClipRect++;
4375 void X11SalFrame::EndSetClipRegion()
4377 const int dest_kind = ShapeBounding;
4378 const int ordering = YSorted;
4379 const int op = ShapeSet;
4381 XLIB_Window aShapeWindow = mhShellWindow;
4382 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4383 aShapeWindow,
4384 dest_kind,
4385 0, 0, // x_off, y_off
4386 m_pClipRectangles,
4387 m_nCurClipRect,
4388 op, ordering );