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