Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / vcl / unx / generic / window / salframe.cxx
blob55d45552d8fdafd35b572b0b5002a8b816f98726
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <signal.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
26 #include "tools/debug.hxx"
28 #include "sal/alloca.h"
30 #include "vcl/floatwin.hxx"
31 #include "vcl/svapp.hxx"
32 #include "vcl/keycodes.hxx"
33 #include "vcl/layout.hxx"
34 #include "vcl/printerinfomanager.hxx"
35 #include "vcl/settings.hxx"
36 #include "vcl/bmpacc.hxx"
38 #include <prex.h>
39 #include <X11/Xatom.h>
40 #include <X11/keysym.h>
41 #include "FWS.hxx"
42 #include <X11/extensions/shape.h>
43 #if !defined(SOLARIS) && !defined(AIX)
44 #include <X11/extensions/dpms.h>
45 #endif
46 #include <postx.h>
48 #include "unx/salunx.h"
49 #include "unx/saldata.hxx"
50 #include "unx/saldisp.hxx"
51 #include "unx/salgdi.h"
52 #include "unx/salframe.h"
53 #include "unx/sm.hxx"
54 #include "unx/wmadaptor.hxx"
55 #include "generic/genprn.h"
56 #include "unx/salbmp.h"
57 #include "unx/i18n_ic.hxx"
58 #include "unx/i18n_keysym.hxx"
59 #include "unx/i18n_status.hxx"
60 #include <unx/x11/xlimits.hxx>
62 #include "generic/gensys.h"
63 #include "sallayout.hxx"
65 #include <sal/macros.h>
66 #include <com/sun/star/uno/Exception.hpp>
68 #include "svids.hrc"
69 #include "impbmp.hxx"
71 #include <algorithm>
73 #ifndef Button6
74 # define Button6 6
75 #endif
76 #ifndef Button7
77 # define Button7 7
78 #endif
80 using namespace vcl_sal;
81 using namespace vcl;
83 #define CLIENT_EVENTS StructureNotifyMask \
84 | SubstructureNotifyMask \
85 | KeyPressMask \
86 | KeyReleaseMask \
87 | ButtonPressMask \
88 | ButtonReleaseMask \
89 | PointerMotionMask \
90 | EnterWindowMask \
91 | LeaveWindowMask \
92 | FocusChangeMask \
93 | ExposureMask \
94 | VisibilityChangeMask \
95 | PropertyChangeMask \
96 | ColormapChangeMask
98 static XLIB_Window hPresentationWindow = None, hPresFocusWindow = None;
99 static ::std::list< XLIB_Window > aPresentationReparentList;
100 static int nVisibleFloats = 0;
102 static void doReparentPresentationDialogues( SalDisplay* pDisplay )
104 GetGenericData()->ErrorTrapPush();
105 while( aPresentationReparentList.begin() != aPresentationReparentList.end() )
107 int x, y;
108 XLIB_Window aRoot, aChild;
109 unsigned int w, h, bw, d;
110 XGetGeometry( pDisplay->GetDisplay(),
111 aPresentationReparentList.front(),
112 &aRoot,
113 &x, &y, &w, &h, &bw, &d );
114 XTranslateCoordinates( pDisplay->GetDisplay(),
115 hPresentationWindow,
116 aRoot,
117 x, y,
118 &x, &y,
119 &aChild );
120 XReparentWindow( pDisplay->GetDisplay(),
121 aPresentationReparentList.front(),
122 aRoot,
123 x, y );
124 aPresentationReparentList.pop_front();
126 if( hPresFocusWindow )
127 XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot, CurrentTime );
128 XSync( pDisplay->GetDisplay(), False );
129 GetGenericData()->ErrorTrapPop();
132 bool X11SalFrame::IsOverrideRedirect() const
134 return
135 ((nStyle_ & SAL_FRAME_STYLE_INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash())
137 (!( nStyle_ & ~SAL_FRAME_STYLE_DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen())
141 bool X11SalFrame::IsFloatGrabWindow() const
143 static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" );
145 return
146 ( ( !pDisableGrab || !*pDisableGrab ) &&
148 (nStyle_ & SAL_FRAME_STYLE_FLOAT) &&
149 ! (nStyle_ & SAL_FRAME_STYLE_TOOLTIP) &&
150 ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
155 void X11SalFrame::setXEmbedInfo()
157 if( m_bXEmbed )
159 long aInfo[2];
160 aInfo[0] = 1; // XEMBED protocol version
161 aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED
162 XChangeProperty( pDisplay_->GetDisplay(),
163 mhWindow,
164 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
165 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
167 PropModeReplace,
168 reinterpret_cast<unsigned char*>(aInfo),
169 SAL_N_ELEMENTS(aInfo) );
173 void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
175 XEvent aEvent;
177 memset( &aEvent, 0, sizeof(aEvent) );
178 aEvent.xclient.window = mhForeignParent;
179 aEvent.xclient.type = ClientMessage;
180 aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED );
181 aEvent.xclient.format = 32;
182 aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
183 aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
184 aEvent.xclient.data.l[2] = 0;
185 aEvent.xclient.data.l[3] = 0;
186 aEvent.xclient.data.l[4] = 0;
188 GetGenericData()->ErrorTrapPush();
189 XSendEvent( pDisplay_->GetDisplay(),
190 mhForeignParent,
191 False, NoEventMask, &aEvent );
192 XSync( pDisplay_->GetDisplay(), False );
193 GetGenericData()->ErrorTrapPop();
196 typedef std::vector< unsigned long > NetWmIconData;
198 static void CreateNetWmAppIcon( sal_uInt16 nIcon, NetWmIconData& netwm_icon )
200 const int sizes[ 3 ] = { 48, 32, 16 };
201 netwm_icon.resize( 48 * 48 + 32 * 32 + 16 * 16 + 3 * 2 );
202 int pos = 0;
203 for( int i = 0; i < 3; ++i )
205 int size = sizes[ i ];
206 sal_uInt16 nIconSizeOffset;
207 if( size >= 48 )
208 nIconSizeOffset = SV_ICON_SIZE48_START;
209 else if( size >= 32 )
210 nIconSizeOffset = SV_ICON_SIZE32_START;
211 else
212 nIconSizeOffset = SV_ICON_SIZE16_START;
213 BitmapEx aIcon( ResId(nIconSizeOffset + nIcon, *ImplGetResMgr()));
214 if( aIcon.IsEmpty())
215 continue;
216 Bitmap icon = aIcon.GetBitmap();
217 AlphaMask mask;
218 switch( aIcon.GetTransparentType())
220 case TRANSPARENT_NONE:
222 sal_uInt8 nTrans = 0;
223 mask = AlphaMask( icon.GetSizePixel(), &nTrans );
225 break;
226 case TRANSPARENT_COLOR:
227 mask = AlphaMask( icon.CreateMask( aIcon.GetTransparentColor() ) );
228 break;
229 case TRANSPARENT_BITMAP:
230 mask = aIcon.GetAlpha();
231 break;
233 BitmapReadAccess* iconData = icon.AcquireReadAccess();
234 BitmapReadAccess* maskData = mask.AcquireReadAccess();
235 netwm_icon[ pos++ ] = size; // width
236 netwm_icon[ pos++ ] = size; // height
237 for( int y = 0; y < size; ++y )
238 for( int x = 0; x < size; ++x )
240 BitmapColor col = iconData->GetColor( y, x );
241 BitmapColor alpha = maskData->GetColor( y, x );
242 netwm_icon[ pos++ ] = (((( 255 - alpha.GetBlue()) * 256U ) + col.GetRed()) * 256 + col.GetGreen()) * 256 + col.GetBlue();
244 icon.ReleaseAccess( iconData );
245 mask.ReleaseAccess( maskData );
247 netwm_icon.resize( pos );
250 static bool lcl_SelectAppIconPixmap( SalDisplay *pDisplay, SalX11Screen nXScreen,
251 sal_uInt16 nIcon, sal_uInt16 iconSize,
252 Pixmap& icon_pixmap, Pixmap& icon_mask, NetWmIconData& netwm_icon)
254 if( ! ImplGetResMgr() )
255 return false;
257 CreateNetWmAppIcon( nIcon, netwm_icon );
259 sal_uInt16 nIconSizeOffset;
261 if( iconSize >= 48 )
262 nIconSizeOffset = SV_ICON_SIZE48_START;
263 else if( iconSize >= 32 )
264 nIconSizeOffset = SV_ICON_SIZE32_START;
265 else if( iconSize >= 16 )
266 nIconSizeOffset = SV_ICON_SIZE16_START;
267 else
268 return false;
270 BitmapEx aIcon( ResId(nIconSizeOffset + nIcon, *ImplGetResMgr()));
271 if( aIcon.IsEmpty() )
272 return false;
274 SalTwoRect aRect;
275 aRect.mnSrcX = 0; aRect.mnSrcY = 0;
276 aRect.mnSrcWidth = iconSize; aRect.mnSrcHeight = iconSize;
277 aRect.mnDestX = 0; aRect.mnDestY = 0;
278 aRect.mnDestWidth = iconSize; aRect.mnDestHeight = iconSize;
280 X11SalBitmap *pBitmap = static_cast < X11SalBitmap * >
281 (aIcon.ImplGetBitmapImpBitmap()->ImplGetSalBitmap());
283 icon_pixmap = XCreatePixmap( pDisplay->GetDisplay(),
284 pDisplay->GetRootWindow( nXScreen ),
285 iconSize, iconSize,
286 DefaultDepth( pDisplay->GetDisplay(),
287 nXScreen.getXScreen() )
290 pBitmap->ImplDraw( icon_pixmap,
291 nXScreen,
292 DefaultDepth( pDisplay->GetDisplay(),
293 nXScreen.getXScreen() ),
294 aRect,
295 DefaultGC( pDisplay->GetDisplay(),
296 nXScreen.getXScreen() ) );
298 icon_mask = None;
300 if( TRANSPARENT_BITMAP == aIcon.GetTransparentType() )
302 icon_mask = XCreatePixmap( pDisplay->GetDisplay(),
303 pDisplay->GetRootWindow( pDisplay->GetDefaultXScreen() ),
304 iconSize, iconSize, 1);
306 XGCValues aValues;
307 aValues.foreground = 0xffffffff;
308 aValues.background = 0;
309 aValues.function = GXcopy;
310 GC aMonoGC = XCreateGC( pDisplay->GetDisplay(), icon_mask,
311 GCFunction|GCForeground|GCBackground, &aValues );
313 Bitmap aMask = aIcon.GetMask();
314 aMask.Invert();
316 X11SalBitmap *pMask = static_cast < X11SalBitmap * >
317 (aMask.ImplGetImpBitmap()->ImplGetSalBitmap());
319 pMask->ImplDraw(icon_mask, nXScreen, 1, aRect, aMonoGC);
320 XFreeGC( pDisplay->GetDisplay(), aMonoGC );
323 return true;
326 void X11SalFrame::Init( sal_uLong nSalFrameStyle, SalX11Screen nXScreen, SystemParentData* pParentData, bool bUseGeometry )
328 if( nXScreen.getXScreen() >= GetDisplay()->GetXScreenCount() )
329 nXScreen = GetDisplay()->GetDefaultXScreen();
330 if( mpParent )
331 nXScreen = mpParent->m_nXScreen;
333 m_nXScreen = nXScreen;
334 nStyle_ = nSalFrameStyle;
335 XWMHints Hints;
336 Hints.flags = InputHint;
337 Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True;
338 NetWmIconData netwm_icon;
340 int x = 0, y = 0;
341 unsigned int w = 500, h = 500;
342 XSetWindowAttributes Attributes;
344 int nAttrMask = CWBorderPixel
345 | CWBackPixmap
346 | CWColormap
347 | CWOverrideRedirect
348 | CWEventMask
350 Attributes.border_pixel = 0;
351 Attributes.background_pixmap = None;
352 Attributes.colormap = GetDisplay()->GetColormap( m_nXScreen ).GetXColormap();
353 Attributes.override_redirect = False;
354 Attributes.event_mask = CLIENT_EVENTS;
356 const SalVisual& rVis = GetDisplay()->GetVisual( m_nXScreen );
357 XLIB_Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nXScreen );
358 XLIB_Window aClientLeader = None;
360 if( bUseGeometry )
362 x = maGeometry.nX;
363 y = maGeometry.nY;
364 w = maGeometry.nWidth;
365 h = maGeometry.nHeight;
368 if( (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT) &&
369 ! (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
372 if( nShowState_ == SHOWSTATE_UNKNOWN )
374 w = 10;
375 h = 10;
377 Attributes.override_redirect = True;
379 else if( (nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) )
381 DBG_ASSERT( mpParent, "SAL_FRAME_STYLE_SYSTEMCHILD window without parent" );
382 if( mpParent )
384 aFrameParent = mpParent->mhWindow;
385 // FIXME: since with SAL_FRAME_STYLE_SYSTEMCHILD
386 // multiple X11SalFrame objects can have the same shell window
387 // dispatching events in saldisp.cxx is unclear (the first frame)
388 // wins. HTH this correctly is unclear yet
389 // for the time being, treat set the shell window to own window
390 // like for a normal frame
391 // mhShellWindow = mpParent->GetShellWindow();
394 else if( pParentData )
396 // plugin parent may be killed unexpectedly by plugging
397 // process; start permanantly ignoring X errors ...
398 GetGenericData()->ErrorTrapPush();
400 nStyle_ |= SAL_FRAME_STYLE_PLUG;
401 Attributes.override_redirect = True;
402 if( pParentData->nSize >= sizeof(SystemParentData) )
403 m_bXEmbed = pParentData->bXEmbedSupport;
405 int x_ret, y_ret;
406 unsigned int bw, d;
407 XLIB_Window aRoot, aParent;
409 XGetGeometry( GetXDisplay(), pParentData->aWindow,
410 &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
411 mhForeignParent = pParentData->aWindow;
413 mhShellWindow = aParent = mhForeignParent;
414 XLIB_Window* pChildren;
415 unsigned int nChildren;
416 bool bBreak = false;
419 XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow,
420 &aRoot, &aParent, &pChildren, &nChildren );
421 XFree( pChildren );
422 if( aParent != aRoot )
423 mhShellWindow = aParent;
424 int nCount = 0;
425 Atom* pProps = XListProperties( GetDisplay()->GetDisplay(),
426 mhShellWindow,
427 &nCount );
428 for( int i = 0; i < nCount && ! bBreak; ++i )
429 bBreak = (pProps[i] == XA_WM_HINTS);
430 if( pProps )
431 XFree( pProps );
432 } while( aParent != aRoot && ! bBreak );
434 // check if this is really one of our own frames
435 // do not change the input mask in that case
436 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
437 std::list< SalFrame* >::const_iterator it = rFrames.begin();
438 while( it != rFrames.end() && mhForeignParent != static_cast<const X11SalFrame*>(*it)->GetWindow() )
439 ++it;
441 if( it == rFrames.end() )
443 XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask | FocusChangeMask );
444 XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask | FocusChangeMask );
447 else
449 if( ! bUseGeometry )
451 Size aScreenSize( GetDisplay()->getDataForScreen( m_nXScreen ).m_aSize );
452 w = aScreenSize.Width();
453 h = aScreenSize.Height();
454 if( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE &&
455 nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
457 Size aBestFitSize(bestmaxFrameSizeForScreenSize(aScreenSize));
458 w = aBestFitSize.Width();
459 h = aBestFitSize.Height();
461 if( ! mpParent )
463 // find the last document window (if any)
464 const X11SalFrame* pFrame = NULL;
465 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
466 std::list< SalFrame* >::const_iterator it = rFrames.begin();
467 while( it != rFrames.end() )
469 pFrame = static_cast< const X11SalFrame* >(*it);
470 if( ! ( pFrame->mpParent
471 || pFrame->mbFullScreen
472 || ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
473 || ! pFrame->GetUnmirroredGeometry().nWidth
474 || ! pFrame->GetUnmirroredGeometry().nHeight
477 break;
478 ++it;
481 if( it != rFrames.end() )
483 // set a document position and size
484 // the first frame gets positioned by the window manager
485 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
486 x = rGeom.nX;
487 y = rGeom.nY;
488 if( x+(int)w+40 <= (int)aScreenSize.Width() &&
489 y+(int)h+40 <= (int)aScreenSize.Height()
492 y += 40;
493 x += 40;
495 else
497 x = 10; // leave some space for decoration
498 y = 20;
501 else if( GetDisplay()->IsXinerama() )
503 // place frame on same screen as mouse pointer
504 XLIB_Window aRoot, aChild;
505 int root_x = 0, root_y = 0, lx, ly;
506 unsigned int mask;
507 XQueryPointer( GetXDisplay(),
508 GetDisplay()->GetRootWindow( m_nXScreen ),
509 &aRoot, &aChild,
510 &root_x, &root_y, &lx, &ly, &mask );
511 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
512 for( unsigned int i = 0; i < rScreens.size(); i++ )
513 if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
515 x = rScreens[i].Left();
516 y = rScreens[i].Top();
517 break;
522 Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity();
523 nAttrMask |= CWWinGravity;
524 if( mpParent )
526 Attributes.save_under = True;
527 nAttrMask |= CWSaveUnder;
529 if( IsOverrideRedirect() )
530 Attributes.override_redirect = True;
531 // default icon
532 if( (nStyle_ & SAL_FRAME_STYLE_INTRO) == 0 )
534 bool bOk=false;
537 bOk = lcl_SelectAppIconPixmap( pDisplay_, m_nXScreen,
538 mnIconID != 1 ? mnIconID :
539 (mpParent ? mpParent->mnIconID : 1), 32,
540 Hints.icon_pixmap, Hints.icon_mask, netwm_icon );
542 catch( com::sun::star::uno::Exception& )
544 // can happen - no ucb during early startup
546 if( bOk )
548 Hints.flags |= IconPixmapHint;
549 if( Hints.icon_mask )
550 Hints.flags |= IconMaskHint;
554 // find the top level frame of the transience hierarchy
555 X11SalFrame* pFrame = this;
556 while( pFrame->mpParent )
557 pFrame = pFrame->mpParent;
558 if( (pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) )
560 // if the top level window is a plugin window,
561 // then we should place us in the same window group as
562 // the parent application (or none if there is no window group
563 // hint in the parent).
564 if( pFrame->GetShellWindow() )
566 XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(),
567 pFrame->GetShellWindow() );
568 if( pWMHints )
570 if( (pWMHints->flags & WindowGroupHint) )
572 Hints.flags |= WindowGroupHint;
573 Hints.window_group = pWMHints->window_group;
575 XFree( pWMHints );
579 else
581 Hints.flags |= WindowGroupHint;
582 Hints.window_group = pFrame->GetShellWindow();
583 // note: for a normal document window this will produce None
584 // as the window is not yet created and the shell window is
585 // initialized to None. This must be corrected after window creation.
586 aClientLeader = GetDisplay()->GetDrawable( m_nXScreen );
590 nShowState_ = SHOWSTATE_UNKNOWN;
591 bViewable_ = true;
592 bMapped_ = false;
593 nVisibility_ = VisibilityFullyObscured;
594 mhWindow = XCreateWindow( GetXDisplay(),
595 aFrameParent,
596 x, y,
597 w, h,
599 rVis.GetDepth(),
600 InputOutput,
601 rVis.GetVisual(),
602 nAttrMask,
603 &Attributes );
604 // FIXME: see above: fake shell window for now to own window
605 if( pParentData == NULL )
607 mhShellWindow = mhWindow;
610 // correct window group if necessary
611 if( (Hints.flags & WindowGroupHint) == WindowGroupHint )
613 if( Hints.window_group == None )
614 Hints.window_group = GetShellWindow();
617 maGeometry.nX = x;
618 maGeometry.nY = y;
619 maGeometry.nWidth = w;
620 maGeometry.nHeight = h;
621 updateScreenNumber();
623 XSync( GetXDisplay(), False );
624 setXEmbedInfo();
626 XLIB_Time nUserTime = (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_TOOLWINDOW) ) == 0 ?
627 pDisplay_->GetLastUserEventTime() : 0;
628 pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime );
630 if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect )
632 XSetWMHints( GetXDisplay(), mhWindow, &Hints );
633 // WM Protocols && internals
634 Atom a[3];
635 int n = 0;
636 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
637 if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) )
638 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING );
639 if( (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
640 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS );
641 XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n );
643 // force wm class hint
644 mnExtStyle = ~0;
645 if (mpParent)
646 m_sWMClass = mpParent->m_sWMClass;
647 SetExtendedFrameStyle( 0 );
649 XSizeHints* pHints = XAllocSizeHints();
650 pHints->flags = PWinGravity | PPosition;
651 pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity();
652 pHints->x = 0;
653 pHints->y = 0;
654 if( mbFullScreen )
656 pHints->flags |= PMaxSize | PMinSize;
657 pHints->max_width = w+100;
658 pHints->max_height = h+100;
659 pHints->min_width = w;
660 pHints->min_height = h;
662 XSetWMNormalHints( GetXDisplay(),
663 GetShellWindow(),
664 pHints );
665 XFree (pHints);
667 // set PID and WM_CLIENT_MACHINE
668 pDisplay_->getWMAdaptor()->setClientMachine( this );
669 pDisplay_->getWMAdaptor()->setPID( this );
671 // set client leader
672 if( aClientLeader )
674 XChangeProperty( GetXDisplay(),
675 mhWindow,
676 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER),
677 XA_WINDOW,
679 PropModeReplace,
680 (unsigned char*)&aClientLeader,
684 #define DECOFLAGS (SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE)
685 int nDecoFlags = WMAdaptor::decoration_All;
686 if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ||
687 (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
689 nDecoFlags = 0;
690 else if( (nStyle_ & DECOFLAGS ) != DECOFLAGS || (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
692 if( nStyle_ & DECOFLAGS )
693 // if any decoration, then show a border
694 nDecoFlags = WMAdaptor::decoration_Border;
695 else
696 nDecoFlags = 0;
698 if( ! mpParent && (nStyle_ & DECOFLAGS) )
699 // don't add a min button if window should be decorationless
700 nDecoFlags |= WMAdaptor::decoration_MinimizeBtn;
701 if( nStyle_ & SAL_FRAME_STYLE_CLOSEABLE )
702 nDecoFlags |= WMAdaptor::decoration_CloseBtn;
703 if( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
705 nDecoFlags |= WMAdaptor::decoration_Resize;
706 if( ! (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
707 nDecoFlags |= WMAdaptor::decoration_MaximizeBtn;
709 if( nStyle_ & SAL_FRAME_STYLE_MOVEABLE )
710 nDecoFlags |= WMAdaptor::decoration_Title;
713 WMAdaptor::WMWindowType eType = WMAdaptor::windowType_Normal;
714 if( nStyle_ & SAL_FRAME_STYLE_INTRO )
715 eType = WMAdaptor::windowType_Splash;
716 if( (nStyle_ & SAL_FRAME_STYLE_DIALOG) && hPresentationWindow == None )
717 eType = WMAdaptor::windowType_ModelessDialogue;
718 if( nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW )
719 eType = WMAdaptor::windowType_Utility;
720 if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
721 eType = WMAdaptor::windowType_Toolbar;
722 if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN)
723 && GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
724 eType = WMAdaptor::windowType_Dock;
726 GetDisplay()->getWMAdaptor()->
727 setFrameTypeAndDecoration( this,
728 eType,
729 nDecoFlags,
730 hPresentationWindow ? NULL : mpParent );
732 if( (nStyle_ & (SAL_FRAME_STYLE_DEFAULT |
733 SAL_FRAME_STYLE_OWNERDRAWDECORATION|
734 SAL_FRAME_STYLE_FLOAT |
735 SAL_FRAME_STYLE_INTRO |
736 SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) )
737 == SAL_FRAME_STYLE_DEFAULT )
738 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
740 if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ))
741 XChangeProperty( GetXDisplay(), mhWindow,
742 GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ),
743 XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&netwm_icon.front(), netwm_icon.size());
746 m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea();
748 // Pointer
749 SetPointer( POINTER_ARROW );
752 X11SalFrame::X11SalFrame( SalFrame *pParent, sal_uLong nSalFrameStyle,
753 SystemParentData* pSystemParent ) :
754 m_nXScreen( 0 )
756 SalGenericData *pData = GetGenericData();
758 // initialize frame geometry
759 memset( &maGeometry, 0, sizeof(maGeometry) );
761 mpParent = static_cast< X11SalFrame* >( pParent );
763 mbTransientForRoot = false;
765 pDisplay_ = pData->GetSalDisplay();
766 // insert frame in framelist
767 pDisplay_->registerFrame( this );
769 mhWindow = None;
770 mhShellWindow = None;
771 mhStackingWindow = None;
772 mhForeignParent = None;
773 mhBackgroundPixmap = None;
774 m_bSetFocusOnMap = false;
776 pGraphics_ = NULL;
777 pFreeGraphics_ = NULL;
779 hCursor_ = None;
780 nCaptured_ = 0;
782 nReleaseTime_ = 0;
783 nKeyCode_ = 0;
784 nKeyState_ = 0;
785 nCompose_ = -1;
786 mbSendExtKeyModChange = false;
787 mnExtKeyMod = 0;
789 nShowState_ = SHOWSTATE_UNKNOWN;
790 nWidth_ = 0;
791 nHeight_ = 0;
792 nStyle_ = 0;
793 mnExtStyle = 0;
794 bAlwaysOnTop_ = false;
796 // set bViewable_ to true: hack GetClientSize to report something
797 // different to 0/0 before first map
798 bViewable_ = true;
799 bMapped_ = false;
800 bDefaultPosition_ = true;
801 nVisibility_ = VisibilityFullyObscured;
802 m_nWorkArea = 0;
803 mbInShow = false;
804 m_bXEmbed = false;
806 nScreenSaversTimeout_ = 0;
808 mpInputContext = NULL;
809 mbInputFocus = False;
811 maAlwaysOnTopRaiseTimer.SetTimeoutHdl( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise ) );
812 maAlwaysOnTopRaiseTimer.SetTimeout( 100 );
814 meWindowType = WMAdaptor::windowType_Normal;
815 mnDecorationFlags = WMAdaptor::decoration_All;
816 mbMaximizedVert = false;
817 mbMaximizedHorz = false;
818 mbShaded = false;
819 mbFullScreen = false;
821 mnIconID = 1; // ICON_LO_DEFAULT
823 m_pClipRectangles = NULL;
824 m_nCurClipRect = 0;
825 m_nMaxClipRect = 0;
827 if( mpParent )
828 mpParent->maChildren.push_back( this );
830 Init( nSalFrameStyle, GetDisplay()->GetDefaultXScreen(), pSystemParent );
833 X11SalFrame::~X11SalFrame()
835 notifyDelete();
837 if( m_pClipRectangles )
839 delete [] m_pClipRectangles;
840 m_pClipRectangles = NULL;
841 m_nCurClipRect = m_nMaxClipRect = 0;
844 if( mhBackgroundPixmap )
846 XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None );
847 XFreePixmap( GetXDisplay(), mhBackgroundPixmap );
850 if( mhStackingWindow )
851 aPresentationReparentList.remove( mhStackingWindow );
853 // remove from parent's list
854 if( mpParent )
855 mpParent->maChildren.remove( this );
857 // deregister on SalDisplay
858 pDisplay_->deregisterFrame( this );
860 // unselect all events, some may be still in the queue anyway
861 if( ! IsSysChildWindow() )
862 XSelectInput( GetXDisplay(), GetShellWindow(), 0 );
863 XSelectInput( GetXDisplay(), GetWindow(), 0 );
865 ShowFullScreen( false, 0 );
867 if( bMapped_ )
868 Show( false );
870 if( mpInputContext )
872 mpInputContext->UnsetICFocus( this );
873 mpInputContext->Unmap( this );
874 delete mpInputContext;
877 if( GetWindow() == hPresentationWindow )
879 hPresentationWindow = None;
880 doReparentPresentationDialogues( GetDisplay() );
883 if( pGraphics_ )
885 pGraphics_->DeInit();
886 delete pGraphics_;
889 if( pFreeGraphics_ )
891 pFreeGraphics_->DeInit();
892 delete pFreeGraphics_;
895 XDestroyWindow( GetXDisplay(), mhWindow );
898 * check if there is only the status frame left
899 * if so, free it
901 if( ! GetDisplay()->getFrames().empty() && I18NStatus::exists() )
903 SalFrame* pStatusFrame = I18NStatus::get().getStatusFrame();
904 std::list< SalFrame* >::const_iterator sit = GetDisplay()->getFrames().begin();
905 if( pStatusFrame
906 && *sit == pStatusFrame
907 && ++sit == GetDisplay()->getFrames().end() )
908 vcl::I18NStatus::free();
912 void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
914 if( nStyle != mnExtStyle && ! IsChildWindow() )
916 mnExtStyle = nStyle;
917 updateWMClass();
921 const SystemEnvData* X11SalFrame::GetSystemData() const
923 X11SalFrame *pFrame = const_cast<X11SalFrame*>(this);
924 pFrame->maSystemChildData.nSize = sizeof( SystemEnvData );
925 pFrame->maSystemChildData.pDisplay = GetXDisplay();
926 pFrame->maSystemChildData.aWindow = pFrame->GetWindow();
927 pFrame->maSystemChildData.pSalFrame = pFrame;
928 pFrame->maSystemChildData.pWidget = NULL;
929 pFrame->maSystemChildData.pVisual = GetDisplay()->GetVisual( m_nXScreen ).GetVisual();
930 pFrame->maSystemChildData.nScreen = m_nXScreen.getXScreen();
931 pFrame->maSystemChildData.nDepth = GetDisplay()->GetVisual( m_nXScreen ).GetDepth();
932 pFrame->maSystemChildData.aColormap = GetDisplay()->GetColormap( m_nXScreen ).GetXColormap();
933 pFrame->maSystemChildData.pAppContext = NULL;
934 pFrame->maSystemChildData.aShellWindow = pFrame->GetShellWindow();
935 pFrame->maSystemChildData.pShellWidget = NULL;
936 return &maSystemChildData;
939 SalGraphics *X11SalFrame::AcquireGraphics()
941 if( pGraphics_ )
942 return NULL;
944 if( pFreeGraphics_ )
946 pGraphics_ = pFreeGraphics_;
947 pFreeGraphics_ = NULL;
949 else
951 pGraphics_ = new X11SalGraphics();
952 pGraphics_->Init( this, GetWindow(), m_nXScreen );
955 return pGraphics_;
958 void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics )
960 DBG_ASSERT( pGraphics == pGraphics_, "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" );
962 if( pGraphics != pGraphics_ )
963 return;
965 pFreeGraphics_ = pGraphics_;
966 pGraphics_ = NULL;
969 void X11SalFrame::updateGraphics( bool bClear )
971 Drawable aDrawable = bClear ? None : GetWindow();
972 if( pGraphics_ )
973 pGraphics_->SetDrawable( aDrawable, m_nXScreen );
974 if( pFreeGraphics_ )
975 pFreeGraphics_->SetDrawable( aDrawable, m_nXScreen );
978 void X11SalFrame::Enable( bool /*bEnable*/ )
980 // NYI: enable/disable frame
983 void X11SalFrame::SetIcon( sal_uInt16 nIcon )
985 if ( ! IsChildWindow() )
987 // 0 == default icon -> #1
988 if ( nIcon == 0 )
989 nIcon = 1;
991 mnIconID = nIcon;
993 XIconSize *pIconSize = NULL;
994 int nSizes = 0;
995 int iconSize = 32;
996 if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nXScreen ), &pIconSize, &nSizes ) )
998 #if OSL_DEBUG_LEVEL > 1
999 fprintf(stderr, "X11SalFrame::SetIcon(): found %d IconSizes:\n", nSizes);
1000 #endif
1002 const int ourLargestIconSize = 48;
1004 int i;
1005 for( i=0; i<nSizes; i++)
1007 // select largest supported icon
1009 // Note: olwm/olvwm reports a huge max icon size of
1010 // 160x160 pixels; always choosing the max as the
1011 // preferred icon size is apparently wrong under olvwm
1012 // - so we keep the safe default |iconSize| when we see
1013 // unreasonable large max icon sizes (> twice of our
1014 // largest available icon) reported by XGetIconSizes.
1015 if( pIconSize[i].max_width > iconSize
1016 && pIconSize[i].max_width <= 2*ourLargestIconSize )
1018 iconSize = pIconSize[i].max_width;
1020 iconSize = pIconSize[i].max_width;
1022 #if OSL_DEBUG_LEVEL > 1
1023 fprintf(stderr, "min: %d, %d\nmax: %d, %d\ninc: %d, %d\n\n",
1024 pIconSize[i].min_width, pIconSize[i].min_height,
1025 pIconSize[i].max_width, pIconSize[i].max_height,
1026 pIconSize[i].width_inc, pIconSize[i].height_inc);
1027 #endif
1030 XFree( pIconSize );
1032 else
1034 const OUString& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );
1035 if( rWM.equalsAscii( "KWin" ) ) // assume KDE is running
1036 iconSize = 48;
1037 static bool bGnomeIconSize = false;
1038 static bool bGnomeChecked = false;
1039 if( ! bGnomeChecked )
1041 bGnomeChecked=true;
1042 int nCount = 0;
1043 Atom* pProps = XListProperties( GetXDisplay(),
1044 GetDisplay()->GetRootWindow( m_nXScreen ),
1045 &nCount );
1046 for( int i = 0; i < nCount && !bGnomeIconSize; i++ )
1048 char* pName = XGetAtomName( GetXDisplay(), pProps[i] );
1049 if( pName )
1051 if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) )
1052 bGnomeIconSize = true;
1053 XFree( pName );
1056 if( pProps )
1057 XFree( pProps );
1059 if( bGnomeIconSize )
1060 iconSize = 48;
1063 XWMHints Hints;
1064 Hints.flags = 0;
1065 XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() );
1066 if( pHints )
1068 memcpy(&Hints, pHints, sizeof( XWMHints ));
1069 XFree( pHints );
1071 pHints = &Hints;
1073 NetWmIconData netwm_icon;
1074 bool bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen,
1075 nIcon, iconSize,
1076 pHints->icon_pixmap, pHints->icon_mask, netwm_icon );
1077 if ( !bOk )
1079 // load default icon (0)
1080 bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen,
1081 0, iconSize,
1082 pHints->icon_pixmap, pHints->icon_mask, netwm_icon );
1084 if( bOk )
1086 pHints->flags |= IconPixmapHint;
1087 if( pHints->icon_mask )
1088 pHints->flags |= IconMaskHint;
1090 XSetWMHints( GetXDisplay(), GetShellWindow(), pHints );
1091 if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ))
1092 XChangeProperty( GetXDisplay(), mhWindow,
1093 GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ),
1094 XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&netwm_icon.front(), netwm_icon.size());
1099 void X11SalFrame::SetMaxClientSize( 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->max_width = nWidth;
1113 pHints->max_height = nHeight;
1114 pHints->flags |= PMaxSize;
1115 XSetWMNormalHints( GetXDisplay(),
1116 GetShellWindow(),
1117 pHints );
1118 XFree( pHints );
1123 void X11SalFrame::SetMinClientSize( long nWidth, long nHeight )
1125 if( ! IsChildWindow() )
1127 if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
1129 XSizeHints* pHints = XAllocSizeHints();
1130 long nSupplied = 0;
1131 XGetWMNormalHints( GetXDisplay(),
1132 GetShellWindow(),
1133 pHints,
1134 &nSupplied
1136 pHints->min_width = nWidth;
1137 pHints->min_height = nHeight;
1138 pHints->flags |= PMinSize;
1139 XSetWMNormalHints( GetXDisplay(),
1140 GetShellWindow(),
1141 pHints );
1142 XFree( pHints );
1147 // Show + Pos (x,y,z) + Size (width,height)
1149 void X11SalFrame::Show( bool bVisible, bool bNoActivate )
1151 if( ( bVisible && bMapped_ )
1152 || ( !bVisible && !bMapped_ ) )
1153 return;
1155 // HACK: this is a workaround for (at least) kwin
1156 // even though transient frames should be kept above their parent
1157 // this does not necessarily hold true for DOCK type windows
1158 // so artificially set ABOVE and remove it again on hide
1159 if( mpParent && (mpParent->nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) && pDisplay_->getWMAdaptor()->isLegacyPartialFullscreen())
1160 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible );
1162 bMapped_ = bVisible;
1163 bViewable_ = bVisible;
1164 setXEmbedInfo();
1165 if( bVisible )
1167 mbInShow = true;
1168 if( ! (nStyle_ & SAL_FRAME_STYLE_INTRO) )
1170 // hide all INTRO frames
1171 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
1172 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
1174 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
1175 // look for intro bit map; if present, hide it
1176 if( pFrame->nStyle_ & SAL_FRAME_STYLE_INTRO )
1178 if( pFrame->bMapped_ )
1179 const_cast<X11SalFrame*>(pFrame)->Show( false );
1184 // update NET_WM_STATE which may have been deleted due to earlier Show(false)
1185 if( nShowState_ == SHOWSTATE_HIDDEN )
1186 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1189 * Actually this is rather exotic and currently happens only in conjunction
1190 * with the basic dialogue editor,
1191 * which shows a frame and instantly hides it again. After that the
1192 * editor window is shown and the WM takes this as an opportunity
1193 * to show our hidden transient frame also. So Show( false ) must
1194 * withdraw the frame AND delete the WM_TRANSIENT_FOR property.
1195 * In case the frame is shown again, the transient hint must be restored here.
1197 if( ! IsChildWindow()
1198 && ! IsOverrideRedirect()
1199 && ! IsFloatGrabWindow()
1200 && mpParent
1203 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
1206 // #i45160# switch to desktop where a dialog with parent will appear
1207 if( mpParent && mpParent->m_nWorkArea != m_nWorkArea )
1208 GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea );
1210 if( IsFloatGrabWindow() &&
1211 mpParent &&
1212 nVisibleFloats == 0 &&
1213 ! GetDisplay()->GetCaptureFrame() )
1215 /* #i39420#
1216 * outsmart KWin's "focus strictly under mouse" mode
1217 * which insists on taking the focus from the document
1218 * to the new float. Grab focus to parent frame BEFORE
1219 * showing the float (cannot grab it to the float
1220 * before show).
1222 XGrabPointer( GetXDisplay(),
1223 mpParent->GetWindow(),
1224 True,
1225 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1226 GrabModeAsync,
1227 GrabModeAsync,
1228 None,
1229 mpParent ? mpParent->GetCursor() : None,
1230 CurrentTime
1234 XLIB_Time nUserTime = 0;
1235 if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) == 0 )
1236 nUserTime = pDisplay_->GetLastUserEventTime( true );
1237 GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime );
1238 if( ! bNoActivate && (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
1239 m_bSetFocusOnMap = true;
1241 // actually map the window
1242 if( m_bXEmbed )
1243 askForXEmbedFocus( 0 );
1244 else
1246 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1248 if( IsChildWindow() )
1249 XMapWindow( GetXDisplay(), GetShellWindow() );
1250 XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS );
1252 if( nStyle_ & SAL_FRAME_STYLE_FLOAT )
1253 XMapRaised( GetXDisplay(), GetWindow() );
1254 else
1255 XMapWindow( GetXDisplay(), GetWindow() );
1257 XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS );
1259 if( maGeometry.nWidth > 0
1260 && maGeometry.nHeight > 0
1261 && ( nWidth_ != (int)maGeometry.nWidth
1262 || nHeight_ != (int)maGeometry.nHeight ) )
1264 nWidth_ = maGeometry.nWidth;
1265 nHeight_ = maGeometry.nHeight;
1268 XSync( GetXDisplay(), False );
1270 if( IsFloatGrabWindow() )
1273 * Sawfish and twm can be switched to enter-exit focus behaviour. In this case
1274 * we must grab the pointer else the dumb WM will put the focus to the
1275 * override-redirect float window. The application window will be deactivated
1276 * which causes that the floats are destroyed, so the user can never click on
1277 * a menu because it vanishes as soon as he enters it.
1279 nVisibleFloats++;
1280 if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() )
1282 /* #i39420# now move grab to the new float window */
1283 XGrabPointer( GetXDisplay(),
1284 GetWindow(),
1285 True,
1286 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1287 GrabModeAsync,
1288 GrabModeAsync,
1289 None,
1290 mpParent ? mpParent->GetCursor() : None,
1291 CurrentTime
1295 CallCallback( SALEVENT_RESIZE, NULL );
1298 * sometimes a message box/dialogue is brought up when a frame is not mapped
1299 * the corresponding TRANSIENT_FOR hint is then set to the root window
1300 * so that the dialogue shows in all cases. Correct it here if the
1301 * frame is shown afterwards.
1303 if( ! IsChildWindow()
1304 && ! IsOverrideRedirect()
1305 && ! IsFloatGrabWindow()
1308 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
1309 it != maChildren.end(); ++it )
1311 if( (*it)->mbTransientForRoot )
1312 GetDisplay()->getWMAdaptor()->changeReferenceFrame( *it, this );
1316 * leave SHOWSTATE_UNKNOWN as this indicates first mapping
1317 * and is only reset int HandleSizeEvent
1319 if( nShowState_ != SHOWSTATE_UNKNOWN )
1320 nShowState_ = SHOWSTATE_NORMAL;
1323 * plugged windows don't necessarily get the
1324 * focus on show because the parent may already be mapped
1325 * and have the focus. So try to set the focus
1326 * to the child on Show(true)
1328 if( (nStyle_ & SAL_FRAME_STYLE_PLUG) && ! m_bXEmbed )
1329 XSetInputFocus( GetXDisplay(),
1330 GetWindow(),
1331 RevertToParent,
1332 CurrentTime );
1334 if( mpParent )
1336 // push this frame so it will be in front of its siblings
1337 // only necessary for insane transient behaviour of Dtwm/olwm
1338 mpParent->maChildren.remove( this );
1339 mpParent->maChildren.push_front(this);
1342 else
1344 if( getInputContext() )
1345 getInputContext()->Unmap( this );
1347 if( ! IsChildWindow() )
1349 /* FIXME: Is deleting the property really necessary ? It hurts
1350 * owner drawn windows at least.
1352 if( mpParent && ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
1353 XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) );
1354 XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nXScreen.getXScreen() );
1356 else if( ! m_bXEmbed )
1357 XUnmapWindow( GetXDisplay(), GetWindow() );
1359 nShowState_ = SHOWSTATE_HIDDEN;
1360 if( IsFloatGrabWindow() && nVisibleFloats )
1362 nVisibleFloats--;
1363 if( nVisibleFloats == 0 && ! GetDisplay()->GetCaptureFrame() )
1364 XUngrabPointer( GetXDisplay(),
1365 CurrentTime );
1367 // flush here; there may be a very seldom race between
1368 // the display connection used for clipboard and our connection
1369 Flush();
1373 void X11SalFrame::ToTop( sal_uInt16 nFlags )
1375 if( ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
1376 && ! ( nStyle_ & SAL_FRAME_STYLE_FLOAT )
1377 && nShowState_ != SHOWSTATE_HIDDEN
1378 && nShowState_ != SHOWSTATE_UNKNOWN
1381 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1382 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1383 XMapWindow( GetXDisplay(), GetShellWindow() );
1384 XMapWindow( GetXDisplay(), GetWindow() );
1387 XLIB_Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow();
1388 if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) )
1390 XRaiseWindow( GetXDisplay(), aToTopWindow );
1391 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() )
1392 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
1393 it != maChildren.end(); ++it )
1394 (*it)->ToTop( nFlags & ~SAL_FRAME_TOTOP_GRABFOCUS );
1397 if( ( ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) || ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY ) )
1398 && bMapped_ )
1400 if( m_bXEmbed )
1401 askForXEmbedFocus( 0 );
1402 else
1403 XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent, CurrentTime );
1407 void X11SalFrame::GetWorkArea( Rectangle& rWorkArea )
1409 rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 );
1412 void X11SalFrame::GetClientSize( long &rWidth, long &rHeight )
1414 if( ! bViewable_ )
1416 rWidth = rHeight = 0;
1417 return;
1420 rWidth = maGeometry.nWidth;
1421 rHeight = maGeometry.nHeight;
1423 if( !rWidth || !rHeight )
1425 XWindowAttributes aAttrib;
1427 XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib );
1429 maGeometry.nWidth = rWidth = aAttrib.width;
1430 maGeometry.nHeight = rHeight = aAttrib.height;
1434 void X11SalFrame::Center( )
1436 int nX, nY, nScreenWidth, nScreenHeight;
1437 int nRealScreenWidth, nRealScreenHeight;
1438 int nScreenX = 0, nScreenY = 0;
1440 const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nXScreen ).m_aSize;
1441 nScreenWidth = aScreenSize.Width();
1442 nScreenHeight = aScreenSize.Height();
1443 nRealScreenWidth = nScreenWidth;
1444 nRealScreenHeight = nScreenHeight;
1446 if( GetDisplay()->IsXinerama() )
1448 // get xinerama screen we are on
1449 // if there is a parent, use its center for screen determination
1450 // else use the pointer
1451 XLIB_Window aRoot, aChild;
1452 int root_x, root_y, x, y;
1453 unsigned int mask;
1454 if( mpParent )
1456 root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2;
1457 root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2;
1459 else
1460 XQueryPointer( GetXDisplay(),
1461 GetShellWindow(),
1462 &aRoot, &aChild,
1463 &root_x, &root_y,
1464 &x, &y,
1465 &mask );
1466 const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
1467 for( unsigned int i = 0; i < rScreens.size(); i++ )
1468 if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
1470 nScreenX = rScreens[i].Left();
1471 nScreenY = rScreens[i].Top();
1472 nRealScreenWidth = rScreens[i].GetWidth();
1473 nRealScreenHeight = rScreens[i].GetHeight();
1474 break;
1478 if( mpParent )
1480 X11SalFrame* pFrame = mpParent;
1481 while( pFrame->mpParent )
1482 pFrame = pFrame->mpParent;
1483 if( pFrame->maGeometry.nWidth < 1 || pFrame->maGeometry.nHeight < 1 )
1485 Rectangle aRect;
1486 pFrame->GetPosSize( aRect );
1487 pFrame->maGeometry.nX = aRect.Left();
1488 pFrame->maGeometry.nY = aRect.Top();
1489 pFrame->maGeometry.nWidth = aRect.GetWidth();
1490 pFrame->maGeometry.nHeight = aRect.GetHeight();
1493 if( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG )
1495 XLIB_Window aRoot;
1496 unsigned int bw, depth;
1497 XGetGeometry( GetXDisplay(),
1498 pFrame->GetShellWindow(),
1499 &aRoot,
1500 &nScreenX, &nScreenY,
1501 (unsigned int*)&nScreenWidth,
1502 (unsigned int*)&nScreenHeight,
1503 &bw, &depth );
1505 else
1507 nScreenX = pFrame->maGeometry.nX;
1508 nScreenY = pFrame->maGeometry.nY;
1509 nScreenWidth = pFrame->maGeometry.nWidth;
1510 nScreenHeight = pFrame->maGeometry.nHeight;
1514 if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL )
1516 if( maGeometry.nWidth >= mpParent->maGeometry.nWidth &&
1517 maGeometry.nHeight >= mpParent->maGeometry.nHeight )
1519 nX = nScreenX + 40;
1520 nY = nScreenY + 40;
1522 else
1524 // center the window relative to the top level frame
1525 nX = (nScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX;
1526 nY = (nScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
1529 else
1531 // center the window relative to screen
1532 nX = (nRealScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX;
1533 nY = (nRealScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
1535 nX = nX < 0 ? 0 : nX;
1536 nY = nY < 0 ? 0 : nY;
1538 bDefaultPosition_ = False;
1539 if( mpParent )
1541 nX -= mpParent->maGeometry.nX;
1542 nY -= mpParent->maGeometry.nY;
1545 Point aPoint(nX, nY);
1546 SetPosSize( Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
1549 void X11SalFrame::updateScreenNumber()
1551 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
1553 Point aPoint( maGeometry.nX, maGeometry.nY );
1554 const std::vector<Rectangle>& rScreenRects( GetDisplay()->GetXineramaScreens() );
1555 size_t nScreens = rScreenRects.size();
1556 for( size_t i = 0; i < nScreens; i++ )
1558 if( rScreenRects[i].IsInside( aPoint ) )
1560 maGeometry.nDisplayScreenNumber = static_cast<unsigned int>(i);
1561 break;
1565 else
1566 maGeometry.nDisplayScreenNumber = m_nXScreen.getXScreen();
1569 void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
1571 if( nStyle_ & SAL_FRAME_STYLE_PLUG )
1572 return;
1574 // relative positioning in X11SalFrame::SetPosSize
1575 Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) );
1576 aPosSize.Justify();
1578 if( ! ( nFlags & SAL_FRAME_POSSIZE_X ) )
1580 nX = aPosSize.Left();
1581 if( mpParent )
1582 nX -= mpParent->maGeometry.nX;
1584 if( ! ( nFlags & SAL_FRAME_POSSIZE_Y ) )
1586 nY = aPosSize.Top();
1587 if( mpParent )
1588 nY -= mpParent->maGeometry.nY;
1590 if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH ) )
1591 nWidth = aPosSize.GetWidth();
1592 if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT ) )
1593 nHeight = aPosSize.GetHeight();
1595 aPosSize = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1597 if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) ) )
1599 if( bDefaultPosition_ )
1601 maGeometry.nWidth = aPosSize.GetWidth();
1602 maGeometry.nHeight = aPosSize.GetHeight();
1603 Center();
1605 else
1606 SetSize( Size( nWidth, nHeight ) );
1608 else
1609 SetPosSize( aPosSize );
1611 bDefaultPosition_ = False;
1614 void X11SalFrame::SetAlwaysOnTop( bool bOnTop )
1616 if( ! IsOverrideRedirect() )
1618 bAlwaysOnTop_ = bOnTop;
1619 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop );
1623 #define _FRAMESTATE_MASK_GEOMETRY \
1624 (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y | \
1625 WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT)
1626 #define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \
1627 (WINDOWSTATE_MASK_MAXIMIZED_X | WINDOWSTATE_MASK_MAXIMIZED_Y | \
1628 WINDOWSTATE_MASK_MAXIMIZED_WIDTH | WINDOWSTATE_MASK_MAXIMIZED_HEIGHT)
1630 void X11SalFrame::SetWindowState( const SalFrameState *pState )
1632 if (pState == NULL)
1633 return;
1635 // Request for position or size change
1636 if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY)
1638 Rectangle aPosSize;
1640 /* #i44325#
1641 * if maximized, set restore size and guess maximized size from last time
1642 * in state change below maximize window
1644 if( ! IsChildWindow() &&
1645 (pState->mnMask & WINDOWSTATE_MASK_STATE) &&
1646 (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED) &&
1647 (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) == _FRAMESTATE_MASK_GEOMETRY &&
1648 (pState->mnMask & _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY
1651 XSizeHints* pHints = XAllocSizeHints();
1652 long nSupplied = 0;
1653 XGetWMNormalHints( GetXDisplay(),
1654 GetShellWindow(),
1655 pHints,
1656 &nSupplied );
1657 pHints->flags |= PPosition | PWinGravity;
1658 pHints->x = pState->mnX;
1659 pHints->y = pState->mnY;
1660 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
1661 XSetWMNormalHints( GetXDisplay(),
1662 GetShellWindow(),
1663 pHints );
1664 XFree( pHints );
1666 XMoveResizeWindow( GetXDisplay(), GetShellWindow(),
1667 pState->mnX, pState->mnY,
1668 pState->mnWidth, pState->mnHeight );
1669 // guess maximized geometry from last time
1670 maGeometry.nX = pState->mnMaximizedX;
1671 maGeometry.nY = pState->mnMaximizedY;
1672 maGeometry.nWidth = pState->mnMaximizedWidth;
1673 maGeometry.nHeight = pState->mnMaximizedHeight;
1674 updateScreenNumber();
1676 else
1678 bool bDoAdjust = false;
1679 // initialize with current geometry
1680 if ((pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) != _FRAMESTATE_MASK_GEOMETRY)
1681 GetPosSize (aPosSize);
1683 // change requested properties
1684 if (pState->mnMask & WINDOWSTATE_MASK_X)
1686 aPosSize.setX (pState->mnX);
1688 if (pState->mnMask & WINDOWSTATE_MASK_Y)
1690 aPosSize.setY (pState->mnY);
1692 if (pState->mnMask & WINDOWSTATE_MASK_WIDTH)
1694 long nWidth = pState->mnWidth > 0 ? pState->mnWidth - 1 : 0;
1695 aPosSize.setWidth (nWidth);
1696 bDoAdjust = true;
1698 if (pState->mnMask & WINDOWSTATE_MASK_HEIGHT)
1700 int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0;
1701 aPosSize.setHeight (nHeight);
1702 bDoAdjust = true;
1705 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nXScreen ).m_aSize;
1707 if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width()
1708 && aPosSize.GetHeight() <= aScreenSize.Height() )
1710 SalFrameGeometry aGeom = maGeometry;
1712 if( ! (nStyle_ & ( SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_PLUG ) ) &&
1713 mpParent &&
1714 aGeom.nLeftDecoration == 0 &&
1715 aGeom.nTopDecoration == 0 )
1717 aGeom = mpParent->maGeometry;
1718 if( aGeom.nLeftDecoration == 0 &&
1719 aGeom.nTopDecoration == 0 )
1721 aGeom.nLeftDecoration = 5;
1722 aGeom.nTopDecoration = 20;
1723 aGeom.nRightDecoration = 5;
1724 aGeom.nBottomDecoration = 5;
1728 // adjust position so that frame fits onto screen
1729 if( aPosSize.Right()+(long)aGeom.nRightDecoration > aScreenSize.Width()-1 )
1730 aPosSize.Move( (long)aScreenSize.Width() - (long)aPosSize.Right() - (long)aGeom.nRightDecoration, 0 );
1731 if( aPosSize.Bottom()+(long)aGeom.nBottomDecoration > aScreenSize.Height()-1 )
1732 aPosSize.Move( 0, (long)aScreenSize.Height() - (long)aPosSize.Bottom() - (long)aGeom.nBottomDecoration );
1733 if( aPosSize.Left() < (long)aGeom.nLeftDecoration )
1734 aPosSize.Move( (long)aGeom.nLeftDecoration - (long)aPosSize.Left(), 0 );
1735 if( aPosSize.Top() < (long)aGeom.nTopDecoration )
1736 aPosSize.Move( 0, (long)aGeom.nTopDecoration - (long)aPosSize.Top() );
1739 SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
1743 // request for status change
1744 if (pState->mnMask & WINDOWSTATE_MASK_STATE)
1746 if (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED)
1748 nShowState_ = SHOWSTATE_NORMAL;
1749 if( ! (pState->mnState & (WINDOWSTATE_STATE_MAXIMIZED_HORZ|WINDOWSTATE_STATE_MAXIMIZED_VERT) ) )
1750 Maximize();
1751 else
1753 bool bHorz = (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED_HORZ) ? true : false;
1754 bool bVert = (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED_VERT) ? true : false;
1755 GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert );
1757 maRestorePosSize.Left() = pState->mnX;
1758 maRestorePosSize.Top() = pState->mnY;
1759 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnWidth;
1760 maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnHeight;
1762 else if( mbMaximizedHorz || mbMaximizedVert )
1763 GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false );
1765 if (pState->mnState & WINDOWSTATE_STATE_MINIMIZED)
1767 if (nShowState_ == SHOWSTATE_UNKNOWN)
1768 nShowState_ = SHOWSTATE_NORMAL;
1769 Minimize();
1771 if (pState->mnState & WINDOWSTATE_STATE_NORMAL)
1773 if (nShowState_ != SHOWSTATE_NORMAL)
1774 Restore();
1776 if (pState->mnState & WINDOWSTATE_STATE_ROLLUP)
1777 GetDisplay()->getWMAdaptor()->shade( this, true );
1781 bool X11SalFrame::GetWindowState( SalFrameState* pState )
1783 if( SHOWSTATE_MINIMIZED == nShowState_ )
1784 pState->mnState = WINDOWSTATE_STATE_MINIMIZED;
1785 else
1786 pState->mnState = WINDOWSTATE_STATE_NORMAL;
1788 Rectangle aPosSize;
1789 if( maRestorePosSize.IsEmpty() )
1790 GetPosSize( aPosSize );
1791 else
1792 aPosSize = maRestorePosSize;
1794 if( mbMaximizedHorz )
1795 pState->mnState |= WINDOWSTATE_STATE_MAXIMIZED_HORZ;
1796 if( mbMaximizedVert )
1797 pState->mnState |= WINDOWSTATE_STATE_MAXIMIZED_VERT;
1798 if( mbShaded )
1799 pState->mnState |= WINDOWSTATE_STATE_ROLLUP;
1801 pState->mnX = aPosSize.Left();
1802 pState->mnY = aPosSize.Top();
1803 pState->mnWidth = aPosSize.GetWidth();
1804 pState->mnHeight = aPosSize.GetHeight();
1806 pState->mnMask = _FRAMESTATE_MASK_GEOMETRY | WINDOWSTATE_MASK_STATE;
1808 if (! maRestorePosSize.IsEmpty() )
1810 GetPosSize( aPosSize );
1811 pState->mnState |= WINDOWSTATE_STATE_MAXIMIZED;
1812 pState->mnMaximizedX = aPosSize.Left();
1813 pState->mnMaximizedY = aPosSize.Top();
1814 pState->mnMaximizedWidth = aPosSize.GetWidth();
1815 pState->mnMaximizedHeight = aPosSize.GetHeight();
1816 pState->mnMask |= _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY;
1819 return true;
1822 // native menu implementation - currently empty
1823 void X11SalFrame::DrawMenuBar()
1827 void X11SalFrame::SetMenu( SalMenu* )
1831 void X11SalFrame::GetPosSize( Rectangle &rPosSize )
1833 if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 )
1835 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nXScreen ).m_aSize;
1836 long w = aScreenSize.Width() - maGeometry.nLeftDecoration - maGeometry.nRightDecoration;
1837 long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration;
1839 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) );
1841 else
1842 rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
1843 Size( maGeometry.nWidth, maGeometry.nHeight ) );
1846 void X11SalFrame::SetSize( const Size &rSize )
1848 if( rSize.Width() > 0 && rSize.Height() > 0 )
1850 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
1851 && ! IsChildWindow()
1852 && ( nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
1854 XSizeHints* pHints = XAllocSizeHints();
1855 long nSupplied = 0;
1856 XGetWMNormalHints( GetXDisplay(),
1857 GetShellWindow(),
1858 pHints,
1859 &nSupplied
1861 pHints->min_width = rSize.Width();
1862 pHints->min_height = rSize.Height();
1863 pHints->max_width = rSize.Width();
1864 pHints->max_height = rSize.Height();
1865 pHints->flags |= PMinSize | PMaxSize;
1866 XSetWMNormalHints( GetXDisplay(),
1867 GetShellWindow(),
1868 pHints );
1869 XFree( pHints );
1871 XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() );
1872 if( GetWindow() != GetShellWindow() )
1874 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
1875 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() );
1876 else
1877 XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() );
1880 maGeometry.nWidth = rSize.Width();
1881 maGeometry.nHeight = rSize.Height();
1883 // allow the external status window to reposition
1884 if (mbInputFocus && mpInputContext != NULL)
1885 mpInputContext->SetICFocus ( this );
1889 void X11SalFrame::SetPosSize( const Rectangle &rPosSize )
1891 XWindowChanges values;
1892 values.x = rPosSize.Left();
1893 values.y = rPosSize.Top();
1894 values.width = rPosSize.GetWidth();
1895 values.height = rPosSize.GetHeight();
1897 if( !values.width || !values.height )
1898 return;
1900 if( mpParent && ! IsSysChildWindow() )
1902 // --- RTL --- (mirror window pos)
1903 if( Application::GetSettings().GetLayoutRTL() )
1904 values.x = mpParent->maGeometry.nWidth-values.width-1-values.x;
1906 XLIB_Window aChild;
1907 // coordinates are relative to parent, so translate to root coordinates
1908 XTranslateCoordinates( GetDisplay()->GetDisplay(),
1909 mpParent->GetWindow(),
1910 GetDisplay()->GetRootWindow( m_nXScreen ),
1911 values.x, values.y,
1912 &values.x, &values.y,
1913 & aChild );
1916 bool bMoved = false;
1917 bool bSized = false;
1918 if( values.x != maGeometry.nX || values.y != maGeometry.nY )
1919 bMoved = true;
1920 if( values.width != (int)maGeometry.nWidth || values.height != (int)maGeometry.nHeight )
1921 bSized = true;
1923 if( ! ( nStyle_ & ( SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_FLOAT ) )
1924 && !(pDisplay_->GetProperties() & PROPERTY_SUPPORT_WM_ClientPos) )
1926 values.x -= maGeometry.nLeftDecoration;
1927 values.y -= maGeometry.nTopDecoration;
1930 // do net set WMNormalHints for ..
1932 // child windows
1933 ! IsChildWindow()
1934 // popups (menu, help window, etc.)
1935 && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT
1936 // shown, sizeable windows
1937 && ( nShowState_ == SHOWSTATE_UNKNOWN ||
1938 nShowState_ == SHOWSTATE_HIDDEN ||
1939 ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
1943 XSizeHints* pHints = XAllocSizeHints();
1944 long nSupplied = 0;
1945 XGetWMNormalHints( GetXDisplay(),
1946 GetShellWindow(),
1947 pHints,
1948 &nSupplied
1950 if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
1952 pHints->min_width = rPosSize.GetWidth();
1953 pHints->min_height = rPosSize.GetHeight();
1954 pHints->max_width = rPosSize.GetWidth();
1955 pHints->max_height = rPosSize.GetHeight();
1956 pHints->flags |= PMinSize | PMaxSize;
1958 if( nShowState_ == SHOWSTATE_UNKNOWN || nShowState_ == SHOWSTATE_HIDDEN )
1960 pHints->flags |= PPosition | PWinGravity;
1961 pHints->x = values.x;
1962 pHints->y = values.y;
1963 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
1965 if( mbFullScreen )
1967 pHints->max_width = 10000;
1968 pHints->max_height = 10000;
1969 pHints->flags |= PMaxSize;
1971 XSetWMNormalHints( GetXDisplay(),
1972 GetShellWindow(),
1973 pHints );
1974 XFree( pHints );
1977 XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height );
1978 if( GetShellWindow() != GetWindow() )
1980 if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
1981 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height );
1982 else
1983 XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height );
1986 maGeometry.nX = values.x;
1987 maGeometry.nY = values.y;
1988 maGeometry.nWidth = values.width;
1989 maGeometry.nHeight = values.height;
1990 if( IsSysChildWindow() && mpParent )
1992 // translate back to root coordinates
1993 maGeometry.nX += mpParent->maGeometry.nX;
1994 maGeometry.nY += mpParent->maGeometry.nY;
1997 updateScreenNumber();
1998 if( bSized && ! bMoved )
1999 CallCallback( SALEVENT_RESIZE, NULL );
2000 else if( bMoved && ! bSized )
2001 CallCallback( SALEVENT_MOVE, NULL );
2002 else
2003 CallCallback( SALEVENT_MOVERESIZE, NULL );
2005 // allow the external status window to reposition
2006 if (mbInputFocus && mpInputContext != NULL)
2007 mpInputContext->SetICFocus ( this );
2010 void X11SalFrame::Minimize()
2012 if( IsSysChildWindow() )
2013 return;
2015 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
2017 stderr0( "X11SalFrame::Minimize on withdrawn window\n" );
2018 return;
2021 if( XIconifyWindow( GetXDisplay(),
2022 GetShellWindow(),
2023 pDisplay_->GetDefaultXScreen().getXScreen() ) )
2024 nShowState_ = SHOWSTATE_MINIMIZED;
2027 void X11SalFrame::Maximize()
2029 if( IsSysChildWindow() )
2030 return;
2032 if( SHOWSTATE_MINIMIZED == nShowState_ )
2034 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2035 XMapWindow( GetXDisplay(), GetShellWindow() );
2036 nShowState_ = SHOWSTATE_NORMAL;
2039 pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
2042 void X11SalFrame::Restore()
2044 if( IsSysChildWindow() )
2045 return;
2047 if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
2049 stderr0( "X11SalFrame::Restore on withdrawn window\n" );
2050 return;
2053 if( SHOWSTATE_MINIMIZED == nShowState_ )
2055 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2056 XMapWindow( GetXDisplay(), GetShellWindow() );
2057 nShowState_ = SHOWSTATE_NORMAL;
2060 pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false );
2063 void X11SalFrame::SetScreenNumber( unsigned int nNewScreen )
2065 if( nNewScreen == maGeometry.nDisplayScreenNumber )
2066 return;
2068 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2070 if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() )
2071 return;
2073 Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nDisplayScreenNumber] );
2074 Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] );
2075 bool bVisible = bMapped_;
2076 if( bVisible )
2077 Show( false );
2078 maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left());
2079 maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top());
2080 createNewWindow( None, m_nXScreen );
2081 if( bVisible )
2082 Show( true );
2083 maGeometry.nDisplayScreenNumber = nNewScreen;
2085 else if( nNewScreen < GetDisplay()->GetXScreenCount() )
2087 bool bVisible = bMapped_;
2088 if( bVisible )
2089 Show( false );
2090 createNewWindow( None, SalX11Screen( nNewScreen ) );
2091 if( bVisible )
2092 Show( true );
2093 maGeometry.nDisplayScreenNumber = nNewScreen;
2097 void X11SalFrame::SetApplicationID( const OUString &rWMClass )
2099 if( rWMClass != m_sWMClass && ! IsChildWindow() )
2101 m_sWMClass = rWMClass;
2102 updateWMClass();
2103 std::list< X11SalFrame* >::const_iterator it;
2104 for( it = maChildren.begin(); it != maChildren.end(); ++it )
2105 (*it)->SetApplicationID(rWMClass);
2109 void X11SalFrame::updateWMClass()
2111 XClassHint* pClass = XAllocClassHint();
2112 OString aResName = SalGenericSystem::getFrameResName();
2113 pClass->res_name = const_cast<char*>(aResName.getStr());
2115 OString aResClass = OUStringToOString(m_sWMClass, RTL_TEXTENCODING_ASCII_US);
2116 const char *pResClass = !aResClass.isEmpty() ? aResClass.getStr() :
2117 SalGenericSystem::getFrameClassName();
2119 pClass->res_class = const_cast<char*>(pResClass);
2120 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
2121 XFree( pClass );
2124 void X11SalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nScreen )
2126 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2128 if( mbFullScreen == (bool)bFullScreen )
2129 return;
2130 if( bFullScreen )
2132 maRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
2133 Size( maGeometry.nWidth, maGeometry.nHeight ) );
2134 Rectangle aRect;
2135 if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) )
2136 aRect = Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nXScreen ) );
2137 else
2138 aRect = GetDisplay()->GetXineramaScreens()[nScreen];
2139 nStyle_ |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
2140 bool bVisible = bMapped_;
2141 if( bVisible )
2142 Show( false );
2143 maGeometry.nX = aRect.Left();
2144 maGeometry.nY = aRect.Top();
2145 maGeometry.nWidth = aRect.GetWidth();
2146 maGeometry.nHeight = aRect.GetHeight();
2147 mbMaximizedHorz = mbMaximizedVert = false;
2148 mbFullScreen = true;
2149 createNewWindow( None, m_nXScreen );
2150 if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
2151 GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true );
2152 else
2153 GetDisplay()->getWMAdaptor()->showFullScreen( this, true );
2154 if( bVisible )
2155 Show(true);
2158 else
2160 mbFullScreen = false;
2161 nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
2162 bool bVisible = bMapped_;
2163 Rectangle aRect = maRestorePosSize;
2164 maRestorePosSize = Rectangle();
2165 if( bVisible )
2166 Show( false );
2167 createNewWindow( None, m_nXScreen );
2168 if( !aRect.IsEmpty() )
2169 SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
2170 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y |
2171 SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
2172 if( bVisible )
2173 Show( true );
2176 else
2178 if( nScreen < 0 || nScreen >= (int)GetDisplay()->GetXScreenCount() )
2179 nScreen = m_nXScreen.getXScreen();
2180 if( nScreen != (int)m_nXScreen.getXScreen() )
2182 bool bVisible = bMapped_;
2183 if( mbFullScreen )
2184 pDisplay_->getWMAdaptor()->showFullScreen( this, false );
2185 if( bVisible )
2186 Show( false );
2187 createNewWindow( None, SalX11Screen( nScreen ) );
2188 if( mbFullScreen )
2189 pDisplay_->getWMAdaptor()->showFullScreen( this, true );
2190 if( bVisible )
2191 Show( true );
2193 if( mbFullScreen == (bool)bFullScreen )
2194 return;
2196 pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen );
2197 if( IsOverrideRedirect()
2198 && WMSupportsFWS( GetXDisplay(), GetDisplay()->GetRootWindow( m_nXScreen ) ) )
2200 AddFwsProtocols( GetXDisplay(), GetShellWindow() );
2201 RegisterFwsWindow( GetXDisplay(), GetShellWindow() );
2206 /* ---------------------------------------------------------------------
2207 the xautolock pseudo screen saver needs special treatment since it
2208 doesn't cooperate with XxxxScreenSaver settings
2209 ------------------------------------------------------------------- */
2211 static Bool
2212 IsRunningXAutoLock( Display *p_display, XLIB_Window a_window )
2214 const char *p_atomname = "XAUTOLOCK_SEMAPHORE_PID";
2215 Atom a_pidatom;
2217 // xautolock interns this atom
2218 a_pidatom = XInternAtom( p_display, p_atomname, True );
2219 if ( a_pidatom == None )
2220 return False;
2222 Atom a_type;
2223 int n_format;
2224 unsigned long n_items;
2225 unsigned long n_bytes_after;
2226 pid_t *p_pid;
2227 pid_t n_pid;
2228 // get pid of running xautolock
2229 XGetWindowProperty (p_display, a_window, a_pidatom, 0L, 2L, False,
2230 AnyPropertyType, &a_type, &n_format, &n_items, &n_bytes_after,
2231 (unsigned char**) &p_pid );
2232 n_pid = *p_pid;
2233 XFree( p_pid );
2235 if ( a_type == XA_INTEGER )
2237 // check if xautolock pid points to a running process
2238 if ( kill(n_pid, 0) == -1 )
2239 return False;
2240 else
2241 return True;
2244 return False;
2247 /* definitions from xautolock.c (pl15) */
2248 #define XAUTOLOCK_DISABLE 1
2249 #define XAUTOLOCK_ENABLE 2
2251 static Bool
2252 MessageToXAutoLock( Display *p_display, int n_message )
2254 const char *p_atomname = "XAUTOLOCK_MESSAGE" ;
2255 Atom a_messageatom;
2256 XLIB_Window a_rootwindow;
2258 a_rootwindow = RootWindowOfScreen( ScreenOfDisplay(p_display, 0) );
2259 if ( ! IsRunningXAutoLock(p_display, a_rootwindow) )
2261 // remove any pending messages
2262 a_messageatom = XInternAtom( p_display, p_atomname, True );
2263 if ( a_messageatom != None )
2264 XDeleteProperty( p_display, a_rootwindow, a_messageatom );
2265 return False;
2268 a_messageatom = XInternAtom( p_display, p_atomname, False );
2269 XChangeProperty (p_display, a_rootwindow, a_messageatom, XA_INTEGER,
2270 8, PropModeReplace, (unsigned char*)&n_message, sizeof(n_message) );
2272 return True;
2275 void X11SalFrame::StartPresentation( bool bStart )
2277 I18NStatus::get().show( !bStart, I18NStatus::presentation );
2278 if ( bStart )
2279 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_DISABLE );
2280 else
2281 MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_ENABLE );
2283 if( ! bStart && hPresentationWindow != None )
2284 doReparentPresentationDialogues( GetDisplay() );
2285 hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None;
2287 // needs static here to save DPMS settings
2288 int dummy;
2289 static bool DPMSExtensionAvailable =
2290 #if !defined(SOLARIS) && !defined(AIX)
2291 (DPMSQueryExtension(GetXDisplay(), &dummy, &dummy) != 0);
2292 static sal_Bool DPMSEnabled = false;
2293 #else
2294 false;
2295 bool DPMSEnabled = false;
2296 (void)dummy;
2297 #define CARD16 unsigned short
2298 #endif
2299 static CARD16 dpms_standby_timeout=0;
2300 static CARD16 dpms_suspend_timeout=0;
2301 static CARD16 dpms_off_timeout=0;
2303 if( bStart || nScreenSaversTimeout_ || DPMSEnabled)
2305 if( hPresentationWindow )
2307 /* #i10559# workaround for WindowMaker: try to restore
2308 * current focus after presentation window is gone
2310 int revert_to = 0;
2311 XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to );
2313 int timeout, interval, prefer_blanking, allow_exposures;
2314 XGetScreenSaver( GetXDisplay(),
2315 &timeout,
2316 &interval,
2317 &prefer_blanking,
2318 &allow_exposures );
2320 // get the DPMS state right before the start
2321 if (DPMSExtensionAvailable)
2323 #if !defined(SOLARIS) && !defined(AIX)
2324 CARD16 state; // card16 is defined in Xdm.h
2325 DPMSInfo( GetXDisplay(),
2326 &state,
2327 &DPMSEnabled);
2328 #endif
2330 if( bStart ) // start show
2332 if ( timeout )
2334 nScreenSaversTimeout_ = timeout;
2335 XResetScreenSaver( GetXDisplay() );
2336 XSetScreenSaver( GetXDisplay(),
2338 interval,
2339 prefer_blanking,
2340 allow_exposures );
2342 #if !defined(SOLARIS) && !defined(AIX)
2343 if( DPMSEnabled )
2345 if ( DPMSExtensionAvailable )
2347 DPMSGetTimeouts( GetXDisplay(),
2348 &dpms_standby_timeout,
2349 &dpms_suspend_timeout,
2350 &dpms_off_timeout);
2351 DPMSSetTimeouts(GetXDisplay(), 0,0,0);
2354 #endif
2356 else
2358 if( nScreenSaversTimeout_ )
2360 XSetScreenSaver( GetXDisplay(),
2361 nScreenSaversTimeout_,
2362 interval,
2363 prefer_blanking,
2364 allow_exposures );
2365 nScreenSaversTimeout_ = 0;
2367 #if !defined(SOLARIS) && !defined(AIX)
2368 if ( DPMSEnabled )
2370 if ( DPMSExtensionAvailable )
2372 // restore timeouts
2373 DPMSSetTimeouts(GetXDisplay(), dpms_standby_timeout,
2374 dpms_suspend_timeout, dpms_off_timeout);
2377 #endif
2382 // Pointer
2384 void X11SalFrame::SetPointer( PointerStyle ePointerStyle )
2386 hCursor_ = pDisplay_->GetPointer( ePointerStyle );
2387 XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ );
2389 if( IsCaptured() || nVisibleFloats > 0 )
2390 XChangeActivePointerGrab( GetXDisplay(),
2391 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
2392 hCursor_,
2393 CurrentTime );
2396 void X11SalFrame::SetPointerPos(long nX, long nY)
2398 /* when the application tries to center the mouse in the dialog the
2399 * window isn't mapped already. So use coordinates relative to the root window.
2401 unsigned int nWindowLeft = maGeometry.nX + nX;
2402 unsigned int nWindowTop = maGeometry.nY + nY;
2404 XWarpPointer( GetXDisplay(), None, pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() ),
2405 0, 0, 0, 0, nWindowLeft, nWindowTop);
2408 // delay handling of extended text input
2409 #if !defined(__synchronous_extinput__)
2410 void
2411 X11SalFrame::HandleExtTextEvent (XClientMessageEvent *pEvent)
2413 #if SAL_TYPES_SIZEOFLONG > 4
2414 void* pExtTextEvent = (void*)( (pEvent->data.l[0] & 0xffffffff)
2415 | (pEvent->data.l[1] << 32) );
2416 #else
2417 void* pExtTextEvent = (void*)(pEvent->data.l[0]);
2418 #endif
2419 sal_uInt16 nExtTextEventType = sal_uInt16(pEvent->data.l[2]);
2421 CallCallback(nExtTextEventType, pExtTextEvent);
2423 switch (nExtTextEventType)
2425 case SALEVENT_ENDEXTTEXTINPUT:
2426 break;
2428 case SALEVENT_EXTTEXTINPUT:
2429 break;
2431 default:
2433 fprintf(stderr, "X11SalFrame::HandleExtTextEvent: invalid extended input\n");
2436 #endif /* defined(__synchronous_extinput__) */
2438 // PostEvent
2440 bool X11SalFrame::PostEvent( void *pData )
2442 GetDisplay()->SendInternalEvent( this, pData );
2443 return true;
2446 // Title
2448 void X11SalFrame::SetTitle( const OUString& rTitle )
2450 if( ! ( IsChildWindow() || (nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) )
2452 m_aTitle = rTitle;
2453 GetDisplay()->getWMAdaptor()->setWMName( this, rTitle );
2457 void X11SalFrame::Flush()
2459 XFlush( GetDisplay()->GetDisplay() );
2462 void X11SalFrame::Sync()
2464 XSync( GetDisplay()->GetDisplay(), False );
2467 // Keyboard
2469 void X11SalFrame::SetInputContext( SalInputContext* pContext )
2471 if (pContext == NULL)
2472 return;
2474 // 1. We should create an input context for this frame
2475 // only when SAL_INPUTCONTEXT_TEXT is set.
2477 if (!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT))
2479 if( mpInputContext )
2480 mpInputContext->Unmap( this );
2481 return;
2484 // 2. We should use on-the-spot inputstyle
2485 // only when SAL_INPUTCONTEXT_EXTTEXTINPUT is set.
2487 if (mpInputContext == NULL)
2489 I18NStatus& rStatus( I18NStatus::get() );
2490 rStatus.setParent( this );
2491 mpInputContext = new SalI18N_InputContext( this );
2492 if (mpInputContext->UseContext())
2494 mpInputContext->ExtendEventMask( GetShellWindow() );
2495 if (pContext->mnOptions & SAL_INPUTCONTEXT_CHANGELANGUAGE)
2496 mpInputContext->SetLanguage(pContext->meLanguage);
2497 if (mbInputFocus)
2498 mpInputContext->SetICFocus( this );
2501 else
2502 mpInputContext->Map( this );
2503 return;
2506 void X11SalFrame::EndExtTextInput( sal_uInt16 nFlags )
2508 if (mpInputContext != NULL)
2509 mpInputContext->EndExtTextInput( nFlags );
2512 OUString X11SalFrame::GetKeyName( sal_uInt16 nKeyCode )
2514 return GetDisplay()->GetKeyName( nKeyCode );
2517 bool X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
2519 // not supported yet
2520 return false;
2523 LanguageType X11SalFrame::GetInputLanguage()
2525 // could be improved by checking unicode ranges of the last input
2526 return LANGUAGE_DONTKNOW;
2529 // Settings
2531 void X11SalFrame::UpdateSettings( AllSettings& rSettings )
2533 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2534 aStyleSettings.SetCursorBlinkTime( 500 );
2535 aStyleSettings.SetMenuBarTextColor( aStyleSettings.GetPersonaMenuBarTextColor().get_value_or( Color( COL_BLACK ) ) );
2536 rSettings.SetStyleSettings( aStyleSettings );
2539 void X11SalFrame::CaptureMouse( bool bCapture )
2541 nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : NULL );
2544 void X11SalFrame::SetParent( SalFrame* pNewParent )
2546 if( mpParent != pNewParent )
2548 if( mpParent )
2549 mpParent->maChildren.remove( this );
2551 mpParent = static_cast<X11SalFrame*>(pNewParent);
2552 mpParent->maChildren.push_back( this );
2553 if( mpParent->m_nXScreen != m_nXScreen )
2554 createNewWindow( None, mpParent->m_nXScreen );
2555 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2559 SalFrame* X11SalFrame::GetParent() const
2561 return mpParent;
2564 void X11SalFrame::createNewWindow( XLIB_Window aNewParent, SalX11Screen nXScreen )
2566 bool bWasVisible = bMapped_;
2567 if( bWasVisible )
2568 Show( false );
2570 if( nXScreen.getXScreen() >= GetDisplay()->GetXScreenCount() )
2571 nXScreen = m_nXScreen;
2573 SystemParentData aParentData;
2574 aParentData.aWindow = aNewParent;
2575 aParentData.bXEmbedSupport = (aNewParent != None && m_bXEmbed); // caution: this is guesswork
2576 if( aNewParent == None )
2578 aNewParent = GetDisplay()->GetRootWindow(nXScreen);
2579 aParentData.aWindow = None;
2580 m_bXEmbed = false;
2582 else
2584 // is new parent a root window ?
2585 Display* pDisp = GetDisplay()->GetDisplay();
2586 int nScreens = GetDisplay()->GetXScreenCount();
2587 for( int i = 0; i < nScreens; i++ )
2589 if( aNewParent == RootWindow( pDisp, i ) )
2591 nXScreen = SalX11Screen( i );
2592 aParentData.aWindow = None;
2593 m_bXEmbed = false;
2594 break;
2599 // first deinit frame
2600 updateGraphics(true);
2601 if( mpInputContext )
2603 mpInputContext->UnsetICFocus( this );
2604 mpInputContext->Unmap( this );
2606 if( GetWindow() == hPresentationWindow )
2608 hPresentationWindow = None;
2609 doReparentPresentationDialogues( GetDisplay() );
2611 XDestroyWindow( GetXDisplay(), mhWindow );
2612 mhWindow = None;
2614 // now init with new parent again
2615 if ( aParentData.aWindow != None )
2616 Init( nStyle_ | SAL_FRAME_STYLE_PLUG, nXScreen, &aParentData );
2617 else
2618 Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nXScreen, NULL, true );
2620 // update graphics if necessary
2621 updateGraphics(false);
2623 if( ! m_aTitle.isEmpty() )
2624 SetTitle( m_aTitle );
2626 if( mpParent )
2628 if( mpParent->m_nXScreen != m_nXScreen )
2629 SetParent( NULL );
2630 else
2631 pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2634 if( bWasVisible )
2635 Show( true );
2637 std::list< X11SalFrame* > aChildren = maChildren;
2638 for( std::list< X11SalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
2639 (*it)->createNewWindow( None, m_nXScreen );
2641 // FIXME: SalObjects
2644 bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent )
2646 if( pNewParent->nSize >= sizeof(SystemParentData) )
2647 m_bXEmbed = pNewParent->aWindow != None && pNewParent->bXEmbedSupport;
2649 createNewWindow(pNewParent->aWindow);
2651 return true;
2654 // Sound
2655 void X11SalFrame::Beep()
2657 GetDisplay()->Beep();
2660 // Event Handling
2662 static sal_uInt16 sal_GetCode( int state )
2664 sal_uInt16 nCode = 0;
2666 if( state & Button1Mask )
2667 nCode |= MOUSE_LEFT;
2668 if( state & Button2Mask )
2669 nCode |= MOUSE_MIDDLE;
2670 if( state & Button3Mask )
2671 nCode |= MOUSE_RIGHT;
2673 if( state & ShiftMask )
2674 nCode |= KEY_SHIFT;
2675 if( state & ControlMask )
2676 nCode |= KEY_MOD1;
2677 if( state & Mod1Mask )
2678 nCode |= KEY_MOD2;
2680 // Map Meta/Super modifier to MOD3 on all Unix systems
2681 // except Mac OS X
2682 if( (state & Mod3Mask) )
2683 nCode |= KEY_MOD3;
2685 return nCode;
2688 SalFrame::SalPointerState X11SalFrame::GetPointerState()
2690 SalPointerState aState;
2691 XLIB_Window aRoot, aChild;
2692 int rx, ry, wx, wy;
2693 unsigned int nMask = 0;
2694 XQueryPointer( GetXDisplay(),
2695 GetShellWindow(),
2696 &aRoot,
2697 &aChild,
2698 &rx, &ry,
2699 &wx, &wy,
2700 &nMask
2703 aState.maPos = Point(wx, wy);
2704 aState.mnState = sal_GetCode( nMask );
2705 return aState;
2708 SalFrame::SalIndicatorState X11SalFrame::GetIndicatorState()
2710 SalIndicatorState aState;
2711 aState.mnState = GetGenericData()->GetSalDisplay()->GetIndicatorState();
2712 return aState;
2715 void X11SalFrame::SimulateKeyPress( sal_uInt16 nKeyCode )
2717 GetGenericData()->GetSalDisplay()->SimulateKeyPress(nKeyCode);
2720 long X11SalFrame::HandleMouseEvent( XEvent *pEvent )
2722 SalMouseEvent aMouseEvt = {0, 0, 0, 0, 0};
2723 sal_uInt16 nEvent = 0;
2724 bool bClosePopups = false;
2726 if( nVisibleFloats && pEvent->type == EnterNotify )
2727 return 0;
2729 // Solaris X86: clicking the right button on a two-button mouse
2730 // generates a button2 event not a button3 event
2731 if (pDisplay_->GetProperties() & PROPERTY_SUPPORT_3ButtonMouse )
2733 switch (pEvent->type)
2735 case EnterNotify:
2736 case LeaveNotify:
2737 if ( pEvent->xcrossing.state & Button2Mask )
2739 pEvent->xcrossing.state &= ~Button2Mask;
2740 pEvent->xcrossing.state |= Button3Mask;
2742 break;
2744 case MotionNotify:
2745 if ( pEvent->xmotion.state & Button2Mask )
2747 pEvent->xmotion.state &= ~Button2Mask;
2748 pEvent->xmotion.state |= Button3Mask;
2750 break;
2752 default:
2753 if ( Button2 == pEvent->xbutton.button )
2755 pEvent->xbutton.state &= ~Button2Mask;
2756 pEvent->xbutton.state |= Button3Mask;
2757 pEvent->xbutton.button = Button3;
2759 break;
2763 if( LeaveNotify == pEvent->type || EnterNotify == pEvent->type )
2766 * some WMs (and/or) applications have a passive grab on
2767 * mouse buttons (XGrabButton). This leads to enter/leave notifies
2768 * with mouse buttons pressed in the state mask before the actual
2769 * ButtonPress event gets dispatched. But EnterNotify
2770 * is reported in vcl as MouseMove event. Some office code
2771 * decides that a pressed button in a MouseMove belongs to
2772 * a drag operation which leads to doing things differently.
2774 * ignore Enter/LeaveNotify resulting from grabs so that
2775 * help windows do not disappear just after appearing
2777 * hopefully this workaround will not break anything.
2779 if( pEvent->xcrossing.mode == NotifyGrab || pEvent->xcrossing.mode == NotifyUngrab )
2780 return 0;
2782 aMouseEvt.mnX = pEvent->xcrossing.x;
2783 aMouseEvt.mnY = pEvent->xcrossing.y;
2784 aMouseEvt.mnTime = pEvent->xcrossing.time;
2785 aMouseEvt.mnCode = sal_GetCode( pEvent->xcrossing.state );
2786 aMouseEvt.mnButton = 0;
2788 nEvent = LeaveNotify == pEvent->type
2789 ? SALEVENT_MOUSELEAVE
2790 : SALEVENT_MOUSEMOVE;
2792 else if( pEvent->type == MotionNotify )
2794 aMouseEvt.mnX = pEvent->xmotion.x;
2795 aMouseEvt.mnY = pEvent->xmotion.y;
2796 aMouseEvt.mnTime = pEvent->xmotion.time;
2797 aMouseEvt.mnCode = sal_GetCode( pEvent->xmotion.state );
2799 aMouseEvt.mnButton = 0;
2801 nEvent = SALEVENT_MOUSEMOVE;
2802 if( nVisibleFloats > 0 && mpParent )
2804 XLIB_Cursor aCursor = mpParent->GetCursor();
2805 if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < (int)maGeometry.nWidth &&
2806 pEvent->xmotion.y >= 0 && pEvent->xmotion.y < (int)maGeometry.nHeight )
2807 aCursor = None;
2809 XChangeActivePointerGrab( GetXDisplay(),
2810 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
2811 aCursor,
2812 CurrentTime );
2815 else
2817 // let mouse events reach the correct window
2818 if( nVisibleFloats < 1 )
2820 if( ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
2821 XUngrabPointer( GetXDisplay(), CurrentTime );
2823 else if( pEvent->type == ButtonPress )
2825 // see if the user clicks outside all of the floats
2826 // if yes release the grab
2827 bool bInside = false;
2828 const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
2829 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
2831 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
2832 if( pFrame->IsFloatGrabWindow() &&
2833 pFrame->bMapped_ &&
2834 pEvent->xbutton.x_root >= pFrame->maGeometry.nX &&
2835 pEvent->xbutton.x_root < pFrame->maGeometry.nX + (int)pFrame->maGeometry.nWidth &&
2836 pEvent->xbutton.y_root >= pFrame->maGeometry.nY &&
2837 pEvent->xbutton.y_root < pFrame->maGeometry.nY + (int)pFrame->maGeometry.nHeight )
2839 bInside = true;
2840 break;
2843 if( ! bInside )
2845 // need not take care of the XUngrabPointer in Show( false )
2846 // because XUngrabPointer does not produce errors if pointer
2847 // is not grabbed
2848 XUngrabPointer( GetXDisplay(), CurrentTime );
2849 bClosePopups = true;
2851 /* #i15246# only close popups if pointer is outside all our frames
2852 * cannot use our own geometry data here because stacking
2853 * is unknown (the above case implicitly assumes
2854 * that floats are on top which should be true)
2856 XLIB_Window aRoot, aChild;
2857 int root_x, root_y, win_x, win_y;
2858 unsigned int mask_return;
2859 if( XQueryPointer( GetXDisplay(),
2860 GetDisplay()->GetRootWindow( m_nXScreen ),
2861 &aRoot, &aChild,
2862 &root_x, &root_y,
2863 &win_x, &win_y,
2864 &mask_return )
2865 && aChild // pointer may not be in any child
2868 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
2870 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
2871 if( ! pFrame->IsFloatGrabWindow()
2872 && ( pFrame->GetWindow() == aChild ||
2873 pFrame->GetShellWindow() == aChild ||
2874 pFrame->GetStackingWindow() == aChild )
2877 // #i63638# check that pointer is inside window, not
2878 // only inside stacking window
2879 if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) &&
2880 root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) )
2882 bClosePopups = false;
2884 break;
2891 if( m_bXEmbed && pEvent->xbutton.button == Button1 )
2892 askForXEmbedFocus( pEvent->xbutton.time );
2894 if( pEvent->xbutton.button == Button1 ||
2895 pEvent->xbutton.button == Button2 ||
2896 pEvent->xbutton.button == Button3 )
2898 aMouseEvt.mnX = pEvent->xbutton.x;
2899 aMouseEvt.mnY = pEvent->xbutton.y;
2900 aMouseEvt.mnTime = pEvent->xbutton.time;
2901 aMouseEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
2903 if( Button1 == pEvent->xbutton.button )
2904 aMouseEvt.mnButton = MOUSE_LEFT;
2905 else if( Button2 == pEvent->xbutton.button )
2906 aMouseEvt.mnButton = MOUSE_MIDDLE;
2907 else if( Button3 == pEvent->xbutton.button )
2908 aMouseEvt.mnButton = MOUSE_RIGHT;
2910 nEvent = ButtonPress == pEvent->type
2911 ? SALEVENT_MOUSEBUTTONDOWN
2912 : SALEVENT_MOUSEBUTTONUP;
2914 else if( pEvent->xbutton.button == Button4 ||
2915 pEvent->xbutton.button == Button5 ||
2916 pEvent->xbutton.button == Button6 ||
2917 pEvent->xbutton.button == Button7 )
2919 const bool bIncrement(
2920 pEvent->xbutton.button == Button4 ||
2921 pEvent->xbutton.button == Button6 );
2922 const bool bHoriz(
2923 pEvent->xbutton.button == Button6 ||
2924 pEvent->xbutton.button == Button7 );
2926 if( pEvent->type == ButtonRelease )
2927 return 0;
2929 static sal_uLong nLines = 0;
2930 if( ! nLines )
2932 char* pEnv = getenv( "SAL_WHEELLINES" );
2933 nLines = pEnv ? atoi( pEnv ) : 3;
2934 if( nLines > 10 )
2935 nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
2938 SalWheelMouseEvent aWheelEvt;
2939 aWheelEvt.mnTime = pEvent->xbutton.time;
2940 aWheelEvt.mnX = pEvent->xbutton.x;
2941 aWheelEvt.mnY = pEvent->xbutton.y;
2942 aWheelEvt.mnDelta = bIncrement ? 120 : -120;
2943 aWheelEvt.mnNotchDelta = bIncrement ? 1 : -1;
2944 aWheelEvt.mnScrollLines = nLines;
2945 aWheelEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
2946 aWheelEvt.mbHorz = bHoriz;
2948 nEvent = SALEVENT_WHEELMOUSE;
2950 // --- RTL --- (mirror mouse pos)
2951 if( Application::GetSettings().GetLayoutRTL() )
2952 aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX;
2953 return CallCallback( nEvent, &aWheelEvt );
2957 int nRet = 0;
2958 if( nEvent == SALEVENT_MOUSELEAVE
2959 || ( aMouseEvt.mnX < nWidth_ && aMouseEvt.mnX > -1 &&
2960 aMouseEvt.mnY < nHeight_ && aMouseEvt.mnY > -1 )
2961 || pDisplay_->MouseCaptured( this )
2964 // --- RTL --- (mirror mouse pos)
2965 if( Application::GetSettings().GetLayoutRTL() )
2966 aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX;
2967 nRet = CallCallback( nEvent, &aMouseEvt );
2970 if( bClosePopups )
2972 /* #108213# close popups after dispatching the event outside the popup;
2973 * applications do weird things.
2975 ImplSVData* pSVData = ImplGetSVData();
2976 if ( pSVData->maWinData.mpFirstFloat )
2978 static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
2979 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) )
2980 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
2984 return nRet;
2987 // F10 means either KEY_F10 or KEY_MENU, which has to be decided
2988 // in the independent part.
2989 struct KeyAlternate
2991 sal_uInt16 nKeyCode;
2992 sal_Unicode nCharCode;
2993 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
2994 KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
2997 inline KeyAlternate
2998 GetAlternateKeyCode( const sal_uInt16 nKeyCode )
3000 KeyAlternate aAlternate;
3002 switch( nKeyCode )
3004 case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
3005 case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
3008 return aAlternate;
3011 void X11SalFrame::beginUnicodeSequence()
3013 OUString& rSeq( GetGenericData()->GetUnicodeCommand() );
3014 DeletionListener aDeleteWatch( this );
3016 if( !rSeq.isEmpty() )
3017 endUnicodeSequence();
3019 rSeq = "u";
3021 if( ! aDeleteWatch.isDeleted() )
3023 sal_uInt16 nTextAttr = EXTTEXTINPUT_ATTR_UNDERLINE;
3024 SalExtTextInputEvent aEv;
3025 aEv.mnTime = 0;
3026 aEv.maText = rSeq;
3027 aEv.mpTextAttr = &nTextAttr;
3028 aEv.mnCursorPos = 0;
3029 aEv.mnCursorFlags = 0;
3030 aEv.mbOnlyCursor = false;
3032 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
3036 bool X11SalFrame::appendUnicodeSequence( sal_Unicode c )
3038 bool bRet = false;
3039 OUString& rSeq( GetGenericData()->GetUnicodeCommand() );
3040 if( !rSeq.isEmpty() )
3042 // range check
3043 if( (c >= '0' && c <= '9') ||
3044 (c >= 'a' && c <= 'f') ||
3045 (c >= 'A' && c <= 'F') )
3047 OUStringBuffer aBuf( rSeq.getLength() + 1 );
3048 aBuf.append( rSeq );
3049 aBuf.append( c );
3050 rSeq = aBuf.makeStringAndClear();
3051 std::vector<sal_uInt16> attribs( rSeq.getLength(), EXTTEXTINPUT_ATTR_UNDERLINE );
3053 SalExtTextInputEvent aEv;
3054 aEv.mnTime = 0;
3055 aEv.maText = rSeq;
3056 aEv.mpTextAttr = &attribs[0];
3057 aEv.mnCursorPos = 0;
3058 aEv.mnCursorFlags = 0;
3059 aEv.mbOnlyCursor = false;
3061 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
3062 bRet = true;
3064 else
3065 bRet = endUnicodeSequence();
3067 else
3068 endUnicodeSequence();
3069 return bRet;
3072 bool X11SalFrame::endUnicodeSequence()
3074 OUString& rSeq( GetGenericData()->GetUnicodeCommand() );
3076 DeletionListener aDeleteWatch( this );
3077 if( rSeq.getLength() > 1 && rSeq.getLength() < 6 )
3079 // cut the "u"
3080 OUString aNumbers( rSeq.copy( 1 ) );
3081 sal_uInt32 nValue = aNumbers.toUInt32( 16 );
3082 if( nValue >= 32 )
3084 sal_uInt16 nTextAttr = EXTTEXTINPUT_ATTR_UNDERLINE;
3085 SalExtTextInputEvent aEv;
3086 aEv.mnTime = 0;
3087 aEv.maText = OUString( sal_Unicode(nValue) );
3088 aEv.mpTextAttr = &nTextAttr;
3089 aEv.mnCursorPos = 0;
3090 aEv.mnCursorFlags = 0;
3091 aEv.mbOnlyCursor = false;
3092 CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
3095 bool bWasInput = !rSeq.isEmpty();
3096 rSeq = OUString();
3097 if( bWasInput && ! aDeleteWatch.isDeleted() )
3098 CallCallback(SALEVENT_ENDEXTTEXTINPUT, NULL);
3099 return bWasInput;
3102 long X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent )
3104 KeySym nKeySym;
3105 KeySym nUnmodifiedKeySym;
3106 int nLen = 2048;
3107 unsigned char *pPrintable = (unsigned char*)alloca( nLen );
3109 // singlebyte code composed by input method, the new default
3110 if (mpInputContext != NULL && mpInputContext->UseContext())
3112 // returns a keysym as well as the pPrintable (in system encoding)
3113 // printable may be empty.
3114 Status nStatus;
3115 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3116 &nUnmodifiedKeySym,
3117 &nStatus, mpInputContext->GetContext() );
3118 if ( nStatus == XBufferOverflow )
3120 nLen *= 2;
3121 pPrintable = (unsigned char*)alloca( nLen );
3122 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3123 &nUnmodifiedKeySym,
3124 &nStatus, mpInputContext->GetContext() );
3127 else
3129 // fallback, this should never ever be called
3130 Status nStatus = 0;
3131 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus );
3134 SalKeyEvent aKeyEvt;
3135 sal_uInt16 nKeyCode;
3136 sal_uInt16 nModCode = 0;
3137 char aDummy;
3139 if( pEvent->state & ShiftMask )
3140 nModCode |= KEY_SHIFT;
3141 if( pEvent->state & ControlMask )
3142 nModCode |= KEY_MOD1;
3143 if( pEvent->state & Mod1Mask )
3144 nModCode |= KEY_MOD2;
3146 if( nModCode != (KEY_SHIFT|KEY_MOD1) )
3147 endUnicodeSequence();
3149 if( nKeySym == XK_Shift_L || nKeySym == XK_Shift_R
3150 || nKeySym == XK_Control_L || nKeySym == XK_Control_R
3151 || nKeySym == XK_Alt_L || nKeySym == XK_Alt_R
3152 || nKeySym == XK_Meta_L || nKeySym == XK_Meta_R
3153 || nKeySym == XK_Super_L || nKeySym == XK_Super_R )
3155 SalKeyModEvent aModEvt;
3156 aModEvt.mnModKeyCode = 0;
3157 if( pEvent->type == XLIB_KeyPress && mnExtKeyMod == 0 )
3158 mbSendExtKeyModChange = true;
3159 else if( pEvent->type == KeyRelease && mbSendExtKeyModChange )
3161 aModEvt.mnModKeyCode = mnExtKeyMod;
3162 mnExtKeyMod = 0;
3165 // pressing just the ctrl key leads to a keysym of XK_Control but
3166 // the event state does not contain ControlMask. In the release
3167 // event its the other way round: it does contain the Control mask.
3168 // The modifier mode therefore has to be adapted manually.
3169 sal_uInt16 nExtModMask = 0;
3170 sal_uInt16 nModMask = 0;
3171 switch( nKeySym )
3173 case XK_Control_L:
3174 nExtModMask = MODKEY_LMOD1;
3175 nModMask = KEY_MOD1;
3176 break;
3177 case XK_Control_R:
3178 nExtModMask = MODKEY_RMOD1;
3179 nModMask = KEY_MOD1;
3180 break;
3181 case XK_Alt_L:
3182 nExtModMask = MODKEY_LMOD2;
3183 nModMask = KEY_MOD2;
3184 break;
3185 case XK_Alt_R:
3186 nExtModMask = MODKEY_RMOD2;
3187 nModMask = KEY_MOD2;
3188 break;
3189 case XK_Shift_L:
3190 nExtModMask = MODKEY_LSHIFT;
3191 nModMask = KEY_SHIFT;
3192 break;
3193 case XK_Shift_R:
3194 nExtModMask = MODKEY_RSHIFT;
3195 nModMask = KEY_SHIFT;
3196 break;
3197 // Map Meta/Super keys to MOD3 modifier on all Unix systems
3198 // except Mac OS X
3199 case XK_Meta_L:
3200 case XK_Super_L:
3201 nExtModMask = MODKEY_LMOD3;
3202 nModMask = KEY_MOD3;
3203 break;
3204 case XK_Meta_R:
3205 case XK_Super_R:
3206 nExtModMask = MODKEY_RMOD3;
3207 nModMask = KEY_MOD3;
3208 break;
3210 if( pEvent->type == KeyRelease )
3212 nModCode &= ~nModMask;
3213 mnExtKeyMod &= ~nExtModMask;
3215 else
3217 nModCode |= nModMask;
3218 mnExtKeyMod |= nExtModMask;
3221 aModEvt.mnCode = nModCode;
3222 aModEvt.mnTime = pEvent->time;
3224 int nRet = CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3226 return nRet;
3229 mbSendExtKeyModChange = false;
3231 // try to figure out the vcl code for the keysym
3232 // #i52338# use the unmodified KeySym if there is none for the real KeySym
3233 // because the independent part has only keycodes for unshifted keys
3234 nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy );
3235 if( nKeyCode == 0 )
3236 nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
3238 // try to figure out a printable if XmbLookupString returns only a keysym
3239 // and NOT a printable. Do not store it in pPrintable[0] since it is expected to
3240 // be in system encoding, not unicode.
3241 // #i8988##, if KeySym and printable look equally promising then prefer KeySym
3242 // the printable is bound to the encoding so the KeySym might contain more
3243 // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and
3244 // (the desired) Zcaron in KeySym
3245 sal_Unicode nKeyString = 0x0;
3246 if ( (nLen == 0)
3247 || ((nLen == 1) && (nKeySym > 0)) )
3248 nKeyString = KeysymToUnicode (nKeySym);
3249 // if we have nothing we give up
3250 if( !nKeyCode && !nLen && !nKeyString)
3251 return 0;
3253 DeletionListener aDeleteWatch( this );
3255 if( nModCode == (KEY_SHIFT | KEY_MOD1) && pEvent->type == XLIB_KeyPress )
3257 sal_uInt16 nSeqKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
3258 if( nSeqKeyCode == KEY_U )
3260 beginUnicodeSequence();
3261 return 1;
3263 else if( nSeqKeyCode >= KEY_0 && nSeqKeyCode <= KEY_9 )
3265 if( appendUnicodeSequence( sal_Unicode( '0' ) + sal_Unicode(nSeqKeyCode - KEY_0) ) )
3266 return 1;
3268 else if( nSeqKeyCode >= KEY_A && nSeqKeyCode <= KEY_F )
3270 if( appendUnicodeSequence( sal_Unicode( 'a' ) + sal_Unicode(nSeqKeyCode - KEY_A) ) )
3271 return 1;
3273 else
3274 endUnicodeSequence();
3277 if( aDeleteWatch.isDeleted() )
3278 return 0;
3280 rtl_TextEncoding nEncoding = osl_getThreadTextEncoding();
3282 sal_Unicode *pBuffer;
3283 sal_Unicode *pString;
3284 sal_Size nBufferSize = nLen * 2;
3285 sal_Size nSize;
3286 pBuffer = (sal_Unicode*) malloc( nBufferSize + 2 );
3287 pBuffer[ 0 ] = 0;
3289 if (nKeyString != 0)
3291 pString = &nKeyString;
3292 nSize = 1;
3294 else if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE)
3296 // create text converter
3297 rtl_TextToUnicodeConverter aConverter =
3298 rtl_createTextToUnicodeConverter( nEncoding );
3299 rtl_TextToUnicodeContext aContext =
3300 rtl_createTextToUnicodeContext( aConverter );
3302 sal_uInt32 nConversionInfo;
3303 sal_Size nConvertedChars;
3305 // convert to single byte text stream
3306 nSize = rtl_convertTextToUnicode(
3307 aConverter, aContext,
3308 (char*)pPrintable, nLen,
3309 pBuffer, nBufferSize,
3310 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
3311 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE,
3312 &nConversionInfo, &nConvertedChars );
3314 // destroy converter
3315 rtl_destroyTextToUnicodeContext( aConverter, aContext );
3316 rtl_destroyTextToUnicodeConverter( aConverter );
3318 pString = pBuffer;
3320 else if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */)
3322 pString = (sal_Unicode*)pPrintable;
3323 nSize = nLen;
3325 else
3327 pString = pBuffer;
3328 nSize = 0;
3331 if ( mpInputContext != NULL
3332 && mpInputContext->UseContext()
3333 && KeyRelease != pEvent->type
3334 && ( (nSize > 1)
3335 || (nSize > 0 && mpInputContext->IsPreeditMode())) )
3337 mpInputContext->CommitKeyEvent(pString, nSize);
3339 else
3340 // normal single character keyinput
3342 aKeyEvt.mnCode = nKeyCode | nModCode;
3343 aKeyEvt.mnRepeat = 0;
3344 aKeyEvt.mnTime = pEvent->time;
3345 aKeyEvt.mnCharCode = pString[ 0 ];
3347 if( KeyRelease == pEvent->type )
3349 CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3351 else
3353 if ( ! CallCallback(SALEVENT_KEYINPUT, &aKeyEvt) )
3355 // independent layer doesn't want to handle key-event, so check
3356 // whether the keycode may have an alternate meaning
3357 KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode );
3358 if ( aAlternate.nKeyCode != 0 )
3360 aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode;
3361 if( aAlternate.nCharCode )
3362 aKeyEvt.mnCharCode = aAlternate.nCharCode;
3363 CallCallback(SALEVENT_KEYINPUT, &aKeyEvt);
3369 // update the spot location for PreeditPosition IME style
3371 if (! aDeleteWatch.isDeleted())
3373 if (mpInputContext != NULL && mpInputContext->UseContext())
3374 mpInputContext->UpdateSpotLocation();
3377 free (pBuffer);
3378 return True;
3381 long X11SalFrame::HandleFocusEvent( XFocusChangeEvent *pEvent )
3383 // ReflectionX in Windows mode changes focus while mouse is grabbed
3384 if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName().equalsAscii( "ReflectionX Windows" ) )
3385 return 1;
3387 /* ignore focusout resulting from keyboard grabs
3388 * we do not grab it and are not interested when
3389 * someone else does CDE e.g. does a XGrabKey on arrow keys
3390 * handle focus events with mode NotifyWhileGrabbed
3391 * because with CDE alt-tab focus changing we do not get
3392 * normal focus events
3393 * cast focus event to the input context, otherwise the
3394 * status window does not follow the application frame
3397 if ( mpInputContext != NULL )
3399 if( FocusIn == pEvent->type )
3400 mpInputContext->SetICFocus( this );
3401 else
3404 * do not unset the IC focuse here because would kill
3405 * a lookup choice windows that might have the focus now
3406 * mpInputContext->UnsetICFocus( this );
3408 I18NStatus::get().show( false, I18NStatus::focus );
3412 if ( pEvent->mode == NotifyNormal || pEvent->mode == NotifyWhileGrabbed ||
3413 ( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
3416 if( hPresentationWindow != None && hPresentationWindow != GetShellWindow() )
3417 return 0;
3419 if( FocusIn == pEvent->type )
3421 GetSalData()->m_pInstance->updatePrinterUpdate();
3422 mbInputFocus = True;
3423 ImplSVData* pSVData = ImplGetSVData();
3425 long nRet = CallCallback( SALEVENT_GETFOCUS, 0 );
3426 if ((mpParent != NULL && nStyle_ == 0)
3427 && pSVData->maWinData.mpFirstFloat )
3429 sal_uLong nMode = pSVData->maWinData.mpFirstFloat->GetPopupModeFlags();
3430 pSVData->maWinData.mpFirstFloat->SetPopupModeFlags(
3431 nMode & ~(FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE));
3433 return nRet;
3435 else
3437 mbInputFocus = False;
3438 mbSendExtKeyModChange = false;
3439 mnExtKeyMod = 0;
3440 return CallCallback( SALEVENT_LOSEFOCUS, 0 );
3444 return 0;
3447 long X11SalFrame::HandleExposeEvent( XEvent *pEvent )
3449 XRectangle aRect = { 0, 0, 0, 0 };
3450 sal_uInt16 nCount = 0;
3452 if( pEvent->type == Expose )
3454 aRect.x = pEvent->xexpose.x;
3455 aRect.y = pEvent->xexpose.y;
3456 aRect.width = pEvent->xexpose.width;
3457 aRect.height = pEvent->xexpose.height;
3458 nCount = pEvent->xexpose.count;
3460 else if( pEvent->type == GraphicsExpose )
3462 aRect.x = pEvent->xgraphicsexpose.x;
3463 aRect.y = pEvent->xgraphicsexpose.y;
3464 aRect.width = pEvent->xgraphicsexpose.width;
3465 aRect.height = pEvent->xgraphicsexpose.height;
3466 nCount = pEvent->xgraphicsexpose.count;
3469 if( IsOverrideRedirect() && mbFullScreen &&
3470 aPresentationReparentList.begin() == aPresentationReparentList.end() )
3471 // we are in fullscreen mode -> override redirect
3472 // focus is possibly lost, so reget it
3473 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone, CurrentTime );
3475 // width and height are extents, so they are of by one for rectangle
3476 maPaintRegion.Union( Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) );
3478 if( nCount )
3479 // wait for last expose rectangle, do not wait for resize timer
3480 // if a completed graphics expose sequence is available
3481 return 1;
3483 SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() );
3485 CallCallback( SALEVENT_PAINT, &aPEvt );
3486 maPaintRegion = Rectangle();
3488 return 1;
3491 void X11SalFrame::RestackChildren( XLIB_Window* pTopLevelWindows, int nTopLevelWindows )
3493 if( maChildren.begin() != maChildren.end() )
3495 int nWindow = nTopLevelWindows;
3496 while( nWindow-- )
3497 if( pTopLevelWindows[nWindow] == GetStackingWindow() )
3498 break;
3499 if( nWindow < 0 )
3500 return;
3502 std::list< X11SalFrame* >::const_iterator it;
3503 for( it = maChildren.begin(); it != maChildren.end(); ++it )
3505 X11SalFrame* pData = *it;
3506 if( pData->bMapped_ )
3508 int nChild = nWindow;
3509 while( nChild-- )
3511 if( pTopLevelWindows[nChild] == pData->GetStackingWindow() )
3513 // if a child is behind its parent, place it above the
3514 // parent (for insane WMs like Dtwm and olwm)
3515 XWindowChanges aCfg;
3516 aCfg.sibling = GetStackingWindow();
3517 aCfg.stack_mode = Above;
3518 XConfigureWindow( GetXDisplay(), pData->GetStackingWindow(), CWSibling|CWStackMode, &aCfg );
3519 break;
3524 for( it = maChildren.begin(); it != maChildren.end(); ++it )
3526 X11SalFrame* pData = *it;
3527 pData->RestackChildren( pTopLevelWindows, nTopLevelWindows );
3532 void X11SalFrame::RestackChildren()
3534 if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected()
3535 && maChildren.begin() != maChildren.end() )
3537 XLIB_Window aRoot, aParent, *pChildren = NULL;
3538 unsigned int nChildren;
3539 if( XQueryTree( GetXDisplay(),
3540 GetDisplay()->GetRootWindow( m_nXScreen ),
3541 &aRoot,
3542 &aParent,
3543 &pChildren,
3544 &nChildren ) )
3546 RestackChildren( pChildren, nChildren );
3547 XFree( pChildren );
3552 static Bool size_event_predicate( Display*, XEvent* event, XPointer arg )
3554 if( event->type != ConfigureNotify )
3555 return False;
3556 X11SalFrame* frame = reinterpret_cast< X11SalFrame* >( arg );
3557 XConfigureEvent* pEvent = &event->xconfigure;
3558 if( pEvent->window != frame->GetShellWindow()
3559 && pEvent->window != frame->GetWindow()
3560 && pEvent->window != frame->GetForeignParent()
3561 && pEvent->window != frame->GetStackingWindow())
3562 { // ignored at top of HandleSizeEvent()
3563 return False;
3565 if( pEvent->window == frame->GetStackingWindow())
3566 return False; // filtered later in HandleSizeEvent()
3567 // at this point we know that there is another similar event in the queue
3568 frame->setPendingSizeEvent();
3569 return False; // but do not process the new event out of order
3572 void X11SalFrame::setPendingSizeEvent()
3574 mPendingSizeEvent = true;
3577 long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
3579 // NOTE: if you add more tests in this function, make sure to update size_event_predicate()
3580 // so that it finds exactly the same events
3582 if ( pEvent->window != GetShellWindow()
3583 && pEvent->window != GetWindow()
3584 && pEvent->window != GetForeignParent()
3585 && pEvent->window != GetStackingWindow()
3588 // could be as well a sys-child window (aka SalObject)
3589 return 1;
3592 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
3594 // just update the children's positions
3595 RestackChildren();
3596 return 1;
3599 if( pEvent->window == GetForeignParent() )
3600 XResizeWindow( GetXDisplay(),
3601 GetWindow(),
3602 pEvent->width,
3603 pEvent->height );
3605 XLIB_Window hDummy;
3606 XTranslateCoordinates( GetXDisplay(),
3607 GetWindow(),
3608 pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() ),
3609 0, 0,
3610 &pEvent->x, &pEvent->y,
3611 &hDummy );
3613 if( pEvent->window == GetStackingWindow() )
3615 if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y )
3617 maGeometry.nX = pEvent->x;
3618 maGeometry.nY = pEvent->y;
3619 CallCallback( SALEVENT_MOVE, NULL );
3621 return 1;
3624 // check size hints in first time SalFrame::Show
3625 if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ )
3626 nShowState_ = SHOWSTATE_NORMAL;
3628 // Avoid a race condition where resizing this window to one size and shortly after that
3629 // to another size generates first size event with the old size and only after that
3630 // with the new size, temporarily making us think the old size is valid (bnc#674806).
3631 // So if there is another size event for this window pending, ignore this one.
3632 mPendingSizeEvent = false;
3633 XEvent dummy;
3634 XCheckIfEvent( GetXDisplay(), &dummy, size_event_predicate, reinterpret_cast< XPointer >( this ));
3635 if( mPendingSizeEvent )
3636 return 1;
3638 nWidth_ = pEvent->width;
3639 nHeight_ = pEvent->height;
3641 bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY );
3642 bool bSized = ( pEvent->width != (int)maGeometry.nWidth || pEvent->height != (int)maGeometry.nHeight );
3644 maGeometry.nX = pEvent->x;
3645 maGeometry.nY = pEvent->y;
3646 maGeometry.nWidth = pEvent->width;
3647 maGeometry.nHeight = pEvent->height;
3648 updateScreenNumber();
3650 // update children's position
3651 RestackChildren();
3653 if( bSized && ! bMoved )
3654 CallCallback( SALEVENT_RESIZE, NULL );
3655 else if( bMoved && ! bSized )
3656 CallCallback( SALEVENT_MOVE, NULL );
3657 else if( bMoved && bSized )
3658 CallCallback( SALEVENT_MOVERESIZE, NULL );
3660 return 1;
3663 IMPL_LINK_NOARG(X11SalFrame, HandleAlwaysOnTopRaise)
3665 if( bMapped_ )
3666 ToTop( 0 );
3667 return 0;
3670 long X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent )
3672 Display *pDisplay = pEvent->display;
3673 XLIB_Window hWM_Parent;
3674 XLIB_Window hRoot, *Children, hDummy;
3675 unsigned int nChildren;
3676 bool bNone = pDisplay_->GetProperties()
3677 & PROPERTY_SUPPORT_WM_Parent_Pixmap_None;
3678 bool bAccessParentWindow = ! (pDisplay_->GetProperties()
3679 & PROPERTY_FEATURE_TrustedSolaris);
3681 static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" );
3683 GetGenericData()->ErrorTrapPush();
3686 * don't rely on the new parent from the event.
3687 * the event may be "out of date", that is the window manager
3688 * window may not exist anymore. This can happen if someone
3689 * shows a frame and hides it again quickly (not that that would
3690 * be very sensible)
3692 hWM_Parent = GetShellWindow();
3695 Children = NULL;
3696 XQueryTree( pDisplay,
3697 hWM_Parent,
3698 &hRoot,
3699 &hDummy,
3700 &Children,
3701 &nChildren );
3703 bool bError = GetGenericData()->ErrorTrapPop( false );
3704 GetGenericData()->ErrorTrapPush();
3706 if( bError )
3708 hWM_Parent = GetShellWindow();
3709 break;
3711 /* this sometimes happens if a Show(true) is
3712 * immediately followed by Show(false) (which is braindead anyway)
3714 if( hDummy == hWM_Parent )
3715 hDummy = hRoot;
3716 if( hDummy != hRoot )
3718 hWM_Parent = hDummy;
3719 if( bAccessParentWindow && bNone )
3720 XSetWindowBackgroundPixmap( pDisplay, hWM_Parent, None );
3722 if( Children )
3723 XFree( Children );
3724 } while( hDummy != hRoot );
3726 if( GetStackingWindow() == None
3727 && hWM_Parent != hPresentationWindow
3728 && hWM_Parent != GetShellWindow()
3729 && ( ! pDisableStackingCheck || ! *pDisableStackingCheck )
3732 mhStackingWindow = hWM_Parent;
3733 if (bAccessParentWindow)
3734 XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask );
3737 if( hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() )
3738 || hWM_Parent == GetForeignParent()
3739 || pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() )
3740 || ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) )
3742 // Reparenting before Destroy
3743 aPresentationReparentList.remove( GetStackingWindow() );
3744 mhStackingWindow = None;
3745 GetGenericData()->ErrorTrapPop();
3746 return 0;
3750 * evil hack to show decorated windows on top
3751 * of override redirect presentation windows:
3752 * reparent the window manager window to the presentation window
3753 * does not work with non-reparenting WMs
3754 * in future this should not be necessary anymore with
3755 * _NET_WM_STATE_FULLSCREEN available
3757 if( hPresentationWindow != None
3758 && hPresentationWindow != GetWindow()
3759 && GetStackingWindow() != None
3760 && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nXScreen )
3763 int x = 0, y = 0;
3764 XLIB_Window aChild;
3765 XTranslateCoordinates( GetXDisplay(),
3766 GetStackingWindow(),
3767 GetDisplay()->GetRootWindow( m_nXScreen ),
3768 0, 0,
3769 &x, &y,
3770 &aChild
3772 XReparentWindow( GetXDisplay(),
3773 GetStackingWindow(),
3774 hPresentationWindow,
3775 x, y
3777 aPresentationReparentList.push_back( GetStackingWindow() );
3780 int nLeft = 0, nTop = 0;
3781 XTranslateCoordinates( GetXDisplay(),
3782 GetShellWindow(),
3783 hWM_Parent,
3784 0, 0,
3785 &nLeft,
3786 &nTop,
3787 &hDummy );
3788 maGeometry.nLeftDecoration = nLeft > 0 ? nLeft-1 : 0;
3789 maGeometry.nTopDecoration = nTop > 0 ? nTop-1 : 0;
3792 * decorations are not symmetric,
3793 * so need real geometries here
3794 * (this will fail with virtual roots ?)
3797 // reset error occurred
3798 GetGenericData()->ErrorTrapPop();
3799 GetGenericData()->ErrorTrapPush();
3801 int xp, yp, x, y;
3802 unsigned int wp, w, hp, h, bw, d;
3803 XGetGeometry( GetXDisplay(),
3804 GetShellWindow(),
3805 &hRoot,
3806 &x, &y, &w, &h, &bw, &d );
3807 XGetGeometry( GetXDisplay(),
3808 hWM_Parent,
3809 &hRoot,
3810 &xp, &yp, &wp, &hp, &bw, &d );
3811 bool bResized = false;
3812 bool bError = GetGenericData()->ErrorTrapPop( false );
3813 GetGenericData()->ErrorTrapPush();
3815 if( ! bError )
3817 maGeometry.nRightDecoration = wp - w - maGeometry.nLeftDecoration;
3818 maGeometry.nBottomDecoration = hp - h - maGeometry.nTopDecoration;
3820 * note: this works because hWM_Parent is direct child of root,
3821 * not necessarily parent of GetShellWindow()
3823 maGeometry.nX = xp + nLeft;
3824 maGeometry.nY = yp + nTop;
3825 bResized = w != maGeometry.nWidth || h != maGeometry.nHeight;
3826 maGeometry.nWidth = w;
3827 maGeometry.nHeight = h;
3830 // limit width and height if we are too large: #47757
3831 // olwm and fvwm need this, it doesn't harm the rest
3833 // #i81311# do this only for sizable frames
3834 if( (nStyle_ & SAL_FRAME_STYLE_SIZEABLE) != 0 )
3836 Size aScreenSize = GetDisplay()->GetScreenSize( m_nXScreen );
3837 int nScreenWidth = aScreenSize.Width();
3838 int nScreenHeight = aScreenSize.Height();
3839 int nFrameWidth = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
3840 int nFrameHeight = maGeometry.nHeight + maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
3842 if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight))
3844 Size aSize(maGeometry.nWidth, maGeometry.nHeight);
3846 if (nFrameWidth > nScreenWidth)
3847 aSize.Width() = nScreenWidth - maGeometry.nRightDecoration - maGeometry.nLeftDecoration;
3848 if (nFrameHeight > nScreenHeight)
3849 aSize.Height() = nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration;
3851 SetSize( aSize );
3852 bResized = false;
3855 if( bResized )
3856 CallCallback( SALEVENT_RESIZE, NULL );
3858 GetGenericData()->ErrorTrapPop();
3860 return 1;
3863 long X11SalFrame::HandleColormapEvent( XColormapEvent* )
3865 return 0;
3868 long X11SalFrame::HandleStateEvent( XPropertyEvent *pEvent )
3870 Atom actual_type;
3871 int actual_format;
3872 unsigned long nitems, bytes_after;
3873 unsigned char *prop = NULL;
3875 if( 0 != XGetWindowProperty( GetXDisplay(),
3876 GetShellWindow(),
3877 pEvent->atom, // property
3878 0, // long_offset (32bit)
3879 2, // long_length (32bit)
3880 False, // delete
3881 pEvent->atom, // req_type
3882 &actual_type,
3883 &actual_format,
3884 &nitems,
3885 &bytes_after,
3886 &prop )
3887 || ! prop
3889 return 0;
3891 DBG_ASSERT( actual_type == pEvent->atom
3892 && 32 == actual_format
3893 && 2 == nitems
3894 && 0 == bytes_after, "HandleStateEvent" );
3896 if( *(unsigned long*)prop == NormalState )
3897 nShowState_ = SHOWSTATE_NORMAL;
3898 else if( *(unsigned long*)prop == IconicState )
3899 nShowState_ = SHOWSTATE_MINIMIZED;
3901 XFree( prop );
3902 return 1;
3905 long X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent )
3907 const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() );
3909 #if !defined(__synchronous_extinput__)
3910 if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) )
3912 HandleExtTextEvent (pEvent);
3913 return 1;
3915 #endif
3916 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) )
3918 stderr0( "X11SalFrame::Dispatch Quit\n" );
3919 Close(); // ???
3920 return 1;
3922 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS ) )
3924 if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::NET_WM_PING ) )
3925 rWMAdaptor.answerPing( this, pEvent );
3926 else if( ! ( nStyle_ & SAL_FRAME_STYLE_PLUG )
3927 && ! (( nStyle_ & SAL_FRAME_STYLE_FLOAT ) && (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION))
3930 if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) )
3932 Close();
3933 return 1;
3935 else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) )
3937 // do nothing, we set the input focus in ToTop() if necessary
3938 #if OSL_DEBUG_LEVEL > 1
3939 fprintf( stderr, "got WM_TAKE_FOCUS on %s window\n",
3940 (nStyle_&SAL_FRAME_STYLE_OWNERDRAWDECORATION) ?
3941 "ownerdraw" : "NON OWNERDRAW" );
3942 #endif
3946 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) &&
3947 pEvent->window == GetWindow() )
3949 if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
3950 pEvent->data.l[1] == 2 ) // XEMBED_WINDOW_DEACTIVATE
3952 XFocusChangeEvent aEvent;
3953 aEvent.type = (pEvent->data.l[1] == 1 ? FocusIn : FocusOut);
3954 aEvent.serial = pEvent->serial;
3955 aEvent.send_event = True;
3956 aEvent.display = pEvent->display;
3957 aEvent.window = pEvent->window;
3958 aEvent.mode = NotifyNormal;
3959 aEvent.detail = NotifyDetailNone;
3960 HandleFocusEvent( &aEvent );
3963 return 0;
3966 extern "C"
3968 Bool call_checkKeyReleaseForRepeat( Display* pDisplay, XEvent* pCheck, XPointer pX11SalFrame )
3970 return X11SalFrame::checkKeyReleaseForRepeat( pDisplay, pCheck, pX11SalFrame );
3974 Bool X11SalFrame::checkKeyReleaseForRepeat( Display*, XEvent* pCheck, XPointer pX11SalFrame )
3976 X11SalFrame* pThis = (X11SalFrame*)pX11SalFrame;
3977 return
3978 pCheck->type == XLIB_KeyPress &&
3979 pCheck->xkey.state == pThis->nKeyState_ &&
3980 pCheck->xkey.keycode == pThis->nKeyCode_ &&
3981 pCheck->xkey.time == pThis->nReleaseTime_ ? True : False;
3984 long X11SalFrame::Dispatch( XEvent *pEvent )
3986 long nRet = 0;
3988 if( -1 == nCaptured_ )
3990 CaptureMouse( true );
3991 #ifdef DBG_UTIL
3992 if( -1 != nCaptured_ )
3993 pDisplay_->DbgPrintDisplayEvent("Captured", pEvent);
3994 #endif
3997 if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() )
3999 switch( pEvent->type )
4001 case XLIB_KeyPress:
4002 nKeyCode_ = pEvent->xkey.keycode;
4003 nKeyState_ = pEvent->xkey.state;
4004 nRet = HandleKeyEvent( &pEvent->xkey );
4005 break;
4007 case KeyRelease:
4008 if( -1 == nCompose_ )
4010 nReleaseTime_ = pEvent->xkey.time;
4011 XEvent aEvent;
4012 if( XCheckIfEvent( pEvent->xkey.display, &aEvent, call_checkKeyReleaseForRepeat, (XPointer)this ) )
4013 XPutBackEvent( pEvent->xkey.display, &aEvent );
4014 else
4015 nRet = HandleKeyEvent( &pEvent->xkey );
4017 break;
4019 case ButtonPress:
4020 // if we lose the focus in presentation mode
4021 // there are good chances that we never get it back
4022 // since the WM ignores us
4023 if( IsOverrideRedirect() )
4025 XSetInputFocus( GetXDisplay(), GetShellWindow(),
4026 RevertToNone, CurrentTime );
4028 //fall-through
4029 case ButtonRelease:
4030 case MotionNotify:
4031 case EnterNotify:
4032 case LeaveNotify:
4033 nRet = HandleMouseEvent( pEvent );
4034 break;
4036 case FocusIn:
4037 case FocusOut:
4038 nRet = HandleFocusEvent( &pEvent->xfocus );
4039 break;
4041 case Expose:
4042 case GraphicsExpose:
4043 nRet = HandleExposeEvent( pEvent );
4044 break;
4046 case MapNotify:
4047 if( pEvent->xmap.window == GetShellWindow() )
4049 if( nShowState_ == SHOWSTATE_HIDDEN )
4052 * workaround for (at least) KWin 2.2.2
4053 * which will map windows that were once transient
4054 * even if they are withdrawn when the respective
4055 * document is mapped.
4057 if( ! (nStyle_ & SAL_FRAME_STYLE_PLUG) )
4058 XUnmapWindow( GetXDisplay(), GetShellWindow() );
4059 break;
4061 bMapped_ = true;
4062 bViewable_ = true;
4063 nRet = 1;
4064 if ( mpInputContext != NULL )
4065 mpInputContext->Map( this );
4066 CallCallback( SALEVENT_RESIZE, NULL );
4068 bool bSetFocus = m_bSetFocusOnMap;
4069 /* another workaround for sawfish: if a transient window for the same parent is shown
4070 * sawfish does not set the focus to it. Applies only for click to focus mode.
4072 if( ! (nStyle_ & SAL_FRAME_STYLE_FLOAT ) && mbInShow && GetDisplay()->getWMAdaptor()->getWindowManagerName().equalsAscii( "Sawfish" ) )
4074 // don't set the focus into the IME status window
4075 // since this will lead to a parent loss of focus, close status,
4076 // reget focus, open status, .... flicker loop
4077 if ( (I18NStatus::get().getStatusFrame() != this) )
4078 bSetFocus = true;
4082 * sometimes a message box/dialogue is brought up when a frame is not mapped
4083 * the corresponding TRANSIENT_FOR hint is then set to the root window
4084 * so that the dialogue shows in all cases. Correct it here if the
4085 * frame is shown afterwards.
4087 if( ! IsChildWindow()
4088 && ! IsOverrideRedirect()
4089 && ! IsFloatGrabWindow()
4092 for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
4093 it != maChildren.end(); ++it )
4095 if( (*it)->mbTransientForRoot )
4096 pDisplay_->getWMAdaptor()->changeReferenceFrame( *it, this );
4100 if( hPresentationWindow != None && GetShellWindow() == hPresentationWindow )
4101 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime );
4103 if( bSetFocus )
4105 XSetInputFocus( GetXDisplay(),
4106 GetShellWindow(),
4107 RevertToParent,
4108 CurrentTime );
4111 RestackChildren();
4112 mbInShow = false;
4113 m_bSetFocusOnMap = false;
4115 break;
4117 case UnmapNotify:
4118 if( pEvent->xunmap.window == GetShellWindow() )
4120 bMapped_ = false;
4121 bViewable_ = false;
4122 nRet = 1;
4123 if ( mpInputContext != NULL )
4124 mpInputContext->Unmap( this );
4125 CallCallback( SALEVENT_RESIZE, NULL );
4127 break;
4129 case ConfigureNotify:
4130 if( pEvent->xconfigure.window == GetShellWindow()
4131 || pEvent->xconfigure.window == GetWindow() )
4132 nRet = HandleSizeEvent( &pEvent->xconfigure );
4133 break;
4135 case VisibilityNotify:
4136 nVisibility_ = pEvent->xvisibility.state;
4137 nRet = 1;
4138 if( bAlwaysOnTop_
4139 && bMapped_
4140 && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK()
4141 && nVisibility_ != VisibilityUnobscured )
4142 maAlwaysOnTopRaiseTimer.Start();
4143 break;
4145 case ReparentNotify:
4146 nRet = HandleReparentEvent( &pEvent->xreparent );
4147 break;
4149 case MappingNotify:
4150 if( MappingPointer != pEvent->xmapping.request )
4151 nRet = CallCallback( SALEVENT_KEYBOARDCHANGED, 0 );
4152 break;
4154 case ColormapNotify:
4155 nRet = HandleColormapEvent( &pEvent->xcolormap );
4156 break;
4158 case PropertyNotify:
4160 if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) )
4161 nRet = HandleStateEvent( &pEvent->xproperty );
4162 else
4163 nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty );
4164 break;
4167 case ClientMessage:
4168 nRet = HandleClientMessage( &pEvent->xclient );
4169 break;
4172 else
4174 switch( pEvent->type )
4176 case FocusIn:
4177 case FocusOut:
4178 if( ( nStyle_ & SAL_FRAME_STYLE_PLUG )
4179 && ( pEvent->xfocus.window == GetShellWindow()
4180 || pEvent->xfocus.window == GetForeignParent() )
4183 nRet = HandleFocusEvent( &pEvent->xfocus );
4185 break;
4187 case ConfigureNotify:
4188 if( pEvent->xconfigure.window == GetForeignParent() ||
4189 pEvent->xconfigure.window == GetShellWindow() )
4190 nRet = HandleSizeEvent( &pEvent->xconfigure );
4192 if( pEvent->xconfigure.window == GetStackingWindow() )
4193 nRet = HandleSizeEvent( &pEvent->xconfigure );
4195 RestackChildren();
4196 break;
4200 return nRet;
4203 void X11SalFrame::ResetClipRegion()
4205 delete [] m_pClipRectangles;
4206 m_pClipRectangles = NULL;
4207 m_nCurClipRect = m_nMaxClipRect = 0;
4209 const int dest_kind = ShapeBounding;
4210 const int op = ShapeSet;
4211 const int ordering = YSorted;
4213 XWindowAttributes win_attrib;
4214 XRectangle win_size;
4216 XLIB_Window aShapeWindow = mhShellWindow;
4218 XGetWindowAttributes ( GetDisplay()->GetDisplay(),
4219 aShapeWindow,
4220 &win_attrib );
4222 win_size.x = 0;
4223 win_size.y = 0;
4224 win_size.width = win_attrib.width;
4225 win_size.height = win_attrib.height;
4227 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4228 aShapeWindow,
4229 dest_kind,
4230 0, 0, // x_off, y_off
4231 &win_size, // list of rectangles
4232 1, // number of rectangles
4233 op, ordering );
4236 void X11SalFrame::BeginSetClipRegion( sal_uLong nRects )
4238 if( m_pClipRectangles )
4239 delete [] m_pClipRectangles;
4240 if( nRects )
4241 m_pClipRectangles = new XRectangle[nRects];
4242 else
4243 m_pClipRectangles = NULL;
4244 m_nMaxClipRect = static_cast<int>(nRects);
4245 m_nCurClipRect = 0;
4248 void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
4250 if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect )
4252 m_pClipRectangles[m_nCurClipRect].x = nX;
4253 m_pClipRectangles[m_nCurClipRect].y = nY;
4254 m_pClipRectangles[m_nCurClipRect].width = nWidth;
4255 m_pClipRectangles[m_nCurClipRect].height = nHeight;
4256 m_nCurClipRect++;
4260 void X11SalFrame::EndSetClipRegion()
4262 const int dest_kind = ShapeBounding;
4263 const int ordering = YSorted;
4264 const int op = ShapeSet;
4266 XLIB_Window aShapeWindow = mhShellWindow;
4267 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4268 aShapeWindow,
4269 dest_kind,
4270 0, 0, // x_off, y_off
4271 m_pClipRectangles,
4272 m_nCurClipRect,
4273 op, ordering );
4277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */