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