Bug Summary

File:home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx
Warning:line 2390, column 9
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name salframe.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D GLM_FORCE_CTOR_INIT -D HAVE_VALGRIND_HEADERS -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D VCLPLUG_GEN_IMPLEMENTATION -D USE_RANDR -D USE_XINERAMA_XORG -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <string.h>
21#include <string_view>
22#include <stdio.h>
23#include <stdlib.h>
24
25#include <tools/debug.hxx>
26
27#include <vcl/event.hxx>
28#include <vcl/floatwin.hxx>
29#include <vcl/keycodes.hxx>
30#include <vcl/settings.hxx>
31#include <vcl/bitmapaccess.hxx>
32#include <vcl/opengl/OpenGLContext.hxx>
33#include <vcl/BitmapTools.hxx>
34
35#include <X11/Xlib.h>
36#include <X11/Xutil.h>
37#include <X11/Xatom.h>
38#include <X11/keysym.h>
39#include <X11/extensions/shape.h>
40
41#include <saldatabasic.hxx>
42#include <unx/saldisp.hxx>
43#include <unx/salgdi.h>
44#include <unx/salframe.h>
45#include <unx/wmadaptor.hxx>
46#include <unx/salbmp.h>
47#include <unx/i18n_ic.hxx>
48#include <unx/i18n_keysym.hxx>
49#include <opengl/zone.hxx>
50
51#include <unx/gensys.h>
52#include <window.h>
53
54#include <sal/macros.h>
55#include <sal/log.hxx>
56#include <com/sun/star/uno/Exception.hpp>
57
58#include <svdata.hxx>
59#include <bitmaps.hlst>
60
61#include <optional>
62
63#include <algorithm>
64
65#ifndef Button66
66# define Button66 6
67#endif
68#ifndef Button77
69# define Button77 7
70#endif
71
72using namespace vcl_sal;
73
74constexpr auto CLIENT_EVENTS = StructureNotifyMask(1L<<17)
75 | SubstructureNotifyMask(1L<<19)
76 | KeyPressMask(1L<<0)
77 | KeyReleaseMask(1L<<1)
78 | ButtonPressMask(1L<<2)
79 | ButtonReleaseMask(1L<<3)
80 | PointerMotionMask(1L<<6)
81 | EnterWindowMask(1L<<4)
82 | LeaveWindowMask(1L<<5)
83 | FocusChangeMask(1L<<21)
84 | ExposureMask(1L<<15)
85 | VisibilityChangeMask(1L<<16)
86 | PropertyChangeMask(1L<<22)
87 | ColormapChangeMask(1L<<23);
88
89static ::Window hPresentationWindow = None0L, hPresFocusWindow = None0L;
90static ::std::list< ::Window > aPresentationReparentList;
91static int nVisibleFloats = 0;
92
93static void doReparentPresentationDialogues( SalDisplay const * pDisplay )
94{
95 GetGenericUnixSalData()->ErrorTrapPush();
96 for (auto const& elem : aPresentationReparentList)
97 {
98 int x, y;
99 ::Window aRoot, aChild;
100 unsigned int w, h, bw, d;
101 XGetGeometry( pDisplay->GetDisplay(),
102 elem,
103 &aRoot,
104 &x, &y, &w, &h, &bw, &d );
105 XTranslateCoordinates( pDisplay->GetDisplay(),
106 hPresentationWindow,
107 aRoot,
108 x, y,
109 &x, &y,
110 &aChild );
111 XReparentWindow( pDisplay->GetDisplay(),
112 elem,
113 aRoot,
114 x, y );
115 }
116 aPresentationReparentList.clear();
117 if( hPresFocusWindow )
118 XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot1L, CurrentTime0L );
119 XSync( pDisplay->GetDisplay(), False0 );
120 GetGenericUnixSalData()->ErrorTrapPop();
121}
122
123bool X11SalFrame::IsOverrideRedirect() const
124{
125 return
126 ((nStyle_ & SalFrameStyleFlags::INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash())
127 ||
128 (!( nStyle_ & ~SalFrameStyleFlags::DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen())
129 ;
130}
131
132bool X11SalFrame::IsFloatGrabWindow() const
133{
134 static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" );
135
136 return
137 ( ( !pDisableGrab || !*pDisableGrab ) &&
138 (
139 (nStyle_ & SalFrameStyleFlags::FLOAT) &&
140 ! (nStyle_ & SalFrameStyleFlags::TOOLTIP) &&
141 ! (nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION)
142 )
143 );
144}
145
146void X11SalFrame::setXEmbedInfo()
147{
148 if( !m_bXEmbed )
149 return;
150
151 long aInfo[2];
152 aInfo[0] = 1; // XEMBED protocol version
153 aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED
154 XChangeProperty( pDisplay_->GetDisplay(),
155 mhWindow,
156 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
157 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
158 32,
159 PropModeReplace0,
160 reinterpret_cast<unsigned char*>(aInfo),
161 SAL_N_ELEMENTS(aInfo)(sizeof(sal_n_array_size(aInfo))) );
162}
163
164void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
165{
166 XEvent aEvent;
167
168 memset( &aEvent, 0, sizeof(aEvent) );
169 aEvent.xclient.window = mhForeignParent;
170 aEvent.xclient.type = ClientMessage33;
171 aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED );
172 aEvent.xclient.format = 32;
173 aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime0L;
174 aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
175 aEvent.xclient.data.l[2] = 0;
176 aEvent.xclient.data.l[3] = 0;
177 aEvent.xclient.data.l[4] = 0;
178
179 GetGenericUnixSalData()->ErrorTrapPush();
180 XSendEvent( pDisplay_->GetDisplay(),
181 mhForeignParent,
182 False0, NoEventMask0L, &aEvent );
183 XSync( pDisplay_->GetDisplay(), False0 );
184 GetGenericUnixSalData()->ErrorTrapPop();
185}
186
187typedef std::vector< unsigned long > NetWmIconData;
188
189namespace
190{
191 const std::u16string_view SV_ICON_SIZE48[] =
192 {
193 u"" MAINAPP_48_8"res/mainapp_48_8.png",
194 u"" MAINAPP_48_8"res/mainapp_48_8.png",
195 u"" ODT_48_8"res/odt_48_8.png",
196 u"" OTT_48_8"res/ott_48_8.png",
197 u"" ODS_48_8"res/ods_48_8.png",
198 u"" OTS_48_8"res/ots_48_8.png",
199 u"" ODG_48_8"res/odg_48_8.png",
200 u"" MAINAPP_48_8"res/mainapp_48_8.png",
201 u"" ODP_48_8"res/odp_48_8.png",
202 u"" MAINAPP_48_8"res/mainapp_48_8.png",
203 u"" ODM_48_8"res/odm_48_8.png",
204 u"" MAINAPP_48_8"res/mainapp_48_8.png",
205 u"" ODB_48_8"res/odb_48_8.png",
206 u"" ODF_48_8"res/odf_48_8.png"
207 };
208
209 const std::u16string_view SV_ICON_SIZE32[] =
210 {
211 u"" MAINAPP_32_8"res/mainapp_32_8.png",
212 u"" MAINAPP_32_8"res/mainapp_32_8.png",
213 u"" ODT_32_8"res/odt_32_8.png",
214 u"" OTT_32_8"res/ott_32_8.png",
215 u"" ODS_32_8"res/ods_32_8.png",
216 u"" OTS_32_8"res/ots_32_8.png",
217 u"" ODG_32_8"res/odg_32_8.png",
218 u"" MAINAPP_32_8"res/mainapp_32_8.png",
219 u"" ODP_32_8"res/odp_32_8.png",
220 u"" MAINAPP_32_8"res/mainapp_32_8.png",
221 u"" ODM_32_8"res/odm_32_8.png",
222 u"" MAINAPP_32_8"res/mainapp_32_8.png",
223 u"" ODB_32_8"res/odb_32_8.png",
224 u"" ODF_32_8"res/odf_32_8.png"
225 };
226
227 const std::u16string_view SV_ICON_SIZE16[] =
228 {
229 u"" MAINAPP_16_8"res/mainapp_16_8.png",
230 u"" MAINAPP_16_8"res/mainapp_16_8.png",
231 u"" ODT_16_8"res/odt_16_8.png",
232 u"" OTT_16_8"res/ott_16_8.png",
233 u"" ODS_16_8"res/ods_16_8.png",
234 u"" OTS_16_8"res/ots_16_8.png",
235 u"" ODG_16_8"res/odg_16_8.png",
236 u"" MAINAPP_16_8"res/mainapp_16_8.png",
237 u"" ODP_16_8"res/odp_16_8.png",
238 u"" MAINAPP_16_8"res/mainapp_16_8.png",
239 u"" ODM_16_8"res/odm_16_8.png",
240 u"" MAINAPP_16_8"res/mainapp_16_8.png",
241 u"" ODB_16_8"res/odb_16_8.png",
242 u"" ODF_16_8"res/odf_16_8.png"
243 };
244}
245
246static void CreateNetWmAppIcon( sal_uInt16 nIcon, NetWmIconData& netwm_icon )
247{
248 const int sizes[ 3 ] = { 48, 32, 16 };
249 netwm_icon.resize( 48 * 48 + 32 * 32 + 16 * 16 + 3 * 2 );
250 int pos = 0;
251 for(int size : sizes)
252 {
253 OUString sIcon;
254 if( size >= 48 )
255 sIcon = SV_ICON_SIZE48[nIcon];
256 else if( size >= 32 )
257 sIcon = SV_ICON_SIZE32[nIcon];
258 else
259 sIcon = SV_ICON_SIZE16[nIcon];
260
261 BitmapEx aIcon = vcl::bitmap::loadFromName(sIcon, ImageLoadFlags::IgnoreScalingFactor);
262
263 if( aIcon.IsEmpty())
264 continue;
265 vcl::bitmap::convertBitmap32To24Plus8(aIcon, aIcon);
266 Bitmap icon = aIcon.GetBitmap();
267 AlphaMask mask;
268 switch( aIcon.GetTransparentType())
269 {
270 case TransparentType::NONE:
271 {
272 sal_uInt8 nTrans = 0;
273 mask = AlphaMask( icon.GetSizePixel(), &nTrans );
274 }
275 break;
276 case TransparentType::Color:
277 mask = AlphaMask( icon.CreateMask( aIcon.GetTransparentColor() ) );
278 break;
279 case TransparentType::Bitmap:
280 mask = aIcon.GetAlpha();
281 break;
282 }
283 BitmapReadAccess* iconData = icon.AcquireReadAccess();
284 BitmapReadAccess* maskData = mask.AcquireReadAccess();
285 netwm_icon[ pos++ ] = size; // width
286 netwm_icon[ pos++ ] = size; // height
287 for( int y = 0; y < size; ++y )
288 for( int x = 0; x < size; ++x )
289 {
290 BitmapColor col = iconData->GetColor( y, x );
291 BitmapColor alpha = maskData->GetColor( y, x );
292 netwm_icon[ pos++ ] = (((( 255 - alpha.GetBlue()) * 256U ) + col.GetRed()) * 256 + col.GetGreen()) * 256 + col.GetBlue();
293 }
294 Bitmap::ReleaseAccess( iconData );
295 mask.ReleaseAccess( maskData );
296 }
297 netwm_icon.resize( pos );
298}
299
300static bool lcl_SelectAppIconPixmap( SalDisplay const *pDisplay, SalX11Screen nXScreen,
301 sal_uInt16 nIcon, sal_uInt16 iconSize,
302 Pixmap& icon_pixmap, Pixmap& icon_mask, NetWmIconData& netwm_icon)
303{
304 PreDefaultWinNoOpenGLZone aGuard;
305
306 CreateNetWmAppIcon( nIcon, netwm_icon );
307
308 OUString sIcon;
309
310 if( iconSize >= 48 )
311 sIcon = SV_ICON_SIZE48[nIcon];
312 else if( iconSize >= 32 )
313 sIcon = SV_ICON_SIZE32[nIcon];
314 else if( iconSize >= 16 )
315 sIcon = SV_ICON_SIZE16[nIcon];
316 else
317 return false;
318
319 BitmapEx aIcon = vcl::bitmap::loadFromName(sIcon, ImageLoadFlags::IgnoreScalingFactor);
320
321 if( aIcon.IsEmpty() )
322 return false;
323
324 X11SalBitmap *pBitmap = dynamic_cast < X11SalBitmap * >
325 (aIcon.ImplGetBitmapSalBitmap().get());
326 if (!pBitmap) // FIXME: opengl , TODO SKIA
327 return false;
328
329 icon_pixmap = XCreatePixmap( pDisplay->GetDisplay(),
330 pDisplay->GetRootWindow( nXScreen ),
331 iconSize, iconSize,
332 DefaultDepth( pDisplay->GetDisplay(),((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->root_depth)
333 nXScreen.getXScreen() )((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->root_depth)
334 );
335
336 SalTwoRect aRect(0, 0, iconSize, iconSize, 0, 0, iconSize, iconSize);
337
338 pBitmap->ImplDraw( icon_pixmap,
339 nXScreen,
340 DefaultDepth( pDisplay->GetDisplay(),((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->root_depth)
341 nXScreen.getXScreen() )((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->root_depth)
,
342 aRect,
343 DefaultGC( pDisplay->GetDisplay(),((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->default_gc)
344 nXScreen.getXScreen() )((&((_XPrivDisplay)(pDisplay->GetDisplay()))->screens
[nXScreen.getXScreen()])->default_gc)
);
345
346 icon_mask = None0L;
347
348 if( TransparentType::Bitmap == aIcon.GetTransparentType() )
349 {
350 icon_mask = XCreatePixmap( pDisplay->GetDisplay(),
351 pDisplay->GetRootWindow( pDisplay->GetDefaultXScreen() ),
352 iconSize, iconSize, 1);
353
354 XGCValues aValues;
355 aValues.foreground = 0xffffffff;
356 aValues.background = 0;
357 aValues.function = GXcopy0x3;
358 GC aMonoGC = XCreateGC( pDisplay->GetDisplay(), icon_mask,
359 GCFunction(1L<<0)|GCForeground(1L<<2)|GCBackground(1L<<3), &aValues );
360
361 Bitmap aMask = aIcon.GetMask();
362 aMask.Invert();
363
364 X11SalBitmap *pMask = static_cast < X11SalBitmap * >
365 (aMask.ImplGetSalBitmap().get());
366
367 pMask->ImplDraw(icon_mask, nXScreen, 1, aRect, aMonoGC);
368 XFreeGC( pDisplay->GetDisplay(), aMonoGC );
369 }
370
371 return true;
372}
373
374void X11SalFrame::Init( SalFrameStyleFlags nSalFrameStyle, SalX11Screen nXScreen, SystemParentData const * pParentData, bool bUseGeometry )
375{
376 if( nXScreen.getXScreen() >= GetDisplay()->GetXScreenCount() )
377 nXScreen = GetDisplay()->GetDefaultXScreen();
378 if( mpParent )
379 nXScreen = mpParent->m_nXScreen;
380
381 m_nXScreen = nXScreen;
382 nStyle_ = nSalFrameStyle;
383 XWMHints Hints;
384 Hints.flags = InputHint(1L << 0);
385 Hints.input = (nSalFrameStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) ? False0 : True1;
386 NetWmIconData netwm_icon;
387
388 int x = 0, y = 0;
389 unsigned int w = 500, h = 500;
390 XSetWindowAttributes Attributes;
391
392 int nAttrMask = CWBorderPixel(1L<<3)
393 | CWBackPixmap(1L<<0)
394 | CWColormap(1L<<13)
395 | CWOverrideRedirect(1L<<9)
396 | CWEventMask(1L<<11)
397 ;
398 Attributes.border_pixel = 0;
399 Attributes.background_pixmap = None0L;
400 Attributes.colormap = GetDisplay()->GetColormap( m_nXScreen ).GetXColormap();
401 Attributes.override_redirect = False0;
402 Attributes.event_mask = CLIENT_EVENTS;
403
404 const SalVisual& rVis = GetDisplay()->GetVisual( m_nXScreen );
405 ::Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nXScreen );
406 ::Window aClientLeader = None0L;
407
408 if( bUseGeometry )
409 {
410 x = maGeometry.nX;
411 y = maGeometry.nY;
412 w = maGeometry.nWidth;
413 h = maGeometry.nHeight;
414 }
415
416 if( (nSalFrameStyle & SalFrameStyleFlags::FLOAT) &&
417 ! (nSalFrameStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
418 )
419 {
420 if( nShowState_ == SHOWSTATE_UNKNOWN-1 )
421 {
422 w = 10;
423 h = 10;
424 }
425 Attributes.override_redirect = True1;
426 }
427 else if( nSalFrameStyle & SalFrameStyleFlags::SYSTEMCHILD )
428 {
429 SAL_WARN_IF( !mpParent, "vcl", "SalFrameStyleFlags::SYSTEMCHILD window without parent" )do { if (true && (!mpParent)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "SalFrameStyleFlags::SYSTEMCHILD window without parent"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "429" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SalFrameStyleFlags::SYSTEMCHILD window without parent"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SalFrameStyleFlags::SYSTEMCHILD window without parent"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "429" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "SalFrameStyleFlags::SYSTEMCHILD window without parent"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "429" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SalFrameStyleFlags::SYSTEMCHILD window without parent"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SalFrameStyleFlags::SYSTEMCHILD window without parent"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "429" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
430 if( mpParent )
431 {
432 aFrameParent = mpParent->mhWindow;
433 // FIXME: since with SalFrameStyleFlags::SYSTEMCHILD
434 // multiple X11SalFrame objects can have the same shell window
435 // dispatching events in saldisp.cxx is unclear (the first frame)
436 // wins. HTH this correctly is unclear yet
437 // for the time being, treat set the shell window to own window
438 // like for a normal frame
439 // mhShellWindow = mpParent->GetShellWindow();
440 }
441 }
442 else if( pParentData )
443 {
444 // plugin parent may be killed unexpectedly by plugging
445 // process; start permanently ignoring X errors...
446 GetGenericUnixSalData()->ErrorTrapPush();
447
448 nStyle_ |= SalFrameStyleFlags::PLUG;
449 Attributes.override_redirect = True1;
450 if( pParentData->nSize >= sizeof(SystemParentData) )
451 m_bXEmbed = pParentData->bXEmbedSupport;
452
453 int x_ret, y_ret;
454 unsigned int bw, d;
455 ::Window aRoot, aParent;
456
457 XGetGeometry( GetXDisplay(), pParentData->aWindow,
458 &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
459 mhForeignParent = pParentData->aWindow;
460
461 mhShellWindow = aParent = mhForeignParent;
462 ::Window* pChildren;
463 unsigned int nChildren;
464 bool bBreak = false;
465 do
466 {
467 XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow,
468 &aRoot, &aParent, &pChildren, &nChildren );
469 XFree( pChildren );
470 if( aParent != aRoot )
471 mhShellWindow = aParent;
472 int nCount = 0;
473 Atom* pProps = XListProperties( GetDisplay()->GetDisplay(),
474 mhShellWindow,
475 &nCount );
476 for( int i = 0; i < nCount && ! bBreak; ++i )
477 bBreak = (pProps[i] == XA_WM_HINTS((Atom) 35));
478 if( pProps )
479 XFree( pProps );
480 } while( aParent != aRoot && ! bBreak );
481
482 // check if this is really one of our own frames
483 // do not change the input mask in that case
484 bool bIsReallyOurFrame = false;
485 for (auto pSalFrame : GetDisplay()->getFrames() )
486 if ( static_cast<const X11SalFrame*>( pSalFrame )->GetWindow() == mhForeignParent )
487 {
488 bIsReallyOurFrame = true;
489 break;
490 }
491 if (!bIsReallyOurFrame)
492 {
493 XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask(1L<<17) | FocusChangeMask(1L<<21) );
494 XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask(1L<<17) | FocusChangeMask(1L<<21) );
495 }
496 }
497 else
498 {
499 if( ! bUseGeometry )
500 {
501 Size aScreenSize( GetDisplay()->getDataForScreen( m_nXScreen ).m_aSize );
502 w = aScreenSize.Width();
503 h = aScreenSize.Height();
504 if( nSalFrameStyle & SalFrameStyleFlags::SIZEABLE &&
505 nSalFrameStyle & SalFrameStyleFlags::MOVEABLE )
506 {
507 Size aBestFitSize(bestmaxFrameSizeForScreenSize(aScreenSize));
508 w = aBestFitSize.Width();
509 h = aBestFitSize.Height();
510 }
511 if( ! mpParent )
512 {
513 // find the last document window (if any)
514 const X11SalFrame* pFrame = nullptr;
515 bool bIsDocumentWindow = false;
516 for (auto pSalFrame : GetDisplay()->getFrames() )
517 {
518 pFrame = static_cast< const X11SalFrame* >( pSalFrame );
519 if( !pFrame->mpParent
520 && !pFrame->mbFullScreen
521 && ( pFrame->nStyle_ & SalFrameStyleFlags::SIZEABLE )
522 && pFrame->GetUnmirroredGeometry().nWidth
523 && pFrame->GetUnmirroredGeometry().nHeight )
524 {
525 bIsDocumentWindow = true;
526 break;
527 }
528 }
529
530 if( bIsDocumentWindow )
531 {
532 // set a document position and size
533 // the first frame gets positioned by the window manager
534 const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
535 x = rGeom.nX;
536 y = rGeom.nY;
537 if( x+static_cast<int>(w)+40 <= static_cast<int>(aScreenSize.Width()) &&
538 y+static_cast<int>(h)+40 <= static_cast<int>(aScreenSize.Height())
539 )
540 {
541 y += 40;
542 x += 40;
543 }
544 else
545 {
546 x = 10; // leave some space for decoration
547 y = 20;
548 }
549 }
550 else if( GetDisplay()->IsXinerama() )
551 {
552 // place frame on same screen as mouse pointer
553 ::Window aRoot, aChild;
554 int root_x = 0, root_y = 0, lx, ly;
555 unsigned int mask;
556 XQueryPointer( GetXDisplay(),
557 GetDisplay()->GetRootWindow( m_nXScreen ),
558 &aRoot, &aChild,
559 &root_x, &root_y, &lx, &ly, &mask );
560 const std::vector< tools::Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
561 for(const auto & rScreen : rScreens)
562 if( rScreen.IsInside( Point( root_x, root_y ) ) )
563 {
564 x = rScreen.Left();
565 y = rScreen.Top();
566 break;
567 }
568 }
569 }
570 }
571 Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity();
572 nAttrMask |= CWWinGravity(1L<<5);
573 if( mpParent )
574 {
575 Attributes.save_under = True1;
576 nAttrMask |= CWSaveUnder(1L<<10);
577 }
578 if( IsOverrideRedirect() )
579 Attributes.override_redirect = True1;
580 // default icon
581 if( !(nStyle_ & SalFrameStyleFlags::INTRO) )
582 {
583 bool bOk=false;
584 try
585 {
586 bOk = lcl_SelectAppIconPixmap( pDisplay_, m_nXScreen,
587 mnIconID != SV_ICON_ID_OFFICE1 ? mnIconID :
588 (mpParent ? mpParent->mnIconID : SV_ICON_ID_OFFICE1), 32,
589 Hints.icon_pixmap, Hints.icon_mask, netwm_icon );
590 }
591 catch( css::uno::Exception& )
592 {
593 // can happen - no ucb during early startup
594 }
595 if( bOk )
596 {
597 Hints.flags |= IconPixmapHint(1L << 2);
598 if( Hints.icon_mask )
599 Hints.flags |= IconMaskHint(1L << 5);
600 }
601 }
602
603 // find the top level frame of the transience hierarchy
604 X11SalFrame* pFrame = this;
605 while( pFrame->mpParent )
606 pFrame = pFrame->mpParent;
607 if( pFrame->nStyle_ & SalFrameStyleFlags::PLUG )
608 {
609 // if the top level window is a plugin window,
610 // then we should place us in the same window group as
611 // the parent application (or none if there is no window group
612 // hint in the parent).
613 if( pFrame->GetShellWindow() )
614 {
615 XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(),
616 pFrame->GetShellWindow() );
617 if( pWMHints )
618 {
619 if( pWMHints->flags & WindowGroupHint(1L << 6) )
620 {
621 Hints.flags |= WindowGroupHint(1L << 6);
622 Hints.window_group = pWMHints->window_group;
623 }
624 XFree( pWMHints );
625 }
626 }
627 }
628 else
629 {
630 Hints.flags |= WindowGroupHint(1L << 6);
631 Hints.window_group = pFrame->GetShellWindow();
632 // note: for a normal document window this will produce None
633 // as the window is not yet created and the shell window is
634 // initialized to None. This must be corrected after window creation.
635 aClientLeader = GetDisplay()->GetDrawable( m_nXScreen );
636 }
637 }
638
639 nShowState_ = SHOWSTATE_UNKNOWN-1;
640 bViewable_ = true;
641 bMapped_ = false;
642 nVisibility_ = VisibilityFullyObscured2;
643 mhWindow = XCreateWindow( GetXDisplay(),
644 aFrameParent,
645 x, y,
646 w, h,
647 0,
648 rVis.GetDepth(),
649 InputOutput1,
650 rVis.GetVisual(),
651 nAttrMask,
652 &Attributes );
653 // FIXME: see above: fake shell window for now to own window
654 if( pParentData == nullptr )
655 {
656 mhShellWindow = mhWindow;
657 }
658
659 // correct window group if necessary
660 if( (Hints.flags & WindowGroupHint(1L << 6)) == WindowGroupHint(1L << 6) )
661 {
662 if( Hints.window_group == None0L )
663 Hints.window_group = GetShellWindow();
664 }
665
666 maGeometry.nX = x;
667 maGeometry.nY = y;
668 maGeometry.nWidth = w;
669 maGeometry.nHeight = h;
670 updateScreenNumber();
671
672 XSync( GetXDisplay(), False0 );
673 setXEmbedInfo();
674
675 Time nUserTime = (nStyle_ & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::TOOLWINDOW) ) == SalFrameStyleFlags::NONE ?
676 pDisplay_->GetLastUserEventTime() : 0;
677 pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime );
678
679 if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect )
680 {
681 XSetWMHints( GetXDisplay(), mhWindow, &Hints );
682 // WM Protocols && internals
683 Atom a[3];
684 int n = 0;
685 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
686
687// LibreOffice advertises NET_WM_PING atom, so mutter rightfully warns of an unresponsive application during debugging.
688// Hack that out unconditionally for debug builds, as per https://bugzilla.redhat.com/show_bug.cgi?id=981149
689// upstream refuses to make this configurable in any way.
690// NOTE: You need to use the 'gen' backend for this to work (SAL_USE_VCLPLUGIN=gen)
691#if OSL_DEBUG_LEVEL1 < 1
692 if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) )
693 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING );
694#endif
695
696 if( nSalFrameStyle & SalFrameStyleFlags::OWNERDRAWDECORATION )
697 a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS );
698 XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n );
699
700 // force wm class hint
701 mnExtStyle = ~0;
702 if (mpParent)
703 m_sWMClass = mpParent->m_sWMClass;
704 SetExtendedFrameStyle( 0 );
705
706 XSizeHints* pHints = XAllocSizeHints();
707 pHints->flags = PWinGravity(1L << 9) | PPosition(1L << 2);
708 pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity();
709 pHints->x = 0;
710 pHints->y = 0;
711 if( mbFullScreen )
712 {
713 pHints->flags |= PMaxSize(1L << 5) | PMinSize(1L << 4);
714 pHints->max_width = w+100;
715 pHints->max_height = h+100;
716 pHints->min_width = w;
717 pHints->min_height = h;
718 }
719 XSetWMNormalHints( GetXDisplay(),
720 GetShellWindow(),
721 pHints );
722 XFree (pHints);
723
724 // set PID and WM_CLIENT_MACHINE
725 pDisplay_->getWMAdaptor()->setClientMachine( this );
726 pDisplay_->getWMAdaptor()->setPID( this );
727
728 // set client leader
729 if( aClientLeader )
730 {
731 XChangeProperty( GetXDisplay(),
732 mhWindow,
733 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER),
734 XA_WINDOW((Atom) 33),
735 32,
736 PropModeReplace0,
737 reinterpret_cast<unsigned char*>(&aClientLeader),
738 1
739 );
740 }
741#define DECOFLAGS(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE |
SalFrameStyleFlags::CLOSEABLE)
(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::CLOSEABLE)
742 int nDecoFlags = WMAdaptor::decoration_All;
743 if( (nStyle_ & SalFrameStyleFlags::PARTIAL_FULLSCREEN) ||
744 (nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION)
745 )
746 nDecoFlags = 0;
747 else if( (nStyle_ & DECOFLAGS(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE |
SalFrameStyleFlags::CLOSEABLE)
) != DECOFLAGS(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE |
SalFrameStyleFlags::CLOSEABLE)
|| (nStyle_ & SalFrameStyleFlags::TOOLWINDOW) )
748 {
749 if( nStyle_ & DECOFLAGS(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE |
SalFrameStyleFlags::CLOSEABLE)
)
750 // if any decoration, then show a border
751 nDecoFlags = WMAdaptor::decoration_Border;
752 else
753 nDecoFlags = 0;
754
755 if( ! mpParent && (nStyle_ & DECOFLAGS(SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE |
SalFrameStyleFlags::CLOSEABLE)
) )
756 // don't add a min button if window should be decorationless
757 nDecoFlags |= WMAdaptor::decoration_MinimizeBtn;
758 if( nStyle_ & SalFrameStyleFlags::CLOSEABLE )
759 nDecoFlags |= WMAdaptor::decoration_CloseBtn;
760 if( nStyle_ & SalFrameStyleFlags::SIZEABLE )
761 {
762 nDecoFlags |= WMAdaptor::decoration_Resize;
763 if( ! (nStyle_ & SalFrameStyleFlags::TOOLWINDOW) )
764 nDecoFlags |= WMAdaptor::decoration_MaximizeBtn;
765 }
766 if( nStyle_ & SalFrameStyleFlags::MOVEABLE )
767 nDecoFlags |= WMAdaptor::decoration_Title;
768 }
769
770 WMWindowType eType = WMWindowType::Normal;
771 if( nStyle_ & SalFrameStyleFlags::INTRO )
772 eType = WMWindowType::Splash;
773 if( (nStyle_ & SalFrameStyleFlags::DIALOG) && hPresentationWindow == None0L )
774 eType = WMWindowType::ModelessDialogue;
775 if( nStyle_ & SalFrameStyleFlags::TOOLWINDOW )
776 eType = WMWindowType::Utility;
777 if( nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION )
778 eType = WMWindowType::Toolbar;
779 if( (nStyle_ & SalFrameStyleFlags::PARTIAL_FULLSCREEN)
780 && GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
781 eType = WMWindowType::Dock;
782
783 GetDisplay()->getWMAdaptor()->
784 setFrameTypeAndDecoration( this,
785 eType,
786 nDecoFlags,
787 hPresentationWindow ? nullptr : mpParent );
788
789 if( (nStyle_ & (SalFrameStyleFlags::DEFAULT |
790 SalFrameStyleFlags::OWNERDRAWDECORATION|
791 SalFrameStyleFlags::FLOAT |
792 SalFrameStyleFlags::INTRO |
793 SalFrameStyleFlags::PARTIAL_FULLSCREEN) )
794 == SalFrameStyleFlags::DEFAULT )
795 pDisplay_->getWMAdaptor()->maximizeFrame( this );
796
797 if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ))
798 XChangeProperty( GetXDisplay(), mhWindow,
799 GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ),
800 XA_CARDINAL((Atom) 6), 32, PropModeReplace0, reinterpret_cast<unsigned char*>(netwm_icon.data()), netwm_icon.size());
801 }
802
803 m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea();
804
805 // Pointer
806 SetPointer( PointerStyle::Arrow );
807}
808
809X11SalFrame::X11SalFrame( SalFrame *pParent, SalFrameStyleFlags nSalFrameStyle,
810 SystemParentData const * pSystemParent ) :
811 m_nXScreen( 0 )
812{
813 GenericUnixSalData *pData = GetGenericUnixSalData();
814
815 mpParent = static_cast< X11SalFrame* >( pParent );
816
817 mbTransientForRoot = false;
818
819 pDisplay_ = vcl_sal::getSalDisplay(pData);
820 // insert frame in framelist
821 pDisplay_->registerFrame( this );
822
823 mhWindow = None0L;
824 mhShellWindow = None0L;
825 mhStackingWindow = None0L;
826 mhForeignParent = None0L;
827 m_bSetFocusOnMap = false;
828
829 pGraphics_ = nullptr;
830 pFreeGraphics_ = nullptr;
831
832 hCursor_ = None0L;
833 nCaptured_ = 0;
834
835 mbSendExtKeyModChange = false;
836 mnExtKeyMod = ModKeyFlags::NONE;
837
838 nShowState_ = SHOWSTATE_UNKNOWN-1;
839 nWidth_ = 0;
840 nHeight_ = 0;
841 nStyle_ = SalFrameStyleFlags::NONE;
842 mnExtStyle = 0;
843 bAlwaysOnTop_ = false;
844
845 // set bViewable_ to true: hack GetClientSize to report something
846 // different to 0/0 before first map
847 bViewable_ = true;
848 bMapped_ = false;
849 bDefaultPosition_ = true;
850 nVisibility_ = VisibilityFullyObscured2;
851 m_nWorkArea = 0;
852 m_bXEmbed = false;
853
854
855 mpInputContext = nullptr;
856 mbInputFocus = False0;
857
858 maAlwaysOnTopRaiseTimer.SetInvokeHandler( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise )::tools::detail::makeLink( ::tools::detail::castTo<X11SalFrame
*>(this), &X11SalFrame::LinkStubHandleAlwaysOnTopRaise
)
);
859 maAlwaysOnTopRaiseTimer.SetTimeout( 100 );
860 maAlwaysOnTopRaiseTimer.SetDebugName( "vcl::X11SalFrame maAlwaysOnTopRaiseTimer" );
861
862 meWindowType = WMWindowType::Normal;
863 mbMaximizedVert = false;
864 mbMaximizedHorz = false;
865 mbShaded = false;
866 mbFullScreen = false;
867
868 mnIconID = SV_ICON_ID_OFFICE1;
869
870 if( mpParent )
871 mpParent->maChildren.push_back( this );
872
873 Init( nSalFrameStyle, GetDisplay()->GetDefaultXScreen(), pSystemParent );
874}
875
876X11SalFrame::~X11SalFrame()
877{
878 notifyDelete();
879
880 m_vClipRectangles.clear();
881
882 if( mhStackingWindow )
883 aPresentationReparentList.remove( mhStackingWindow );
884
885 // remove from parent's list
886 if( mpParent )
887 mpParent->maChildren.remove( this );
888
889 // deregister on SalDisplay
890 pDisplay_->deregisterFrame( this );
891
892 // unselect all events, some may be still in the queue anyway
893 if( ! IsSysChildWindow() )
894 XSelectInput( GetXDisplay(), GetShellWindow(), 0 );
895 XSelectInput( GetXDisplay(), GetWindow(), 0 );
896
897 ShowFullScreen( false, 0 );
898
899 if( bMapped_ )
900 Show( false );
901
902 if( mpInputContext )
903 {
904 mpInputContext->UnsetICFocus();
905 mpInputContext->Unmap();
906 mpInputContext.reset();
907 }
908
909 if( GetWindow() == hPresentationWindow )
910 {
911 hPresentationWindow = None0L;
912 doReparentPresentationDialogues( GetDisplay() );
913 }
914
915 if( pGraphics_ )
916 {
917 pGraphics_->DeInit();
918 pGraphics_.reset();
919 }
920
921 if( pFreeGraphics_ )
922 {
923 pFreeGraphics_->DeInit();
924 pFreeGraphics_.reset();
925 }
926
927 // reset all OpenGL contexts using this window
928 rtl::Reference<OpenGLContext> pContext = ImplGetSVData()->maGDIData.mpLastContext;
929 while( pContext.is() )
930 {
931 if (static_cast<const GLX11Window&>(pContext->getOpenGLWindow()).win == mhWindow)
932 pContext->reset();
933 pContext = pContext->mpPrevContext;
934 }
935
936 XDestroyWindow( GetXDisplay(), mhWindow );
937}
938
939void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
940{
941 if( nStyle != mnExtStyle && ! IsChildWindow() )
942 {
943 mnExtStyle = nStyle;
944 updateWMClass();
945 }
946}
947
948const SystemEnvData* X11SalFrame::GetSystemData() const
949{
950 X11SalFrame *pFrame = const_cast<X11SalFrame*>(this);
951 pFrame->maSystemChildData.pDisplay = GetXDisplay();
952 pFrame->maSystemChildData.aWindow = pFrame->GetWindow();
953 pFrame->maSystemChildData.pSalFrame = pFrame;
954 pFrame->maSystemChildData.pWidget = nullptr;
955 pFrame->maSystemChildData.pVisual = GetDisplay()->GetVisual( m_nXScreen ).GetVisual();
956 pFrame->maSystemChildData.nScreen = m_nXScreen.getXScreen();
957 pFrame->maSystemChildData.aShellWindow = pFrame->GetShellWindow();
958 pFrame->maSystemChildData.toolkit = SystemEnvData::Toolkit::Gen;
959 pFrame->maSystemChildData.platform = SystemEnvData::Platform::Xcb;
960 return &maSystemChildData;
961}
962
963SalGraphics *X11SalFrame::AcquireGraphics()
964{
965 if( pGraphics_ )
966 return nullptr;
967
968 if( pFreeGraphics_ )
969 {
970 pGraphics_ = std::move(pFreeGraphics_);
971 }
972 else
973 {
974 pGraphics_.reset(new X11SalGraphics());
975 pGraphics_->Init( this, GetWindow(), m_nXScreen );
976 }
977
978 return pGraphics_.get();
979}
980
981void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics )
982{
983 SAL_WARN_IF( pGraphics != pGraphics_.get(), "vcl", "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" )do { if (true && (pGraphics != pGraphics_.get())) { switch
(sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) {
case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "983" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "983" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "983" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SalFrame::ReleaseGraphics pGraphics!=pGraphics_"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "983" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
984
985 if( pGraphics != pGraphics_.get() )
986 return;
987
988 pFreeGraphics_ = std::move(pGraphics_);
989}
990
991void X11SalFrame::updateGraphics( bool bClear )
992{
993 Drawable aDrawable = bClear ? None0L : GetWindow();
994 if( pGraphics_ )
995 pGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen );
996 if( pFreeGraphics_ )
997 pFreeGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen );
998}
999
1000void X11SalFrame::SetIcon( sal_uInt16 nIcon )
1001{
1002 if ( IsChildWindow() )
1003 return;
1004
1005 // 0 == default icon -> #1
1006 if ( nIcon == 0 )
1007 nIcon = 1;
1008
1009 mnIconID = nIcon;
1010
1011 XIconSize *pIconSize = nullptr;
1012 int nSizes = 0;
1013 int iconSize = 32;
1014 if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nXScreen ), &pIconSize, &nSizes ) )
1015 {
1016#if OSL_DEBUG_LEVEL1 > 1
1017 SAL_INFO("vcl.window", "X11SalFrame::SetIcon(): found "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::SetIcon(): found " << nSizes <<
" IconSizes:") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1018 << nSizesdo { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::SetIcon(): found " << nSizes <<
" IconSizes:") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1019 << " IconSizes:")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::SetIcon(): found " << nSizes <<
" IconSizes:") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::SetIcon(): found " <<
nSizes << " IconSizes:"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "X11SalFrame::SetIcon(): found "
<< nSizes << " IconSizes:"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1020#endif
1021 int i;
1022 for( i=0; i<nSizes; i++)
1023 {
1024 // select largest supported icon
1025 if( pIconSize[i].max_width > iconSize )
1026 {
1027 iconSize = pIconSize[i].max_width;
1028 }
1029
1030#if OSL_DEBUG_LEVEL1 > 1
1031 SAL_INFO("vcl.window", "min: "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "min: " << pIconSize
[i].min_width << ", " << pIconSize[i].min_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "min: " << pIconSize[i].min_width << ", "
<< pIconSize[i].min_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1032 << pIconSize[i].min_widthdo { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "min: " << pIconSize
[i].min_width << ", " << pIconSize[i].min_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "min: " << pIconSize[i].min_width << ", "
<< pIconSize[i].min_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1033 << ", "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "min: " << pIconSize
[i].min_width << ", " << pIconSize[i].min_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "min: " << pIconSize[i].min_width << ", "
<< pIconSize[i].min_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1034 << pIconSize[i].min_height)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "min: " << pIconSize
[i].min_width << ", " << pIconSize[i].min_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "min: " << pIconSize[i].min_width << ", "
<< pIconSize[i].min_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "min: " << pIconSize[i].min_width
<< ", " << pIconSize[i].min_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"min: " << pIconSize[i].min_width << ", " <<
pIconSize[i].min_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1034" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1035 SAL_INFO("vcl.window", "max: "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "max: " << pIconSize
[i].max_width << ", " << pIconSize[i].max_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "max: " << pIconSize[i].max_width << ", "
<< pIconSize[i].max_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1036 << pIconSize[i].max_widthdo { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "max: " << pIconSize
[i].max_width << ", " << pIconSize[i].max_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "max: " << pIconSize[i].max_width << ", "
<< pIconSize[i].max_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1037 << ", "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "max: " << pIconSize
[i].max_width << ", " << pIconSize[i].max_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "max: " << pIconSize[i].max_width << ", "
<< pIconSize[i].max_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1038 << pIconSize[i].max_height)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "max: " << pIconSize
[i].max_width << ", " << pIconSize[i].max_height)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "max: " << pIconSize[i].max_width << ", "
<< pIconSize[i].max_height) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "max: " << pIconSize[i].max_width
<< ", " << pIconSize[i].max_height), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"max: " << pIconSize[i].max_width << ", " <<
pIconSize[i].max_height; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1038" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1039 SAL_INFO("vcl.window", "inc: "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "inc: " << pIconSize
[i].width_inc << ", " << pIconSize[i].height_inc)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "inc: " << pIconSize[i].width_inc << ", "
<< pIconSize[i].height_inc) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1040 << pIconSize[i].width_incdo { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "inc: " << pIconSize
[i].width_inc << ", " << pIconSize[i].height_inc)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "inc: " << pIconSize[i].width_inc << ", "
<< pIconSize[i].height_inc) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1041 << ", "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "inc: " << pIconSize
[i].width_inc << ", " << pIconSize[i].height_inc)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "inc: " << pIconSize[i].width_inc << ", "
<< pIconSize[i].height_inc) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1042 << pIconSize[i].height_inc)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "inc: " << pIconSize
[i].width_inc << ", " << pIconSize[i].height_inc)
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "inc: " << pIconSize[i].width_inc << ", "
<< pIconSize[i].height_inc) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "inc: " << pIconSize[i].width_inc
<< ", " << pIconSize[i].height_inc), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"inc: " << pIconSize[i].width_inc << ", " <<
pIconSize[i].height_inc; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "1042" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1043#endif
1044 }
1045
1046 XFree( pIconSize );
1047 }
1048 else
1049 {
1050 const OUString& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );
1051 if( rWM == "KWin" ) // assume KDE is running
1052 iconSize = 48;
1053 static bool bGnomeIconSize = false;
1054 static bool bGnomeChecked = false;
1055 if( ! bGnomeChecked )
1056 {
1057 bGnomeChecked=true;
1058 int nCount = 0;
1059 Atom* pProps = XListProperties( GetXDisplay(),
1060 GetDisplay()->GetRootWindow( m_nXScreen ),
1061 &nCount );
1062 for( int i = 0; i < nCount && !bGnomeIconSize; i++ )
1063 {
1064 char* pName = XGetAtomName( GetXDisplay(), pProps[i] );
1065 if( pName )
1066 {
1067 if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) )
1068 bGnomeIconSize = true;
1069 XFree( pName );
1070 }
1071 }
1072 if( pProps )
1073 XFree( pProps );
1074 }
1075 if( bGnomeIconSize )
1076 iconSize = 48;
1077 }
1078
1079 XWMHints Hints;
1080 Hints.flags = 0;
1081 XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() );
1082 if( pHints )
1083 {
1084 memcpy(&Hints, pHints, sizeof( XWMHints ));
1085 XFree( pHints );
1086 }
1087 pHints = &Hints;
1088
1089 NetWmIconData netwm_icon;
1090 bool bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen,
1091 nIcon, iconSize,
1092 pHints->icon_pixmap, pHints->icon_mask, netwm_icon );
1093 if ( !bOk )
1094 {
1095 // load default icon (0)
1096 bOk = lcl_SelectAppIconPixmap( GetDisplay(), m_nXScreen,
1097 0, iconSize,
1098 pHints->icon_pixmap, pHints->icon_mask, netwm_icon );
1099 }
1100 if( bOk )
1101 {
1102 pHints->flags |= IconPixmapHint(1L << 2);
1103 if( pHints->icon_mask )
1104 pHints->flags |= IconMaskHint(1L << 5);
1105
1106 XSetWMHints( GetXDisplay(), GetShellWindow(), pHints );
1107 if( !netwm_icon.empty() && GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ))
1108 XChangeProperty( GetXDisplay(), mhWindow,
1109 GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_ICON ),
1110 XA_CARDINAL((Atom) 6), 32, PropModeReplace0, reinterpret_cast<unsigned char*>(netwm_icon.data()), netwm_icon.size());
1111 }
1112
1113}
1114
1115void X11SalFrame::SetMaxClientSize( long nWidth, long nHeight )
1116{
1117 if( IsChildWindow() )
1118 return;
1119
1120 if( !GetShellWindow() ||
1121 (nStyle_ & (SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::OWNERDRAWDECORATION) ) == SalFrameStyleFlags::FLOAT )
1122 return;
1123
1124 XSizeHints* pHints = XAllocSizeHints();
1125 long nSupplied = 0;
1126 XGetWMNormalHints( GetXDisplay(),
1127 GetShellWindow(),
1128 pHints,
1129 &nSupplied
1130 );
1131 pHints->max_width = nWidth;
1132 pHints->max_height = nHeight;
1133 pHints->flags |= PMaxSize(1L << 5);
1134 XSetWMNormalHints( GetXDisplay(),
1135 GetShellWindow(),
1136 pHints );
1137 XFree( pHints );
1138}
1139
1140void X11SalFrame::SetMinClientSize( long nWidth, long nHeight )
1141{
1142 if( IsChildWindow() )
1143 return;
1144
1145 if( !GetShellWindow() ||
1146 (nStyle_ & (SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::OWNERDRAWDECORATION) ) == SalFrameStyleFlags::FLOAT )
1147 return;
1148
1149 XSizeHints* pHints = XAllocSizeHints();
1150 long nSupplied = 0;
1151 XGetWMNormalHints( GetXDisplay(),
1152 GetShellWindow(),
1153 pHints,
1154 &nSupplied
1155 );
1156 pHints->min_width = nWidth;
1157 pHints->min_height = nHeight;
1158 pHints->flags |= PMinSize(1L << 4);
1159 XSetWMNormalHints( GetXDisplay(),
1160 GetShellWindow(),
1161 pHints );
1162 XFree( pHints );
1163}
1164
1165// Show + Pos (x,y,z) + Size (width,height)
1166
1167void X11SalFrame::Show( bool bVisible, bool bNoActivate )
1168{
1169 if( ( bVisible && bMapped_ )
1170 || ( !bVisible && !bMapped_ ) )
1171 return;
1172
1173 // HACK: this is a workaround for (at least) kwin
1174 // even though transient frames should be kept above their parent
1175 // this does not necessarily hold true for DOCK type windows
1176 // so artificially set ABOVE and remove it again on hide
1177 if( mpParent && (mpParent->nStyle_ & SalFrameStyleFlags::PARTIAL_FULLSCREEN ) && pDisplay_->getWMAdaptor()->isLegacyPartialFullscreen())
1178 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible );
1179
1180 bMapped_ = bVisible;
1181 bViewable_ = bVisible;
1182 setXEmbedInfo();
1183 if( bVisible )
1184 {
1185 if( ! (nStyle_ & SalFrameStyleFlags::INTRO) )
1186 {
1187 // hide all INTRO frames
1188 for (auto pSalFrame : GetDisplay()->getFrames() )
1189 {
1190 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( pSalFrame );
1191 // look for intro bit map; if present, hide it
1192 if( pFrame->nStyle_ & SalFrameStyleFlags::INTRO )
1193 {
1194 if( pFrame->bMapped_ )
1195 const_cast<X11SalFrame*>(pFrame)->Show( false );
1196 }
1197 }
1198 }
1199
1200 // update NET_WM_STATE which may have been deleted due to earlier Show(false)
1201 if( nShowState_ == SHOWSTATE_HIDDEN2 )
1202 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1203
1204 /*
1205 * Actually this is rather exotic and currently happens only in conjunction
1206 * with the basic dialogue editor,
1207 * which shows a frame and instantly hides it again. After that the
1208 * editor window is shown and the WM takes this as an opportunity
1209 * to show our hidden transient frame also. So Show( false ) must
1210 * withdraw the frame AND delete the WM_TRANSIENT_FOR property.
1211 * In case the frame is shown again, the transient hint must be restored here.
1212 */
1213 if( ! IsChildWindow()
1214 && ! IsOverrideRedirect()
1215 && ! IsFloatGrabWindow()
1216 && mpParent
1217 )
1218 {
1219 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
1220 }
1221
1222 // #i45160# switch to desktop where a dialog with parent will appear
1223 if( mpParent && mpParent->m_nWorkArea != m_nWorkArea )
1224 GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea );
1225
1226 if( IsFloatGrabWindow() &&
1227 mpParent &&
1228 nVisibleFloats == 0 &&
1229 ! GetDisplay()->GetCaptureFrame() )
1230 {
1231 /* #i39420#
1232 * outsmart KWin's "focus strictly under mouse" mode
1233 * which insists on taking the focus from the document
1234 * to the new float. Grab focus to parent frame BEFORE
1235 * showing the float (cannot grab it to the float
1236 * before show).
1237 */
1238 XGrabPointer( GetXDisplay(),
1239 mpParent->GetWindow(),
1240 True1,
1241 PointerMotionMask(1L<<6) | ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3),
1242 GrabModeAsync1,
1243 GrabModeAsync1,
1244 None0L,
1245 mpParent ? mpParent->GetCursor() : None0L,
1246 CurrentTime0L
1247 );
1248 }
1249
1250 Time nUserTime = 0;
1251 if( ! bNoActivate && !(nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION) )
1252 nUserTime = pDisplay_->GetX11ServerTime();
1253 GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime );
1254 if( ! bNoActivate && (nStyle_ & SalFrameStyleFlags::TOOLWINDOW) )
1255 m_bSetFocusOnMap = true;
1256
1257 // actually map the window
1258 if( m_bXEmbed )
1259 askForXEmbedFocus( 0 );
1260 else
1261 {
1262 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1263 {
1264 if( IsChildWindow() )
1265 XMapWindow( GetXDisplay(), GetShellWindow() );
1266 XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS );
1267 }
1268 if( nStyle_ & SalFrameStyleFlags::FLOAT )
1269 XMapRaised( GetXDisplay(), GetWindow() );
1270 else
1271 XMapWindow( GetXDisplay(), GetWindow() );
1272 }
1273 XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS );
1274
1275 if( maGeometry.nWidth > 0
1276 && maGeometry.nHeight > 0
1277 && ( nWidth_ != static_cast<int>(maGeometry.nWidth)
1278 || nHeight_ != static_cast<int>(maGeometry.nHeight) ) )
1279 {
1280 nWidth_ = maGeometry.nWidth;
1281 nHeight_ = maGeometry.nHeight;
1282 }
1283
1284 XSync( GetXDisplay(), False0 );
1285
1286 if( IsFloatGrabWindow() )
1287 {
1288 /*
1289 * Sawfish and twm can be switched to enter-exit focus behaviour. In this case
1290 * we must grab the pointer else the dumb WM will put the focus to the
1291 * override-redirect float window. The application window will be deactivated
1292 * which causes that the floats are destroyed, so the user can never click on
1293 * a menu because it vanishes as soon as he enters it.
1294 */
1295 nVisibleFloats++;
1296 if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() )
1297 {
1298 /* #i39420# now move grab to the new float window */
1299 XGrabPointer( GetXDisplay(),
1300 GetWindow(),
1301 True1,
1302 PointerMotionMask(1L<<6) | ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3),
1303 GrabModeAsync1,
1304 GrabModeAsync1,
1305 None0L,
1306 mpParent ? mpParent->GetCursor() : None0L,
1307 CurrentTime0L
1308 );
1309 }
1310 }
1311 CallCallback( SalEvent::Resize, nullptr );
1312
1313 /*
1314 * sometimes a message box/dialogue is brought up when a frame is not mapped
1315 * the corresponding TRANSIENT_FOR hint is then set to the root window
1316 * so that the dialogue shows in all cases. Correct it here if the
1317 * frame is shown afterwards.
1318 */
1319 if( ! IsChildWindow()
1320 && ! IsOverrideRedirect()
1321 && ! IsFloatGrabWindow()
1322 )
1323 {
1324 for (auto const& child : maChildren)
1325 {
1326 if( child->mbTransientForRoot )
1327 GetDisplay()->getWMAdaptor()->changeReferenceFrame( child, this );
1328 }
1329 }
1330 /*
1331 * leave SHOWSTATE_UNKNOWN as this indicates first mapping
1332 * and is only reset int HandleSizeEvent
1333 */
1334 if( nShowState_ != SHOWSTATE_UNKNOWN-1 )
1335 nShowState_ = SHOWSTATE_NORMAL1;
1336
1337 /*
1338 * plugged windows don't necessarily get the
1339 * focus on show because the parent may already be mapped
1340 * and have the focus. So try to set the focus
1341 * to the child on Show(true)
1342 */
1343 if( (nStyle_ & SalFrameStyleFlags::PLUG) && ! m_bXEmbed )
1344 XSetInputFocus( GetXDisplay(),
1345 GetWindow(),
1346 RevertToParent2,
1347 CurrentTime0L );
1348
1349 if( mpParent )
1350 {
1351 // push this frame so it will be in front of its siblings
1352 // only necessary for insane transient behaviour of Dtwm/olwm
1353 mpParent->maChildren.remove( this );
1354 mpParent->maChildren.push_front(this);
1355 }
1356 }
1357 else
1358 {
1359 if( getInputContext() )
1360 getInputContext()->Unmap();
1361
1362 if( ! IsChildWindow() )
1363 {
1364 /* FIXME: Is deleting the property really necessary ? It hurts
1365 * owner drawn windows at least.
1366 */
1367 if( mpParent && ! (nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION) )
1368 XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) );
1369 XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nXScreen.getXScreen() );
1370 }
1371 else if( ! m_bXEmbed )
1372 XUnmapWindow( GetXDisplay(), GetWindow() );
1373
1374 nShowState_ = SHOWSTATE_HIDDEN2;
1375 if( IsFloatGrabWindow() && nVisibleFloats )
1376 {
1377 nVisibleFloats--;
1378 if( nVisibleFloats == 0 && ! GetDisplay()->GetCaptureFrame() )
1379 XUngrabPointer( GetXDisplay(),
1380 CurrentTime0L );
1381 }
1382 // flush here; there may be a very seldom race between
1383 // the display connection used for clipboard and our connection
1384 Flush();
1385 }
1386}
1387
1388void X11SalFrame::ToTop( SalFrameToTop nFlags )
1389{
1390 if( ( nFlags & SalFrameToTop::RestoreWhenMin )
1391 && ! ( nStyle_ & SalFrameStyleFlags::FLOAT )
1392 && nShowState_ != SHOWSTATE_HIDDEN2
1393 && nShowState_ != SHOWSTATE_UNKNOWN-1
1394 )
1395 {
1396 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
1397 if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
1398 XMapWindow( GetXDisplay(), GetShellWindow() );
1399 XMapWindow( GetXDisplay(), GetWindow() );
1400 }
1401
1402 ::Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow();
1403 if( ! (nFlags & SalFrameToTop::GrabFocusOnly) )
1404 {
1405 XRaiseWindow( GetXDisplay(), aToTopWindow );
1406 }
1407
1408 if( ( ( nFlags & SalFrameToTop::GrabFocus ) || ( nFlags & SalFrameToTop::GrabFocusOnly ) )
1409 && bMapped_ )
1410 {
1411 if( m_bXEmbed )
1412 askForXEmbedFocus( 0 );
1413 else
1414 XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent2, CurrentTime0L );
1415 }
1416 else if( ( nFlags & SalFrameToTop::RestoreWhenMin ) || ( nFlags & SalFrameToTop::ForegroundTask ) )
1417 {
1418 Time nTimestamp = pDisplay_->GetX11ServerTime();
1419 GetDisplay()->getWMAdaptor()->activateWindow( this, nTimestamp );
1420 }
1421}
1422
1423void X11SalFrame::GetWorkArea( tools::Rectangle& rWorkArea )
1424{
1425 rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 );
1426}
1427
1428void X11SalFrame::GetClientSize( long &rWidth, long &rHeight )
1429{
1430 if( ! bViewable_ )
1431 {
1432 rWidth = rHeight = 0;
1433 return;
1434 }
1435
1436 rWidth = maGeometry.nWidth;
1437 rHeight = maGeometry.nHeight;
1438
1439 if( !rWidth || !rHeight )
1440 {
1441 XWindowAttributes aAttrib;
1442
1443 XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib );
1444
1445 maGeometry.nWidth = rWidth = aAttrib.width;
1446 maGeometry.nHeight = rHeight = aAttrib.height;
1447 }
1448}
1449
1450void X11SalFrame::Center( )
1451{
1452 int nX, nY, nScreenWidth, nScreenHeight;
1453 int nRealScreenWidth, nRealScreenHeight;
1454 int nScreenX = 0, nScreenY = 0;
1455
1456 const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nXScreen ).m_aSize;
1457 nScreenWidth = aScreenSize.Width();
1458 nScreenHeight = aScreenSize.Height();
1459 nRealScreenWidth = nScreenWidth;
1460 nRealScreenHeight = nScreenHeight;
1461
1462 if( GetDisplay()->IsXinerama() )
1463 {
1464 // get xinerama screen we are on
1465 // if there is a parent, use its center for screen determination
1466 // else use the pointer
1467 ::Window aRoot, aChild;
1468 int root_x, root_y, x, y;
1469 unsigned int mask;
1470 if( mpParent )
1471 {
1472 root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2;
1473 root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2;
1474 }
1475 else
1476 XQueryPointer( GetXDisplay(),
1477 GetShellWindow(),
1478 &aRoot, &aChild,
1479 &root_x, &root_y,
1480 &x, &y,
1481 &mask );
1482 const std::vector< tools::Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
1483 for(const auto & rScreen : rScreens)
1484 if( rScreen.IsInside( Point( root_x, root_y ) ) )
1485 {
1486 nScreenX = rScreen.Left();
1487 nScreenY = rScreen.Top();
1488 nRealScreenWidth = rScreen.GetWidth();
1489 nRealScreenHeight = rScreen.GetHeight();
1490 break;
1491 }
1492 }
1493
1494 if( mpParent )
1495 {
1496 X11SalFrame* pFrame = mpParent;
1497 while( pFrame->mpParent )
1498 pFrame = pFrame->mpParent;
1499 if( pFrame->maGeometry.nWidth < 1 || pFrame->maGeometry.nHeight < 1 )
1500 {
1501 tools::Rectangle aRect;
1502 pFrame->GetPosSize( aRect );
1503 pFrame->maGeometry.nX = aRect.Left();
1504 pFrame->maGeometry.nY = aRect.Top();
1505 pFrame->maGeometry.nWidth = aRect.GetWidth();
1506 pFrame->maGeometry.nHeight = aRect.GetHeight();
1507 }
1508
1509 if( pFrame->nStyle_ & SalFrameStyleFlags::PLUG )
1510 {
1511 ::Window aRoot;
1512 unsigned int bw, depth;
1513 XGetGeometry( GetXDisplay(),
1514 pFrame->GetShellWindow(),
1515 &aRoot,
1516 &nScreenX, &nScreenY,
1517 reinterpret_cast<unsigned int*>(&nScreenWidth),
1518 reinterpret_cast<unsigned int*>(&nScreenHeight),
1519 &bw, &depth );
1520 }
1521 else
1522 {
1523 nScreenX = pFrame->maGeometry.nX;
1524 nScreenY = pFrame->maGeometry.nY;
1525 nScreenWidth = pFrame->maGeometry.nWidth;
1526 nScreenHeight = pFrame->maGeometry.nHeight;
1527 }
1528 }
1529
1530 if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL1 )
1531 {
1532 if( maGeometry.nWidth >= mpParent->maGeometry.nWidth &&
1533 maGeometry.nHeight >= mpParent->maGeometry.nHeight )
1534 {
1535 nX = nScreenX + 40;
1536 nY = nScreenY + 40;
1537 }
1538 else
1539 {
1540 // center the window relative to the top level frame
1541 nX = (nScreenWidth - static_cast<int>(maGeometry.nWidth) ) / 2 + nScreenX;
1542 nY = (nScreenHeight - static_cast<int>(maGeometry.nHeight)) / 2 + nScreenY;
1543 }
1544 }
1545 else
1546 {
1547 // center the window relative to screen
1548 nX = (nRealScreenWidth - static_cast<int>(maGeometry.nWidth) ) / 2 + nScreenX;
1549 nY = (nRealScreenHeight - static_cast<int>(maGeometry.nHeight)) / 2 + nScreenY;
1550 }
1551 nX = nX < 0 ? 0 : nX;
1552 nY = nY < 0 ? 0 : nY;
1553
1554 bDefaultPosition_ = False0;
1555 if( mpParent )
1556 {
1557 nX -= mpParent->maGeometry.nX;
1558 nY -= mpParent->maGeometry.nY;
1559 }
1560
1561 Point aPoint(nX, nY);
1562 SetPosSize( tools::Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
1563}
1564
1565void X11SalFrame::updateScreenNumber()
1566{
1567 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
1568 {
1569 Point aPoint( maGeometry.nX, maGeometry.nY );
1570 const std::vector<tools::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.nDisplayScreenNumber = static_cast<unsigned int>(i);
1577 break;
1578 }
1579 }
1580 }
1581 else
1582 maGeometry.nDisplayScreenNumber = m_nXScreen.getXScreen();
1583}
1584
1585void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
1586{
1587 if( nStyle_ & SalFrameStyleFlags::PLUG )
1588 return;
1589
1590 // relative positioning in X11SalFrame::SetPosSize
1591 tools::Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) );
1592 aPosSize.Justify();
1593
1594 if( ! ( nFlags & SAL_FRAME_POSSIZE_X(sal_uInt16(0x0001)) ) )
1595 {
1596 nX = aPosSize.Left();
1597 if( mpParent )
1598 nX -= mpParent->maGeometry.nX;
1599 }
1600 if( ! ( nFlags & SAL_FRAME_POSSIZE_Y(sal_uInt16(0x0002)) ) )
1601 {
1602 nY = aPosSize.Top();
1603 if( mpParent )
1604 nY -= mpParent->maGeometry.nY;
1605 }
1606 if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH(sal_uInt16(0x0004)) ) )
1607 nWidth = aPosSize.GetWidth();
1608 if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT(sal_uInt16(0x0008)) ) )
1609 nHeight = aPosSize.GetHeight();
1610
1611 aPosSize = tools::Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1612
1613 if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X(sal_uInt16(0x0001)) | SAL_FRAME_POSSIZE_Y(sal_uInt16(0x0002)) ) ) )
1614 {
1615 if( bDefaultPosition_ )
1616 {
1617 maGeometry.nWidth = aPosSize.GetWidth();
1618 maGeometry.nHeight = aPosSize.GetHeight();
1619 Center();
1620 }
1621 else
1622 SetSize( Size( nWidth, nHeight ) );
1623 }
1624 else
1625 SetPosSize( aPosSize );
1626
1627 bDefaultPosition_ = False0;
1628}
1629
1630void X11SalFrame::SetAlwaysOnTop( bool bOnTop )
1631{
1632 if( ! IsOverrideRedirect() )
1633 {
1634 bAlwaysOnTop_ = bOnTop;
1635 pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop );
1636 }
1637}
1638
1639constexpr auto FRAMESTATE_MASK_GEOMETRY =
1640 WindowStateMask::X | WindowStateMask::Y |
1641 WindowStateMask::Width | WindowStateMask::Height;
1642constexpr auto FRAMESTATE_MASK_MAXIMIZED_GEOMETRY =
1643 WindowStateMask::MaximizedX | WindowStateMask::MaximizedY |
1644 WindowStateMask::MaximizedWidth | WindowStateMask::MaximizedHeight;
1645
1646void X11SalFrame::SetWindowState( const SalFrameState *pState )
1647{
1648 if (pState == nullptr)
1649 return;
1650
1651 // Request for position or size change
1652 if (pState->mnMask & FRAMESTATE_MASK_GEOMETRY)
1653 {
1654 /* #i44325#
1655 * if maximized, set restore size and guess maximized size from last time
1656 * in state change below maximize window
1657 */
1658 if( ! IsChildWindow() &&
1659 (pState->mnMask & WindowStateMask::State) &&
1660 (pState->mnState & WindowStateState::Maximized) &&
1661 (pState->mnMask & FRAMESTATE_MASK_GEOMETRY) == FRAMESTATE_MASK_GEOMETRY &&
1662 (pState->mnMask & FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == FRAMESTATE_MASK_MAXIMIZED_GEOMETRY
1663 )
1664 {
1665 XSizeHints* pHints = XAllocSizeHints();
1666 long nSupplied = 0;
1667 XGetWMNormalHints( GetXDisplay(),
1668 GetShellWindow(),
1669 pHints,
1670 &nSupplied );
1671 pHints->flags |= PPosition(1L << 2) | PWinGravity(1L << 9);
1672 pHints->x = pState->mnX;
1673 pHints->y = pState->mnY;
1674 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
1675 XSetWMNormalHints( GetXDisplay(),
1676 GetShellWindow(),
1677 pHints );
1678 XFree( pHints );
1679
1680 XMoveResizeWindow( GetXDisplay(), GetShellWindow(),
1681 pState->mnX, pState->mnY,
1682 pState->mnWidth, pState->mnHeight );
1683 // guess maximized geometry from last time
1684 maGeometry.nX = pState->mnMaximizedX;
1685 maGeometry.nY = pState->mnMaximizedY;
1686 maGeometry.nWidth = pState->mnMaximizedWidth;
1687 maGeometry.nHeight = pState->mnMaximizedHeight;
1688 updateScreenNumber();
1689 }
1690 else
1691 {
1692 bool bDoAdjust = false;
1693 tools::Rectangle aPosSize;
1694 // initialize with current geometry
1695 if ((pState->mnMask & FRAMESTATE_MASK_GEOMETRY) != FRAMESTATE_MASK_GEOMETRY)
1696 GetPosSize (aPosSize);
1697
1698 // change requested properties
1699 if (pState->mnMask & WindowStateMask::X)
1700 {
1701 aPosSize.setX (pState->mnX);
1702 }
1703 if (pState->mnMask & WindowStateMask::Y)
1704 {
1705 aPosSize.setY (pState->mnY);
1706 }
1707 if (pState->mnMask & WindowStateMask::Width)
1708 {
1709 long nWidth = pState->mnWidth > 0 ? pState->mnWidth - 1 : 0;
1710 aPosSize.setWidth (nWidth);
1711 bDoAdjust = true;
1712 }
1713 if (pState->mnMask & WindowStateMask::Height)
1714 {
1715 int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0;
1716 aPosSize.setHeight (nHeight);
1717 bDoAdjust = true;
1718 }
1719
1720 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nXScreen ).m_aSize;
1721
1722 if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width()
1723 && aPosSize.GetHeight() <= aScreenSize.Height() )
1724 {
1725 SalFrameGeometry aGeom = maGeometry;
1726
1727 if( ! (nStyle_ & ( SalFrameStyleFlags::FLOAT | SalFrameStyleFlags::PLUG ) ) &&
1728 mpParent &&
1729 aGeom.nLeftDecoration == 0 &&
1730 aGeom.nTopDecoration == 0 )
1731 {
1732 aGeom = mpParent->maGeometry;
1733 if( aGeom.nLeftDecoration == 0 &&
1734 aGeom.nTopDecoration == 0 )
1735 {
1736 aGeom.nLeftDecoration = 5;
1737 aGeom.nTopDecoration = 20;
1738 aGeom.nRightDecoration = 5;
1739 aGeom.nBottomDecoration = 5;
1740 }
1741 }
1742
1743 // adjust position so that frame fits onto screen
1744 if( aPosSize.Right()+static_cast<long>(aGeom.nRightDecoration) > aScreenSize.Width()-1 )
1745 aPosSize.Move( aScreenSize.Width() - aPosSize.Right() - static_cast<long>(aGeom.nRightDecoration), 0 );
1746 if( aPosSize.Bottom()+static_cast<long>(aGeom.nBottomDecoration) > aScreenSize.Height()-1 )
1747 aPosSize.Move( 0, aScreenSize.Height() - aPosSize.Bottom() - static_cast<long>(aGeom.nBottomDecoration) );
1748 if( aPosSize.Left() < static_cast<long>(aGeom.nLeftDecoration) )
1749 aPosSize.Move( static_cast<long>(aGeom.nLeftDecoration) - aPosSize.Left(), 0 );
1750 if( aPosSize.Top() < static_cast<long>(aGeom.nTopDecoration) )
1751 aPosSize.Move( 0, static_cast<long>(aGeom.nTopDecoration) - aPosSize.Top() );
1752 }
1753
1754 SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH(sal_uInt16(0x0004)) | SAL_FRAME_POSSIZE_HEIGHT(sal_uInt16(0x0008)) );
1755 }
1756 }
1757
1758 // request for status change
1759 if (!(pState->mnMask & WindowStateMask::State))
1760 return;
1761
1762 if (pState->mnState & WindowStateState::Maximized)
1763 {
1764 nShowState_ = SHOWSTATE_NORMAL1;
1765 if( ! (pState->mnState & (WindowStateState::MaximizedHorz|WindowStateState::MaximizedVert) ) )
1766 Maximize();
1767 else
1768 {
1769 bool bHorz(pState->mnState & WindowStateState::MaximizedHorz);
1770 bool bVert(pState->mnState & WindowStateState::MaximizedVert);
1771 GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert );
1772 }
1773 maRestorePosSize.SetLeft( pState->mnX );
1774 maRestorePosSize.SetTop( pState->mnY );
1775 maRestorePosSize.SetRight( maRestorePosSize.Left() + pState->mnWidth );
1776 maRestorePosSize.SetRight( maRestorePosSize.Left() + pState->mnHeight );
1777 }
1778 else if( mbMaximizedHorz || mbMaximizedVert )
1779 GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false );
1780
1781 if (pState->mnState & WindowStateState::Minimized)
1782 {
1783 if (nShowState_ == SHOWSTATE_UNKNOWN-1)
1784 nShowState_ = SHOWSTATE_NORMAL1;
1785 Minimize();
1786 }
1787 if (pState->mnState & WindowStateState::Normal)
1788 {
1789 if (nShowState_ != SHOWSTATE_NORMAL1)
1790 Restore();
1791 }
1792 if (pState->mnState & WindowStateState::Rollup)
1793 GetDisplay()->getWMAdaptor()->shade( this, true );
1794}
1795
1796bool X11SalFrame::GetWindowState( SalFrameState* pState )
1797{
1798 if( SHOWSTATE_MINIMIZED0 == nShowState_ )
1799 pState->mnState = WindowStateState::Minimized;
1800 else
1801 pState->mnState = WindowStateState::Normal;
1802
1803 tools::Rectangle aPosSize;
1804 if( maRestorePosSize.IsEmpty() )
1805 GetPosSize( aPosSize );
1806 else
1807 aPosSize = maRestorePosSize;
1808
1809 if( mbMaximizedHorz )
1810 pState->mnState |= WindowStateState::MaximizedHorz;
1811 if( mbMaximizedVert )
1812 pState->mnState |= WindowStateState::MaximizedVert;
1813 if( mbShaded )
1814 pState->mnState |= WindowStateState::Rollup;
1815
1816 pState->mnX = aPosSize.Left();
1817 pState->mnY = aPosSize.Top();
1818 pState->mnWidth = aPosSize.GetWidth();
1819 pState->mnHeight = aPosSize.GetHeight();
1820
1821 pState->mnMask = FRAMESTATE_MASK_GEOMETRY | WindowStateMask::State;
1822
1823 if (! maRestorePosSize.IsEmpty() )
1824 {
1825 GetPosSize( aPosSize );
1826 pState->mnState |= WindowStateState::Maximized;
1827 pState->mnMaximizedX = aPosSize.Left();
1828 pState->mnMaximizedY = aPosSize.Top();
1829 pState->mnMaximizedWidth = aPosSize.GetWidth();
1830 pState->mnMaximizedHeight = aPosSize.GetHeight();
1831 pState->mnMask |= FRAMESTATE_MASK_MAXIMIZED_GEOMETRY;
1832 }
1833
1834 return true;
1835}
1836
1837// native menu implementation - currently empty
1838void X11SalFrame::DrawMenuBar()
1839{
1840}
1841
1842void X11SalFrame::SetMenu( SalMenu* )
1843{
1844}
1845
1846void X11SalFrame::GetPosSize( tools::Rectangle &rPosSize )
1847{
1848 if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 )
1849 {
1850 const Size& aScreenSize = pDisplay_->getDataForScreen( m_nXScreen ).m_aSize;
1851 long w = aScreenSize.Width() - maGeometry.nLeftDecoration - maGeometry.nRightDecoration;
1852 long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration;
1853
1854 rPosSize = tools::Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) );
1855 }
1856 else
1857 rPosSize = tools::Rectangle( Point( maGeometry.nX, maGeometry.nY ),
1858 Size( maGeometry.nWidth, maGeometry.nHeight ) );
1859}
1860
1861void X11SalFrame::SetSize( const Size &rSize )
1862{
1863 if( rSize.IsEmpty() )
1864 return;
1865
1866 if( ! ( nStyle_ & SalFrameStyleFlags::SIZEABLE )
1867 && ! IsChildWindow()
1868 && ( nStyle_ & (SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::OWNERDRAWDECORATION) ) != SalFrameStyleFlags::FLOAT )
1869 {
1870 XSizeHints* pHints = XAllocSizeHints();
1871 long nSupplied = 0;
1872 XGetWMNormalHints( GetXDisplay(),
1873 GetShellWindow(),
1874 pHints,
1875 &nSupplied
1876 );
1877 pHints->min_width = rSize.Width();
1878 pHints->min_height = rSize.Height();
1879 pHints->max_width = rSize.Width();
1880 pHints->max_height = rSize.Height();
1881 pHints->flags |= PMinSize(1L << 4) | PMaxSize(1L << 5);
1882 XSetWMNormalHints( GetXDisplay(),
1883 GetShellWindow(),
1884 pHints );
1885 XFree( pHints );
1886 }
1887 XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() );
1888 if( GetWindow() != GetShellWindow() )
1889 {
1890 if( nStyle_ & SalFrameStyleFlags::PLUG )
1891 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() );
1892 else
1893 XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() );
1894 }
1895
1896 maGeometry.nWidth = rSize.Width();
1897 maGeometry.nHeight = rSize.Height();
1898
1899 // allow the external status window to reposition
1900 if (mbInputFocus && mpInputContext != nullptr)
1901 mpInputContext->SetICFocus ( this );
1902}
1903
1904void X11SalFrame::SetPosSize( const tools::Rectangle &rPosSize )
1905{
1906 XWindowChanges values;
1907 values.x = rPosSize.Left();
1908 values.y = rPosSize.Top();
1909 values.width = rPosSize.GetWidth();
1910 values.height = rPosSize.GetHeight();
1911
1912 if( !values.width || !values.height )
1913 return;
1914
1915 if( mpParent && ! IsSysChildWindow() )
1916 {
1917 if( AllSettings::GetLayoutRTL() )
1918 values.x = mpParent->maGeometry.nWidth-values.width-1-values.x;
1919
1920 ::Window aChild;
1921 // coordinates are relative to parent, so translate to root coordinates
1922 XTranslateCoordinates( GetDisplay()->GetDisplay(),
1923 mpParent->GetWindow(),
1924 GetDisplay()->GetRootWindow( m_nXScreen ),
1925 values.x, values.y,
1926 &values.x, &values.y,
1927 & aChild );
1928 }
1929
1930 bool bMoved = false;
1931 bool bSized = false;
1932 if( values.x != maGeometry.nX || values.y != maGeometry.nY )
1933 bMoved = true;
1934 if( values.width != static_cast<int>(maGeometry.nWidth) || values.height != static_cast<int>(maGeometry.nHeight) )
1935 bSized = true;
1936
1937 // do not set WMNormalHints for...
1938 if(
1939 // child windows
1940 ! IsChildWindow()
1941 // popups (menu, help window, etc.)
1942 && (nStyle_ & (SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::OWNERDRAWDECORATION) ) != SalFrameStyleFlags::FLOAT
1943 // shown, sizeable windows
1944 && ( nShowState_ == SHOWSTATE_UNKNOWN-1 ||
1945 nShowState_ == SHOWSTATE_HIDDEN2 ||
1946 ! ( nStyle_ & SalFrameStyleFlags::SIZEABLE )
1947 )
1948 )
1949 {
1950 XSizeHints* pHints = XAllocSizeHints();
1951 long nSupplied = 0;
1952 XGetWMNormalHints( GetXDisplay(),
1953 GetShellWindow(),
1954 pHints,
1955 &nSupplied
1956 );
1957 if( ! ( nStyle_ & SalFrameStyleFlags::SIZEABLE ) )
1958 {
1959 pHints->min_width = rPosSize.GetWidth();
1960 pHints->min_height = rPosSize.GetHeight();
1961 pHints->max_width = rPosSize.GetWidth();
1962 pHints->max_height = rPosSize.GetHeight();
1963 pHints->flags |= PMinSize(1L << 4) | PMaxSize(1L << 5);
1964 }
1965 if( nShowState_ == SHOWSTATE_UNKNOWN-1 || nShowState_ == SHOWSTATE_HIDDEN2 )
1966 {
1967 pHints->flags |= PPosition(1L << 2) | PWinGravity(1L << 9);
1968 pHints->x = values.x;
1969 pHints->y = values.y;
1970 pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity();
1971 }
1972 if( mbFullScreen )
1973 {
1974 pHints->max_width = 10000;
1975 pHints->max_height = 10000;
1976 pHints->flags |= PMaxSize(1L << 5);
1977 }
1978 XSetWMNormalHints( GetXDisplay(),
1979 GetShellWindow(),
1980 pHints );
1981 XFree( pHints );
1982 }
1983
1984 XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height );
1985 if( GetShellWindow() != GetWindow() )
1986 {
1987 if( nStyle_ & SalFrameStyleFlags::PLUG )
1988 XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height );
1989 else
1990 XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height );
1991 }
1992
1993 maGeometry.nX = values.x;
1994 maGeometry.nY = values.y;
1995 maGeometry.nWidth = values.width;
1996 maGeometry.nHeight = values.height;
1997 if( IsSysChildWindow() && mpParent )
1998 {
1999 // translate back to root coordinates
2000 maGeometry.nX += mpParent->maGeometry.nX;
2001 maGeometry.nY += mpParent->maGeometry.nY;
2002 }
2003
2004 updateScreenNumber();
2005 if( bSized && ! bMoved )
2006 CallCallback( SalEvent::Resize, nullptr );
2007 else if( bMoved && ! bSized )
2008 CallCallback( SalEvent::Move, nullptr );
2009 else
2010 CallCallback( SalEvent::MoveResize, nullptr );
2011
2012 // allow the external status window to reposition
2013 if (mbInputFocus && mpInputContext != nullptr)
2014 mpInputContext->SetICFocus ( this );
2015}
2016
2017void X11SalFrame::Minimize()
2018{
2019 if( IsSysChildWindow() )
2020 return;
2021
2022 if( SHOWSTATE_UNKNOWN-1 == nShowState_ || SHOWSTATE_HIDDEN2 == nShowState_ )
2023 {
2024 SAL_WARN( "vcl", "X11SalFrame::Minimize on withdrawn window" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Minimize on withdrawn window") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Minimize on withdrawn window"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Minimize on withdrawn window"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2024" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Minimize on withdrawn window") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Minimize on withdrawn window"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Minimize on withdrawn window"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2024" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2025 return;
2026 }
2027
2028 if( XIconifyWindow( GetXDisplay(),
2029 GetShellWindow(),
2030 pDisplay_->GetDefaultXScreen().getXScreen() ) )
2031 nShowState_ = SHOWSTATE_MINIMIZED0;
2032}
2033
2034void X11SalFrame::Maximize()
2035{
2036 if( IsSysChildWindow() )
2037 return;
2038
2039 if( SHOWSTATE_MINIMIZED0 == nShowState_ )
2040 {
2041 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2042 XMapWindow( GetXDisplay(), GetShellWindow() );
2043 nShowState_ = SHOWSTATE_NORMAL1;
2044 }
2045
2046 pDisplay_->getWMAdaptor()->maximizeFrame( this );
2047}
2048
2049void X11SalFrame::Restore()
2050{
2051 if( IsSysChildWindow() )
2052 return;
2053
2054 if( SHOWSTATE_UNKNOWN-1 == nShowState_ || SHOWSTATE_HIDDEN2 == nShowState_ )
2055 {
2056 SAL_WARN( "vcl", "X11SalFrame::Restore on withdrawn window" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Restore on withdrawn window") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), (
"/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2056" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Restore on withdrawn window"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Restore on withdrawn window"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2056" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Restore on withdrawn window") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), (
"/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2056" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Restore on withdrawn window"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Restore on withdrawn window"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2056" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2057 return;
2058 }
2059
2060 if( SHOWSTATE_MINIMIZED0 == nShowState_ )
2061 {
2062 GetDisplay()->getWMAdaptor()->frameIsMapping( this );
2063 XMapWindow( GetXDisplay(), GetShellWindow() );
2064 nShowState_ = SHOWSTATE_NORMAL1;
2065 }
2066
2067 pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false );
2068}
2069
2070void X11SalFrame::SetScreenNumber( unsigned int nNewScreen )
2071{
2072 if( nNewScreen == maGeometry.nDisplayScreenNumber )
2073 return;
2074
2075 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2076 {
2077 if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() )
2078 return;
2079
2080 tools::Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nDisplayScreenNumber] );
2081 tools::Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] );
2082 bool bVisible = bMapped_;
2083 if( bVisible )
2084 Show( false );
2085 maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left());
2086 maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top());
2087 createNewWindow( None0L, m_nXScreen );
2088 if( bVisible )
2089 Show( true );
2090 maGeometry.nDisplayScreenNumber = nNewScreen;
2091 }
2092 else if( nNewScreen < GetDisplay()->GetXScreenCount() )
2093 {
2094 bool bVisible = bMapped_;
2095 if( bVisible )
2096 Show( false );
2097 createNewWindow( None0L, SalX11Screen( nNewScreen ) );
2098 if( bVisible )
2099 Show( true );
2100 maGeometry.nDisplayScreenNumber = nNewScreen;
2101 }
2102}
2103
2104void X11SalFrame::SetApplicationID( const OUString &rWMClass )
2105{
2106 if( rWMClass != m_sWMClass && ! IsChildWindow() )
2107 {
2108 m_sWMClass = rWMClass;
2109 updateWMClass();
2110 for (auto const& child : maChildren)
2111 child->SetApplicationID(rWMClass);
2112 }
2113}
2114
2115void X11SalFrame::updateWMClass()
2116{
2117 XClassHint* pClass = XAllocClassHint();
2118 OString aResName = SalGenericSystem::getFrameResName();
2119 pClass->res_name = const_cast<char*>(aResName.getStr());
2120
2121 OString aResClass = OUStringToOString(m_sWMClass, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
2122 const char *pResClass = !aResClass.isEmpty() ? aResClass.getStr() :
2123 SalGenericSystem::getFrameClassName();
2124
2125 pClass->res_class = const_cast<char*>(pResClass);
2126 XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
2127 XFree( pClass );
2128}
2129
2130void X11SalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nScreen )
2131{
2132 if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
2133 {
2134 if( mbFullScreen == bFullScreen )
2135 return;
2136 if( bFullScreen )
2137 {
2138 maRestorePosSize = tools::Rectangle( Point( maGeometry.nX, maGeometry.nY ),
2139 Size( maGeometry.nWidth, maGeometry.nHeight ) );
2140 tools::Rectangle aRect;
2141 if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) )
2142 aRect = tools::Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nXScreen ) );
2143 else
2144 aRect = GetDisplay()->GetXineramaScreens()[nScreen];
2145 nStyle_ |= SalFrameStyleFlags::PARTIAL_FULLSCREEN;
2146 bool bVisible = bMapped_;
2147 if( bVisible )
2148 Show( false );
2149 maGeometry.nX = aRect.Left();
2150 maGeometry.nY = aRect.Top();
2151 maGeometry.nWidth = aRect.GetWidth();
2152 maGeometry.nHeight = aRect.GetHeight();
2153 mbMaximizedHorz = mbMaximizedVert = false;
2154 mbFullScreen = true;
2155 createNewWindow( None0L, m_nXScreen );
2156 if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
2157 GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true );
2158 else
2159 GetDisplay()->getWMAdaptor()->showFullScreen( this, true );
2160 if( bVisible )
2161 Show(true);
2162
2163 }
2164 else
2165 {
2166 mbFullScreen = false;
2167 nStyle_ &= ~SalFrameStyleFlags::PARTIAL_FULLSCREEN;
2168 bool bVisible = bMapped_;
2169 tools::Rectangle aRect = maRestorePosSize;
2170 maRestorePosSize = tools::Rectangle();
2171 if( bVisible )
2172 Show( false );
2173 createNewWindow( None0L, m_nXScreen );
2174 if( !aRect.IsEmpty() )
2175 SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
2176 SAL_FRAME_POSSIZE_X(sal_uInt16(0x0001)) | SAL_FRAME_POSSIZE_Y(sal_uInt16(0x0002)) |
2177 SAL_FRAME_POSSIZE_WIDTH(sal_uInt16(0x0004)) | SAL_FRAME_POSSIZE_HEIGHT(sal_uInt16(0x0008)) );
2178 if( bVisible )
2179 Show( true );
2180 }
2181 }
2182 else
2183 {
2184 if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXScreenCount()) )
2185 nScreen = m_nXScreen.getXScreen();
2186 if( nScreen != static_cast<int>(m_nXScreen.getXScreen()) )
2187 {
2188 bool bVisible = bMapped_;
2189 if( mbFullScreen )
2190 pDisplay_->getWMAdaptor()->showFullScreen( this, false );
2191 if( bVisible )
2192 Show( false );
2193 createNewWindow( None0L, SalX11Screen( nScreen ) );
2194 if( mbFullScreen )
2195 pDisplay_->getWMAdaptor()->showFullScreen( this, true );
2196 if( bVisible )
2197 Show( true );
2198 }
2199 if( mbFullScreen == bFullScreen )
2200 return;
2201
2202 pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen );
2203 }
2204}
2205
2206void X11SalFrame::StartPresentation( bool bStart )
2207{
2208 maScreenSaverInhibitor.inhibit( bStart,
2209 "presentation",
2210 true, // isX11
2211 mhWindow,
2212 GetXDisplay() );
2213
2214 if( ! bStart && hPresentationWindow != None0L )
2215 doReparentPresentationDialogues( GetDisplay() );
2216 hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None0L;
2217
2218 if( bStart && hPresentationWindow )
2219 {
2220 /* #i10559# workaround for WindowMaker: try to restore
2221 * current focus after presentation window is gone
2222 */
2223 int revert_to = 0;
2224 XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to );
2225 }
2226}
2227
2228// Pointer
2229
2230void X11SalFrame::SetPointer( PointerStyle ePointerStyle )
2231{
2232 hCursor_ = pDisplay_->GetPointer( ePointerStyle );
2233 XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ );
2234
2235 if( IsCaptured() || nVisibleFloats > 0 )
2236 XChangeActivePointerGrab( GetXDisplay(),
2237 PointerMotionMask(1L<<6)|ButtonPressMask(1L<<2)|ButtonReleaseMask(1L<<3),
2238 hCursor_,
2239 CurrentTime0L );
2240}
2241
2242void X11SalFrame::SetPointerPos(long nX, long nY)
2243{
2244 /* when the application tries to center the mouse in the dialog the
2245 * window isn't mapped already. So use coordinates relative to the root window.
2246 */
2247 unsigned int nWindowLeft = maGeometry.nX + nX;
2248 unsigned int nWindowTop = maGeometry.nY + nY;
2249
2250 XWarpPointer( GetXDisplay(), None0L, pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() ),
2251 0, 0, 0, 0, nWindowLeft, nWindowTop);
2252}
2253
2254// delay handling of extended text input
2255#if !defined(__synchronous_extinput__)
2256void
2257X11SalFrame::HandleExtTextEvent (XClientMessageEvent const *pEvent)
2258{
2259 #if SAL_TYPES_SIZEOFLONG8 > 4
2260 void* pExtTextEvent = reinterpret_cast<void*>( (pEvent->data.l[0] & 0xffffffff)
2261 | (pEvent->data.l[1] << 32) );
2262 #else
2263 void* pExtTextEvent = reinterpret_cast<void*>(pEvent->data.l[0]);
2264 #endif
2265 SalEvent nExtTextEventType = SalEvent(pEvent->data.l[2]);
2266
2267 CallCallback(nExtTextEventType, pExtTextEvent);
2268
2269 switch (nExtTextEventType)
2270 {
2271 case SalEvent::EndExtTextInput:
2272 break;
2273
2274 case SalEvent::ExtTextInput:
2275 break;
2276
2277 default:
2278 SAL_WARN("vcl.window",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::HandleExtTextEvent: invalid extended input."
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::HandleExtTextEvent: invalid extended input."
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
2279 "X11SalFrame::HandleExtTextEvent: invalid extended input.")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::HandleExtTextEvent: invalid extended input."
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::HandleExtTextEvent: invalid extended input."
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::HandleExtTextEvent: invalid extended input."
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "2279" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2280 }
2281}
2282#endif /* defined(__synchronous_extinput__) */
2283
2284// PostEvent
2285
2286bool X11SalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
2287{
2288 GetDisplay()->SendInternalEvent( this, pData.release() );
2289 return true;
2290}
2291
2292// Title
2293
2294void X11SalFrame::SetTitle( const OUString& rTitle )
2295{
2296 if( ! ( IsChildWindow() || (nStyle_ & SalFrameStyleFlags::FLOAT ) ) )
2297 {
2298 m_aTitle = rTitle;
2299 GetDisplay()->getWMAdaptor()->setWMName( this, rTitle );
2300 }
2301}
2302
2303void X11SalFrame::Flush()
2304{
2305 if( pGraphics_ )
2306 pGraphics_->Flush();
2307 XFlush( GetDisplay()->GetDisplay() );
2308}
2309
2310// Keyboard
2311
2312void X11SalFrame::SetInputContext( SalInputContext* pContext )
2313{
2314 if (pContext == nullptr)
2315 return;
2316
2317 // 1. We should create an input context for this frame
2318 // only when InputContextFlags::Text is set.
2319
2320 if (!(pContext->mnOptions & InputContextFlags::Text))
2321 {
2322 if( mpInputContext )
2323 mpInputContext->Unmap();
2324 return;
2325 }
2326
2327 // 2. We should use on-the-spot inputstyle
2328 // only when InputContextFlags::ExtTExt is set.
2329
2330 if (mpInputContext == nullptr)
2331 {
2332 mpInputContext.reset( new SalI18N_InputContext( this ) );
2333 if (mpInputContext->UseContext())
2334 {
2335 mpInputContext->ExtendEventMask( GetShellWindow() );
2336 if (mbInputFocus)
2337 mpInputContext->SetICFocus( this );
2338 }
2339 }
2340 else
2341 mpInputContext->Map( this );
2342}
2343
2344void X11SalFrame::EndExtTextInput( EndExtTextInputFlags )
2345{
2346 if (mpInputContext != nullptr)
2347 mpInputContext->EndExtTextInput();
2348}
2349
2350OUString X11SalFrame::GetKeyName( sal_uInt16 nKeyCode )
2351{
2352 return GetDisplay()->GetKeyName( nKeyCode );
2353}
2354
2355bool X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
2356{
2357 // not supported yet
2358 return false;
2359}
2360
2361LanguageType X11SalFrame::GetInputLanguage()
2362{
2363 // could be improved by checking unicode ranges of the last input
2364 return LANGUAGE_DONTKNOWLanguageType(0x03FF);
2365}
2366
2367// Settings
2368
2369void X11SalFrame::UpdateSettings( AllSettings& rSettings )
2370{
2371 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2372 aStyleSettings.SetCursorBlinkTime( 500 );
2373 aStyleSettings.SetMenuBarTextColor( aStyleSettings.GetPersonaMenuBarTextColor().value_or( COL_BLACK ) );
2374 rSettings.SetStyleSettings( aStyleSettings );
2375}
2376
2377void X11SalFrame::CaptureMouse( bool bCapture )
2378{
2379 nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : nullptr );
2380}
2381
2382void X11SalFrame::SetParent( SalFrame* pNewParent )
2383{
2384 if( mpParent != pNewParent
19.1
'pNewParent' is not equal to field 'mpParent'
)
20
Taking true branch
2385 {
2386 if( mpParent
20.1
Field 'mpParent' is non-null
)
21
Taking true branch
2387 mpParent->maChildren.remove( this );
2388
2389 mpParent = static_cast<X11SalFrame*>(pNewParent);
22
Null pointer value stored to field 'mpParent'
2390 mpParent->maChildren.push_back( this );
23
Called C++ object pointer is null
2391 if( mpParent->m_nXScreen != m_nXScreen )
2392 createNewWindow( None0L, mpParent->m_nXScreen );
2393 GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2394 }
2395}
2396
2397SalFrame* X11SalFrame::GetParent() const
2398{
2399 return mpParent;
2400}
2401
2402void X11SalFrame::createNewWindow( ::Window aNewParent, SalX11Screen nXScreen )
2403{
2404 bool bWasVisible = bMapped_;
2405 if( bWasVisible )
4
Assuming 'bWasVisible' is false
5
Taking false branch
2406 Show( false );
2407
2408 if( nXScreen.getXScreen() >= GetDisplay()->GetXScreenCount() )
6
Assuming the condition is false
7
Taking false branch
2409 nXScreen = m_nXScreen;
2410
2411 SystemParentData aParentData;
2412 aParentData.nSize = sizeof(SystemParentData);
2413 aParentData.aWindow = aNewParent;
2414 aParentData.bXEmbedSupport = (aNewParent != None0L && m_bXEmbed); // caution: this is guesswork
8
Assuming 'aNewParent' is equal to None
2415 if( aNewParent
8.1
'aNewParent' is equal to None
== None0L )
9
Taking true branch
2416 {
2417 aParentData.aWindow = None0L;
2418 m_bXEmbed = false;
2419 }
2420 else
2421 {
2422 // is new parent a root window ?
2423 Display* pDisp = GetDisplay()->GetDisplay();
2424 int nScreens = GetDisplay()->GetXScreenCount();
2425 for( int i = 0; i < nScreens; i++ )
2426 {
2427 if( aNewParent == RootWindow( pDisp, i )((&((_XPrivDisplay)(pDisp))->screens[i])->root) )
2428 {
2429 nXScreen = SalX11Screen( i );
2430 aParentData.aWindow = None0L;
2431 m_bXEmbed = false;
2432 break;
2433 }
2434 }
2435 }
2436
2437 // first deinit frame
2438 updateGraphics(true);
2439 if( mpInputContext )
10
Taking false branch
2440 {
2441 mpInputContext->UnsetICFocus();
2442 mpInputContext->Unmap();
2443 }
2444 if( GetWindow() == hPresentationWindow )
11
Assuming the condition is false
12
Taking false branch
2445 {
2446 hPresentationWindow = None0L;
2447 doReparentPresentationDialogues( GetDisplay() );
2448 }
2449 XDestroyWindow( GetXDisplay(), mhWindow );
2450 mhWindow = None0L;
2451
2452 // now init with new parent again
2453 if ( aParentData.aWindow
12.1
Field 'aWindow' is equal to None
!= None0L )
13
Taking false branch
2454 Init( nStyle_ | SalFrameStyleFlags::PLUG, nXScreen, &aParentData );
2455 else
2456 Init( nStyle_ & ~SalFrameStyleFlags::PLUG, nXScreen, nullptr, true );
2457
2458 // update graphics if necessary
2459 updateGraphics(false);
2460
2461 if( ! m_aTitle.isEmpty() )
14
Taking false branch
2462 SetTitle( m_aTitle );
2463
2464 if( mpParent )
15
Assuming field 'mpParent' is non-null
16
Taking true branch
2465 {
2466 if( mpParent->m_nXScreen != m_nXScreen )
17
Taking true branch
2467 SetParent( nullptr );
18
Passing null pointer value via 1st parameter 'pNewParent'
19
Calling 'X11SalFrame::SetParent'
2468 else
2469 pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent );
2470 }
2471
2472 if( bWasVisible )
2473 Show( true );
2474
2475 std::list< X11SalFrame* > aChildren = maChildren;
2476 for (auto const& child : aChildren)
2477 child->createNewWindow( None0L, m_nXScreen );
2478
2479 // FIXME: SalObjects
2480}
2481
2482bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent )
2483{
2484 if( pNewParent->nSize >= sizeof(SystemParentData) )
1
Assuming the condition is false
2
Taking false branch
2485 m_bXEmbed = pNewParent->aWindow != None0L && pNewParent->bXEmbedSupport;
2486
2487 createNewWindow(pNewParent->aWindow);
3
Calling 'X11SalFrame::createNewWindow'
2488
2489 return true;
2490}
2491
2492// Sound
2493void X11SalFrame::Beep()
2494{
2495 GetDisplay()->Beep();
2496}
2497
2498// Event Handling
2499
2500static sal_uInt16 sal_GetCode( int state )
2501{
2502 sal_uInt16 nCode = 0;
2503
2504 if( state & Button1Mask(1<<8) )
2505 nCode |= MOUSE_LEFT(sal_uInt16(0x0001));
2506 if( state & Button2Mask(1<<9) )
2507 nCode |= MOUSE_MIDDLE(sal_uInt16(0x0002));
2508 if( state & Button3Mask(1<<10) )
2509 nCode |= MOUSE_RIGHT(sal_uInt16(0x0004));
2510
2511 if( state & ShiftMask(1<<0) )
2512 nCode |= KEY_SHIFT;
2513 if( state & ControlMask(1<<2) )
2514 nCode |= KEY_MOD1;
2515 if( state & Mod1Mask(1<<3) )
2516 nCode |= KEY_MOD2;
2517
2518 // Map Meta/Super modifier to MOD3 on all Unix systems
2519 // except macOS
2520 if( state & Mod3Mask(1<<5) )
2521 nCode |= KEY_MOD3;
2522
2523 return nCode;
2524}
2525
2526SalFrame::SalPointerState X11SalFrame::GetPointerState()
2527{
2528 SalPointerState aState;
2529 ::Window aRoot, aChild;
2530 int rx, ry, wx, wy;
2531 unsigned int nMask = 0;
2532 XQueryPointer( GetXDisplay(),
2533 GetShellWindow(),
2534 &aRoot,
2535 &aChild,
2536 &rx, &ry,
2537 &wx, &wy,
2538 &nMask
2539 );
2540
2541 aState.maPos = Point(wx, wy);
2542 aState.mnState = sal_GetCode( nMask );
2543 return aState;
2544}
2545
2546KeyIndicatorState X11SalFrame::GetIndicatorState()
2547{
2548 return vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetIndicatorState();
2549}
2550
2551void X11SalFrame::SimulateKeyPress( sal_uInt16 nKeyCode )
2552{
2553 vcl_sal::getSalDisplay(GetGenericUnixSalData())->SimulateKeyPress(nKeyCode);
2554}
2555
2556namespace
2557{
2558struct CompressWheelEventsData
2559{
2560 XEvent* firstEvent;
2561 bool ignore;
2562 int count; // number of compressed events
2563};
2564
2565Boolint compressWheelEvents( Display*, XEvent* event, XPointer p )
2566{
2567 CompressWheelEventsData* data = reinterpret_cast< CompressWheelEventsData* >( p );
2568 if( data->ignore )
2569 return False0; // we're already after the events to compress
2570 if( event->type == ButtonPress4 || event->type == ButtonRelease5 )
2571 {
2572 const unsigned int mask = Button1Mask(1<<8) << ( event->xbutton.button - Button11 );
2573 if( event->xbutton.button == data->firstEvent->xbutton.button
2574 && event->xbutton.window == data->firstEvent->xbutton.window
2575 && event->xbutton.x == data->firstEvent->xbutton.x
2576 && event->xbutton.y == data->firstEvent->xbutton.y
2577 && ( event->xbutton.state | mask ) == ( data->firstEvent->xbutton.state | mask ))
2578 {
2579 // Count if it's another press (i.e. wheel start event).
2580 if( event->type == ButtonPress4 )
2581 ++data->count;
2582 return True1; // And remove the event from the queue.
2583 }
2584 }
2585 // Non-matching event, skip certain events that cannot possibly affect input processing,
2586 // but otherwise ignore all further events.
2587 switch( event->type )
2588 {
2589 case Expose12:
2590 case NoExpose14:
2591 break;
2592 default:
2593 data->ignore = true;
2594 break;
2595 }
2596 return False0;
2597}
2598
2599} // namespace
2600
2601bool X11SalFrame::HandleMouseEvent( XEvent *pEvent )
2602{
2603 SalMouseEvent aMouseEvt;
2604 SalEvent nEvent = SalEvent::NONE;
2605 bool bClosePopups = false;
2606
2607 if( nVisibleFloats && pEvent->type == EnterNotify7 )
2608 return false;
2609
2610 if( LeaveNotify8 == pEvent->type || EnterNotify7 == pEvent->type )
2611 {
2612 /*
2613 * some WMs (and/or) applications have a passive grab on
2614 * mouse buttons (XGrabButton). This leads to enter/leave notifies
2615 * with mouse buttons pressed in the state mask before the actual
2616 * ButtonPress event gets dispatched. But EnterNotify
2617 * is reported in vcl as MouseMove event. Some office code
2618 * decides that a pressed button in a MouseMove belongs to
2619 * a drag operation which leads to doing things differently.
2620 *
2621 * ignore Enter/LeaveNotify resulting from grabs so that
2622 * help windows do not disappear just after appearing
2623 *
2624 * hopefully this workaround will not break anything.
2625 */
2626 if( pEvent->xcrossing.mode == NotifyGrab1 || pEvent->xcrossing.mode == NotifyUngrab2 )
2627 return false;
2628
2629 aMouseEvt.mnX = pEvent->xcrossing.x;
2630 aMouseEvt.mnY = pEvent->xcrossing.y;
2631 aMouseEvt.mnTime = pEvent->xcrossing.time;
2632 aMouseEvt.mnCode = sal_GetCode( pEvent->xcrossing.state );
2633 aMouseEvt.mnButton = 0;
2634
2635 nEvent = LeaveNotify8 == pEvent->type
2636 ? SalEvent::MouseLeave
2637 : SalEvent::MouseMove;
2638 }
2639 else if( pEvent->type == MotionNotify6 )
2640 {
2641 aMouseEvt.mnX = pEvent->xmotion.x;
2642 aMouseEvt.mnY = pEvent->xmotion.y;
2643 aMouseEvt.mnTime = pEvent->xmotion.time;
2644 aMouseEvt.mnCode = sal_GetCode( pEvent->xmotion.state );
2645
2646 aMouseEvt.mnButton = 0;
2647
2648 nEvent = SalEvent::MouseMove;
2649 if( nVisibleFloats > 0 && mpParent )
2650 {
2651 Cursor aCursor = mpParent->GetCursor();
2652 if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < static_cast<int>(maGeometry.nWidth) &&
2653 pEvent->xmotion.y >= 0 && pEvent->xmotion.y < static_cast<int>(maGeometry.nHeight) )
2654 aCursor = None0L;
2655
2656 XChangeActivePointerGrab( GetXDisplay(),
2657 PointerMotionMask(1L<<6)|ButtonPressMask(1L<<2)|ButtonReleaseMask(1L<<3),
2658 aCursor,
2659 CurrentTime0L );
2660 }
2661 }
2662 else
2663 {
2664 // let mouse events reach the correct window
2665 if( nVisibleFloats < 1 )
2666 {
2667 if( ! (nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION) )
2668 XUngrabPointer( GetXDisplay(), CurrentTime0L );
2669 }
2670 else if( pEvent->type == ButtonPress4 )
2671 {
2672 // see if the user clicks outside all of the floats
2673 // if yes release the grab
2674 bool bInside = false;
2675 for (auto pSalFrame : GetDisplay()->getFrames() )
2676 {
2677 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( pSalFrame );
2678 if( pFrame->IsFloatGrabWindow() &&
2679 pFrame->bMapped_ &&
2680 pEvent->xbutton.x_root >= pFrame->maGeometry.nX &&
2681 pEvent->xbutton.x_root < pFrame->maGeometry.nX + static_cast<int>(pFrame->maGeometry.nWidth) &&
2682 pEvent->xbutton.y_root >= pFrame->maGeometry.nY &&
2683 pEvent->xbutton.y_root < pFrame->maGeometry.nY + static_cast<int>(pFrame->maGeometry.nHeight) )
2684 {
2685 bInside = true;
2686 break;
2687 }
2688 }
2689 if( ! bInside )
2690 {
2691 // need not take care of the XUngrabPointer in Show( false )
2692 // because XUngrabPointer does not produce errors if pointer
2693 // is not grabbed
2694 XUngrabPointer( GetXDisplay(), CurrentTime0L );
2695 bClosePopups = true;
2696
2697 /* #i15246# only close popups if pointer is outside all our frames
2698 * cannot use our own geometry data here because stacking
2699 * is unknown (the above case implicitly assumes
2700 * that floats are on top which should be true)
2701 */
2702 ::Window aRoot, aChild;
2703 int root_x, root_y, win_x, win_y;
2704 unsigned int mask_return;
2705 if( XQueryPointer( GetXDisplay(),
2706 GetDisplay()->GetRootWindow( m_nXScreen ),
2707 &aRoot, &aChild,
2708 &root_x, &root_y,
2709 &win_x, &win_y,
2710 &mask_return )
2711 && aChild // pointer may not be in any child
2712 )
2713 {
2714 for (auto pSalFrame : GetDisplay()->getFrames() )
2715 {
2716 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( pSalFrame );
2717 if( ! pFrame->IsFloatGrabWindow()
2718 && ( pFrame->GetWindow() == aChild ||
2719 pFrame->GetShellWindow() == aChild ||
2720 pFrame->GetStackingWindow() == aChild )
2721 )
2722 {
2723 // #i63638# check that pointer is inside window, not
2724 // only inside stacking window
2725 if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) &&
2726 root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) )
2727 {
2728 bClosePopups = false;
2729 }
2730 break;
2731 }
2732 }
2733 }
2734 }
2735 }
2736
2737 if( m_bXEmbed && pEvent->xbutton.button == Button11 )
2738 askForXEmbedFocus( pEvent->xbutton.time );
2739
2740 if( pEvent->xbutton.button == Button11 ||
2741 pEvent->xbutton.button == Button22 ||
2742 pEvent->xbutton.button == Button33 )
2743 {
2744 aMouseEvt.mnX = pEvent->xbutton.x;
2745 aMouseEvt.mnY = pEvent->xbutton.y;
2746 aMouseEvt.mnTime = pEvent->xbutton.time;
2747 aMouseEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
2748
2749 if( Button11 == pEvent->xbutton.button )
2750 aMouseEvt.mnButton = MOUSE_LEFT(sal_uInt16(0x0001));
2751 else if( Button22 == pEvent->xbutton.button )
2752 aMouseEvt.mnButton = MOUSE_MIDDLE(sal_uInt16(0x0002));
2753 else if( Button33 == pEvent->xbutton.button )
2754 aMouseEvt.mnButton = MOUSE_RIGHT(sal_uInt16(0x0004));
2755
2756 nEvent = ButtonPress4 == pEvent->type
2757 ? SalEvent::MouseButtonDown
2758 : SalEvent::MouseButtonUp;
2759 }
2760 else if( pEvent->xbutton.button == Button44 ||
2761 pEvent->xbutton.button == Button55 ||
2762 pEvent->xbutton.button == Button66 ||
2763 pEvent->xbutton.button == Button77 )
2764 {
2765 const bool bIncrement(
2766 pEvent->xbutton.button == Button44 ||
2767 pEvent->xbutton.button == Button66 );
2768 const bool bHoriz(
2769 pEvent->xbutton.button == Button66 ||
2770 pEvent->xbutton.button == Button77 );
2771
2772 if( pEvent->type == ButtonRelease5 )
2773 return false;
2774
2775 static sal_uLong nLines = 0;
2776 if( ! nLines )
2777 {
2778 char* pEnv = getenv( "SAL_WHEELLINES" );
2779 nLines = pEnv ? atoi( pEnv ) : 3;
2780 if( nLines > 10 )
2781 nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL(sal_uLong(0xFFFFFFFF));
2782 }
2783
2784 // Compress consecutive wheel events (way too fine scrolling may cause lags if one scrolling steps takes long).
2785 CompressWheelEventsData data;
2786 data.firstEvent = pEvent;
2787 data.count = 1;
2788 XEvent dummy;
2789 do
2790 {
2791 data.ignore = false;
2792 } while( XCheckIfEvent( pEvent->xany.display, &dummy, compressWheelEvents, reinterpret_cast< XPointer >( &data )));
2793
2794 SalWheelMouseEvent aWheelEvt;
2795 aWheelEvt.mnTime = pEvent->xbutton.time;
2796 aWheelEvt.mnX = pEvent->xbutton.x;
2797 aWheelEvt.mnY = pEvent->xbutton.y;
2798 aWheelEvt.mnDelta = ( bIncrement ? 120 : -120 ) * data.count;
2799 aWheelEvt.mnNotchDelta = bIncrement ? 1 : -1;
2800 aWheelEvt.mnScrollLines = nLines * data.count;
2801 aWheelEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
2802 aWheelEvt.mbHorz = bHoriz;
2803
2804 nEvent = SalEvent::WheelMouse;
2805
2806 if( AllSettings::GetLayoutRTL() )
2807 aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX;
2808 return CallCallback( nEvent, &aWheelEvt );
2809 }
2810 }
2811
2812 bool nRet = false;
2813 if( nEvent == SalEvent::MouseLeave
2814 || ( aMouseEvt.mnX < nWidth_ && aMouseEvt.mnX > -1 &&
2815 aMouseEvt.mnY < nHeight_ && aMouseEvt.mnY > -1 )
2816 || pDisplay_->MouseCaptured( this )
2817 )
2818 {
2819 if( AllSettings::GetLayoutRTL() )
2820 aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX;
2821 nRet = CallCallback( nEvent, &aMouseEvt );
2822 }
2823
2824 if( bClosePopups )
2825 {
2826 /* #108213# close popups after dispatching the event outside the popup;
2827 * applications do weird things.
2828 */
2829 ImplSVData* pSVData = ImplGetSVData();
2830 if (pSVData->mpWinData->mpFirstFloat)
2831 {
2832 if (!(pSVData->mpWinData->mpFirstFloat->GetPopupModeFlags()
2833 & FloatWinPopupFlags::NoAppFocusClose))
2834 pSVData->mpWinData->mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel
2835 | FloatWinPopupEndFlags::CloseAll);
2836 }
2837 }
2838
2839 return nRet;
2840}
2841
2842namespace {
2843
2844// F10 means either KEY_F10 or KEY_MENU, which has to be decided
2845// in the independent part.
2846struct KeyAlternate
2847{
2848 sal_uInt16 nKeyCode;
2849 sal_Unicode nCharCode;
2850 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
2851 KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
2852};
2853
2854}
2855
2856static KeyAlternate
2857GetAlternateKeyCode( const sal_uInt16 nKeyCode )
2858{
2859 KeyAlternate aAlternate;
2860
2861 switch( nKeyCode )
2862 {
2863 case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
2864 case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
2865 }
2866
2867 return aAlternate;
2868}
2869
2870void X11SalFrame::beginUnicodeSequence()
2871{
2872 OUString& rSeq( GetGenericUnixSalData()->GetUnicodeCommand() );
2873 vcl::DeletionListener aDeleteWatch( this );
2874
2875 if( !rSeq.isEmpty() )
2876 endUnicodeSequence();
2877
2878 rSeq = "u";
2879
2880 if( ! aDeleteWatch.isDeleted() )
2881 {
2882 ExtTextInputAttr nTextAttr = ExtTextInputAttr::Underline;
2883 SalExtTextInputEvent aEv;
2884 aEv.maText = rSeq;
2885 aEv.mpTextAttr = &nTextAttr;
2886 aEv.mnCursorPos = 0;
2887 aEv.mnCursorFlags = 0;
2888
2889 CallCallback(SalEvent::ExtTextInput, static_cast<void*>(&aEv));
2890 }
2891}
2892
2893bool X11SalFrame::appendUnicodeSequence( sal_Unicode c )
2894{
2895 bool bRet = false;
2896 OUString& rSeq( GetGenericUnixSalData()->GetUnicodeCommand() );
2897 if( !rSeq.isEmpty() )
2898 {
2899 // range check
2900 if( (c >= '0' && c <= '9') ||
2901 (c >= 'a' && c <= 'f') ||
2902 (c >= 'A' && c <= 'F') )
2903 {
2904 rSeq += OUStringChar(c);
2905 std::vector<ExtTextInputAttr> attribs( rSeq.getLength(), ExtTextInputAttr::Underline );
2906
2907 SalExtTextInputEvent aEv;
2908 aEv.maText = rSeq;
2909 aEv.mpTextAttr = attribs.data();
2910 aEv.mnCursorPos = 0;
2911 aEv.mnCursorFlags = 0;
2912
2913 CallCallback(SalEvent::ExtTextInput, static_cast<void*>(&aEv));
2914 bRet = true;
2915 }
2916 else
2917 bRet = endUnicodeSequence();
2918 }
2919 else
2920 endUnicodeSequence();
2921 return bRet;
2922}
2923
2924bool X11SalFrame::endUnicodeSequence()
2925{
2926 OUString& rSeq( GetGenericUnixSalData()->GetUnicodeCommand() );
2927
2928 vcl::DeletionListener aDeleteWatch( this );
2929 if( rSeq.getLength() > 1 && rSeq.getLength() < 6 )
2930 {
2931 // cut the "u"
2932 OUString aNumbers( rSeq.copy( 1 ) );
2933 sal_uInt32 nValue = aNumbers.toUInt32( 16 );
2934 if( nValue >= 32 )
2935 {
2936 ExtTextInputAttr nTextAttr = ExtTextInputAttr::Underline;
2937 SalExtTextInputEvent aEv;
2938 aEv.maText = OUString( sal_Unicode(nValue) );
2939 aEv.mpTextAttr = &nTextAttr;
2940 aEv.mnCursorPos = 0;
2941 aEv.mnCursorFlags = 0;
2942 CallCallback(SalEvent::ExtTextInput, static_cast<void*>(&aEv));
2943 }
2944 }
2945 bool bWasInput = !rSeq.isEmpty();
2946 rSeq.clear();
2947 if( bWasInput && ! aDeleteWatch.isDeleted() )
2948 CallCallback(SalEvent::EndExtTextInput, nullptr);
2949 return bWasInput;
2950}
2951
2952bool X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent )
2953{
2954 if( pEvent->type == KeyRelease3 )
2955 {
2956 // Ignore autorepeat keyrelease events. If there is a series of keypress+keyrelease+keypress events
2957 // generated by holding down a key, and if these are from autorepeat (keyrelease and the following keypress
2958 // have the same timestamp), drop the autorepeat keyrelease event. Not exactly sure why this is done
2959 // (possibly hiding differences between platforms, or just making it more sensible, because technically
2960 // the key has not been released at all).
2961 bool ignore = false;
2962 // Discard queued excessive autorepeat events.
2963 // If the user presses and holds down a key, the autorepeating keypress events
2964 // may overload LO (e.g. if the key is PageDown and the LO cannot keep up scrolling).
2965 // Reduce the load by simply discarding such excessive events (so for a KeyRelease event,
2966 // check if it's followed by matching KeyPress+KeyRelease pair(s) and discard those).
2967 // This shouldn't have any negative effects - unlike with normal (non-autorepeat
2968 // events), the user is unlikely to rely on the exact number of resulting actions
2969 // (since autorepeat generates keypress events rather quickly and it's hard to estimate
2970 // how many exactly) and the idea should be just keeping the key pressed until something
2971 // happens (in which case more events that just lag LO shouldn't make a difference).
2972 Display* dpy = pEvent->display;
2973 XKeyEvent previousRelease = *pEvent;
2974 while( XPending( dpy ))
2975 {
2976 XEvent nextEvent1;
2977 bool discard1 = false;
2978 XNextEvent( dpy, &nextEvent1 );
2979 if( nextEvent1.type == KeyPress2 && nextEvent1.xkey.time == previousRelease.time
2980 && !nextEvent1.xkey.send_event && nextEvent1.xkey.window == previousRelease.window
2981 && nextEvent1.xkey.state == previousRelease.state && nextEvent1.xkey.keycode == previousRelease.keycode )
2982 { // This looks like another autorepeat keypress.
2983 ignore = true;
2984 if( XPending( dpy ))
2985 {
2986 XEvent nextEvent2;
2987 XNextEvent( dpy, &nextEvent2 );
2988 if( nextEvent2.type == KeyRelease3 && nextEvent2.xkey.time <= ( previousRelease.time + 100 )
2989 && !nextEvent2.xkey.send_event && nextEvent2.xkey.window == previousRelease.window
2990 && nextEvent2.xkey.state == previousRelease.state && nextEvent2.xkey.keycode == previousRelease.keycode )
2991 { // And the matching keyrelease -> drop them both.
2992 discard1 = true;
2993 previousRelease = nextEvent2.xkey;
2994 ignore = false; // There either will be another autorepeating keypress that'll lead to discarding
2995 // the pEvent keyrelease, it this discarding makes that keyrelease the last one.
2996 }
2997 else
2998 {
2999 XPutBackEvent( dpy, &nextEvent2 );
3000 break;
3001 }
3002 }
3003 }
3004 if( !discard1 )
3005 { // Unrelated event, put back and stop compressing.
3006 XPutBackEvent( dpy, &nextEvent1 );
3007 break;
3008 }
3009 }
3010 if( ignore ) // This autorepeating keyrelease is followed by another keypress.
3011 return false;
3012 }
3013
3014 KeySym nKeySym;
3015 KeySym nUnmodifiedKeySym;
3016 int nLen = 2048;
3017 char *pPrintable = static_cast<char*>(alloca( nLen )__builtin_alloca (nLen));
3018
3019 // singlebyte code composed by input method, the new default
3020 if (mpInputContext != nullptr && mpInputContext->UseContext())
3021 {
3022 // returns a keysym as well as the pPrintable (in system encoding)
3023 // printable may be empty.
3024 Statusint nStatus;
3025 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3026 &nUnmodifiedKeySym,
3027 &nStatus, mpInputContext->GetContext() );
3028 if ( nStatus == XBufferOverflow-1 )
3029 {
3030 // In case of overflow, XmbLookupString (called by GetKeySym)
3031 // returns required size
3032 // TODO : check if +1 is needed for 0 terminator
3033 nLen += 1;
3034 pPrintable = static_cast<char*>(alloca( nLen )__builtin_alloca (nLen));
3035 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
3036 &nUnmodifiedKeySym,
3037 &nStatus, mpInputContext->GetContext() );
3038 }
3039 }
3040 else
3041 {
3042 // fallback, this should never ever be called
3043 Statusint nStatus = 0;
3044 nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus );
3045 }
3046
3047 SalKeyEvent aKeyEvt;
3048 sal_uInt16 nKeyCode;
3049 sal_uInt16 nModCode = 0;
3050 char aDummy;
3051
3052 if( pEvent->state & ShiftMask(1<<0) )
3053 nModCode |= KEY_SHIFT;
3054 if( pEvent->state & ControlMask(1<<2) )
3055 nModCode |= KEY_MOD1;
3056 if( pEvent->state & Mod1Mask(1<<3) )
3057 nModCode |= KEY_MOD2;
3058
3059 if( nModCode != (KEY_SHIFT|KEY_MOD1) )
3060 endUnicodeSequence();
3061
3062 if( nKeySym == XK_Shift_L0xffe1 || nKeySym == XK_Shift_R0xffe2
3063 || nKeySym == XK_Control_L0xffe3 || nKeySym == XK_Control_R0xffe4
3064 || nKeySym == XK_Alt_L0xffe9 || nKeySym == XK_Alt_R0xffea
3065 || nKeySym == XK_Meta_L0xffe7 || nKeySym == XK_Meta_R0xffe8
3066 || nKeySym == XK_Super_L0xffeb || nKeySym == XK_Super_R0xffec )
3067 {
3068 SalKeyModEvent aModEvt;
3069 aModEvt.mbDown = false; // auto-accelerator feature not supported here.
3070 aModEvt.mnModKeyCode = ModKeyFlags::NONE;
3071 if( pEvent->type == KeyPress2 && mnExtKeyMod == ModKeyFlags::NONE )
3072 mbSendExtKeyModChange = true;
3073 else if( pEvent->type == KeyRelease3 && mbSendExtKeyModChange )
3074 {
3075 aModEvt.mnModKeyCode = mnExtKeyMod;
3076 mnExtKeyMod = ModKeyFlags::NONE;
3077 }
3078
3079 // pressing just the ctrl key leads to a keysym of XK_Control but
3080 // the event state does not contain ControlMask. In the release
3081 // event it's the other way round: it does contain the Control mask.
3082 // The modifier mode therefore has to be adapted manually.
3083 ModKeyFlags nExtModMask = ModKeyFlags::NONE;
3084 sal_uInt16 nModMask = 0;
3085 switch( nKeySym )
3086 {
3087 case XK_Control_L0xffe3:
3088 nExtModMask = ModKeyFlags::LeftMod1;
3089 nModMask = KEY_MOD1;
3090 break;
3091 case XK_Control_R0xffe4:
3092 nExtModMask = ModKeyFlags::RightMod1;
3093 nModMask = KEY_MOD1;
3094 break;
3095 case XK_Alt_L0xffe9:
3096 nExtModMask = ModKeyFlags::LeftMod2;
3097 nModMask = KEY_MOD2;
3098 break;
3099 case XK_Alt_R0xffea:
3100 nExtModMask = ModKeyFlags::RightMod2;
3101 nModMask = KEY_MOD2;
3102 break;
3103 case XK_Shift_L0xffe1:
3104 nExtModMask = ModKeyFlags::LeftShift;
3105 nModMask = KEY_SHIFT;
3106 break;
3107 case XK_Shift_R0xffe2:
3108 nExtModMask = ModKeyFlags::RightShift;
3109 nModMask = KEY_SHIFT;
3110 break;
3111 // Map Meta/Super keys to MOD3 modifier on all Unix systems
3112 // except macOS
3113 case XK_Meta_L0xffe7:
3114 case XK_Super_L0xffeb:
3115 nExtModMask = ModKeyFlags::LeftMod3;
3116 nModMask = KEY_MOD3;
3117 break;
3118 case XK_Meta_R0xffe8:
3119 case XK_Super_R0xffec:
3120 nExtModMask = ModKeyFlags::RightMod3;
3121 nModMask = KEY_MOD3;
3122 break;
3123 }
3124 if( pEvent->type == KeyRelease3 )
3125 {
3126 nModCode &= ~nModMask;
3127 mnExtKeyMod &= ~nExtModMask;
3128 }
3129 else
3130 {
3131 nModCode |= nModMask;
3132 mnExtKeyMod |= nExtModMask;
3133 }
3134
3135 aModEvt.mnCode = nModCode;
3136
3137 return CallCallback( SalEvent::KeyModChange, &aModEvt );
3138 }
3139
3140 mbSendExtKeyModChange = false;
3141
3142 // try to figure out the vcl code for the keysym
3143 // #i52338# use the unmodified KeySym if there is none for the real KeySym
3144 // because the independent part has only keycodes for unshifted keys
3145 nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy );
3146 if( nKeyCode == 0 )
3147 nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
3148
3149 // try to figure out a printable if XmbLookupString returns only a keysym
3150 // and NOT a printable. Do not store it in pPrintable[0] since it is expected to
3151 // be in system encoding, not unicode.
3152 // #i8988##, if KeySym and printable look equally promising then prefer KeySym
3153 // the printable is bound to the encoding so the KeySym might contain more
3154 // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and
3155 // (the desired) Zcaron in KeySym
3156 sal_Unicode nKeyString = 0x0;
3157 if ( (nLen == 0)
3158 || ((nLen == 1) && (nKeySym > 0)) )
3159 nKeyString = KeysymToUnicode (nKeySym);
3160 // if we have nothing we give up
3161 if( !nKeyCode && !nLen && !nKeyString)
3162 return false;
3163
3164 vcl::DeletionListener aDeleteWatch( this );
3165
3166 if( nModCode == (KEY_SHIFT | KEY_MOD1) && pEvent->type == KeyPress2 )
3167 {
3168 sal_uInt16 nSeqKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
3169 if( nSeqKeyCode == KEY_U )
3170 {
3171 beginUnicodeSequence();
3172 return true;
3173 }
3174 else if( nSeqKeyCode >= KEY_0 && nSeqKeyCode <= KEY_9 )
3175 {
3176 if( appendUnicodeSequence( u'0' + sal_Unicode(nSeqKeyCode - KEY_0) ) )
3177 return true;
3178 }
3179 else if( nSeqKeyCode >= KEY_A && nSeqKeyCode <= KEY_F )
3180 {
3181 if( appendUnicodeSequence( u'a' + sal_Unicode(nSeqKeyCode - KEY_A) ) )
3182 return true;
3183 }
3184 else
3185 endUnicodeSequence();
3186 }
3187
3188 if( aDeleteWatch.isDeleted() )
3189 return false;
3190
3191 rtl_TextEncoding nEncoding = osl_getThreadTextEncoding();
3192
3193 sal_Unicode *pBuffer;
3194 sal_Unicode *pString;
3195 sal_Size nBufferSize = nLen * 2;
3196 sal_Size nSize;
3197 pBuffer = static_cast<sal_Unicode*>(malloc( nBufferSize + 2 ));
3198 pBuffer[ 0 ] = 0;
3199
3200 if (nKeyString != 0)
3201 {
3202 pString = &nKeyString;
3203 nSize = 1;
3204 }
3205 else if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE(((rtl_TextEncoding) 0xFFFF)))
3206 {
3207 // create text converter
3208 rtl_TextToUnicodeConverter aConverter =
3209 rtl_createTextToUnicodeConverter( nEncoding );
3210 rtl_TextToUnicodeContext aContext =
3211 rtl_createTextToUnicodeContext( aConverter );
3212
3213 sal_uInt32 nConversionInfo;
3214 sal_Size nConvertedChars;
3215
3216 // convert to single byte text stream
3217 nSize = rtl_convertTextToUnicode(
3218 aConverter, aContext,
3219 reinterpret_cast<char*>(pPrintable), nLen,
3220 pBuffer, nBufferSize,
3221 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE((sal_uInt32)0x0002) |
3222 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE((sal_uInt32)0x0200),
3223 &nConversionInfo, &nConvertedChars );
3224
3225 // destroy converter
3226 rtl_destroyTextToUnicodeContext( aConverter, aContext );
3227 rtl_destroyTextToUnicodeConverter( aConverter );
3228
3229 pString = pBuffer;
3230 }
3231 else if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */)
3232 {
3233 pString = reinterpret_cast<sal_Unicode*>(pPrintable);
3234 nSize = nLen;
3235 }
3236 else
3237 {
3238 pString = pBuffer;
3239 nSize = 0;
3240 }
3241
3242 if ( mpInputContext != nullptr
3243 && mpInputContext->UseContext()
3244 && KeyRelease3 != pEvent->type
3245 && ( (nSize > 1)
3246 || (nSize > 0 && mpInputContext->IsPreeditMode())) )
3247 {
3248 mpInputContext->CommitKeyEvent(pString, nSize);
3249 }
3250 else
3251 // normal single character keyinput
3252 {
3253 aKeyEvt.mnCode = nKeyCode | nModCode;
3254 aKeyEvt.mnRepeat = 0;
3255 aKeyEvt.mnCharCode = pString[ 0 ];
3256
3257 if( KeyRelease3 == pEvent->type )
3258 {
3259 CallCallback( SalEvent::KeyUp, &aKeyEvt );
3260 }
3261 else
3262 {
3263 if ( ! CallCallback(SalEvent::KeyInput, &aKeyEvt) )
3264 {
3265 // independent layer doesn't want to handle key-event, so check
3266 // whether the keycode may have an alternate meaning
3267 KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode );
3268 if ( aAlternate.nKeyCode != 0 )
3269 {
3270 aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode;
3271 if( aAlternate.nCharCode )
3272 aKeyEvt.mnCharCode = aAlternate.nCharCode;
3273 CallCallback(SalEvent::KeyInput, &aKeyEvt);
3274 }
3275 }
3276 }
3277 }
3278
3279 // update the spot location for PreeditPosition IME style
3280
3281 if (! aDeleteWatch.isDeleted())
3282 {
3283 if (mpInputContext != nullptr && mpInputContext->UseContext())
3284 mpInputContext->UpdateSpotLocation();
3285 }
3286
3287 free (pBuffer);
3288 return true;
3289}
3290
3291bool X11SalFrame::HandleFocusEvent( XFocusChangeEvent const *pEvent )
3292{
3293 // ReflectionX in Windows mode changes focus while mouse is grabbed
3294 if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName() == "ReflectionX Windows" )
3295 return true;
3296
3297 /* ignore focusout resulting from keyboard grabs
3298 * we do not grab it and are not interested when
3299 * someone else does CDE e.g. does a XGrabKey on arrow keys
3300 * handle focus events with mode NotifyWhileGrabbed
3301 * because with CDE alt-tab focus changing we do not get
3302 * normal focus events
3303 * cast focus event to the input context, otherwise the
3304 * status window does not follow the application frame
3305 */
3306
3307 if ( mpInputContext != nullptr )
3308 {
3309 if( FocusIn9 == pEvent->type )
3310 mpInputContext->SetICFocus( this );
3311 }
3312
3313 if ( pEvent->mode == NotifyNormal0 || pEvent->mode == NotifyWhileGrabbed3 ||
3314 ( ( nStyle_ & SalFrameStyleFlags::PLUG ) && pEvent->window == GetShellWindow() )
3315 )
3316 {
3317 if( hPresentationWindow != None0L && hPresentationWindow != GetShellWindow() )
3318 return false;
3319
3320 if( FocusIn9 == pEvent->type )
3321 {
3322 GetSalData()->m_pInstance->updatePrinterUpdate();
3323 mbInputFocus = True1;
3324 ImplSVData* pSVData = ImplGetSVData();
3325
3326 bool nRet = CallCallback( SalEvent::GetFocus, nullptr );
3327 if ((mpParent != nullptr && nStyle_ == SalFrameStyleFlags::NONE)
3328 && pSVData->mpWinData->mpFirstFloat)
3329 {
3330 FloatWinPopupFlags nMode = pSVData->mpWinData->mpFirstFloat->GetPopupModeFlags();
3331 pSVData->mpWinData->mpFirstFloat->SetPopupModeFlags(
3332 nMode & ~FloatWinPopupFlags::NoAppFocusClose);
3333 }
3334 return nRet;
3335 }
3336 else
3337 {
3338 mbInputFocus = False0;
3339 mbSendExtKeyModChange = false;
3340 mnExtKeyMod = ModKeyFlags::NONE;
3341 return CallCallback( SalEvent::LoseFocus, nullptr );
3342 }
3343 }
3344
3345 return false;
3346}
3347
3348bool X11SalFrame::HandleExposeEvent( XEvent const *pEvent )
3349{
3350 XRectangle aRect = { 0, 0, 0, 0 };
3351 sal_uInt16 nCount = 0;
3352
3353 if( pEvent->type == Expose12 )
3354 {
3355 aRect.x = pEvent->xexpose.x;
3356 aRect.y = pEvent->xexpose.y;
3357 aRect.width = pEvent->xexpose.width;
3358 aRect.height = pEvent->xexpose.height;
3359 nCount = pEvent->xexpose.count;
3360 }
3361 else if( pEvent->type == GraphicsExpose13 )
3362 {
3363 aRect.x = pEvent->xgraphicsexpose.x;
3364 aRect.y = pEvent->xgraphicsexpose.y;
3365 aRect.width = pEvent->xgraphicsexpose.width;
3366 aRect.height = pEvent->xgraphicsexpose.height;
3367 nCount = pEvent->xgraphicsexpose.count;
3368 }
3369
3370 if( IsOverrideRedirect() && mbFullScreen &&
3371 aPresentationReparentList.empty() )
3372 // we are in fullscreen mode -> override redirect
3373 // focus is possibly lost, so reget it
3374 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone(int)0L, CurrentTime0L );
3375
3376 // width and height are extents, so they are of by one for rectangle
3377 maPaintRegion.Union( tools::Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) );
3378
3379 if( nCount )
3380 // wait for last expose rectangle, do not wait for resize timer
3381 // if a completed graphics expose sequence is available
3382 return true;
3383
3384 SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() );
3385
3386 CallCallback( SalEvent::Paint, &aPEvt );
3387 maPaintRegion = tools::Rectangle();
3388
3389 return true;
3390}
3391
3392void X11SalFrame::RestackChildren( ::Window* pTopLevelWindows, int nTopLevelWindows )
3393{
3394 if( maChildren.empty() )
3395 return;
3396
3397 int nWindow = nTopLevelWindows;
3398 while( nWindow-- )
3399 if( pTopLevelWindows[nWindow] == GetStackingWindow() )
3400 break;
3401 if( nWindow < 0 )
3402 return;
3403
3404 for (auto const& child : maChildren)
3405 {
3406 if( child->bMapped_ )
3407 {
3408 int nChild = nWindow;
3409 while( nChild-- )
3410 {
3411 if( pTopLevelWindows[nChild] == child->GetStackingWindow() )
3412 {
3413 // if a child is behind its parent, place it above the
3414 // parent (for insane WMs like Dtwm and olwm)
3415 XWindowChanges aCfg;
3416 aCfg.sibling = GetStackingWindow();
3417 aCfg.stack_mode = Above0;
3418 XConfigureWindow( GetXDisplay(), child->GetStackingWindow(), CWSibling(1<<5)|CWStackMode(1<<6), &aCfg );
3419 break;
3420 }
3421 }
3422 }
3423 }
3424 for (auto const& child : maChildren)
3425 {
3426 child->RestackChildren( pTopLevelWindows, nTopLevelWindows );
3427 }
3428}
3429
3430void X11SalFrame::RestackChildren()
3431{
3432 if( maChildren.empty() )
3433 return;
3434
3435 ::Window aRoot, aParent, *pChildren = nullptr;
3436 unsigned int nChildren;
3437 if( XQueryTree( GetXDisplay(),
3438 GetDisplay()->GetRootWindow( m_nXScreen ),
3439 &aRoot,
3440 &aParent,
3441 &pChildren,
3442 &nChildren ) )
3443 {
3444 RestackChildren( pChildren, nChildren );
3445 XFree( pChildren );
3446 }
3447}
3448
3449static Boolint size_event_predicate( Display*, XEvent* event, XPointer arg )
3450{
3451 if( event->type != ConfigureNotify22 )
3452 return False0;
3453 X11SalFrame* frame = reinterpret_cast< X11SalFrame* >( arg );
3454 XConfigureEvent* pEvent = &event->xconfigure;
3455 if( pEvent->window != frame->GetShellWindow()
3456 && pEvent->window != frame->GetWindow()
3457 && pEvent->window != frame->GetForeignParent()
3458 && pEvent->window != frame->GetStackingWindow())
3459 { // ignored at top of HandleSizeEvent()
3460 return False0;
3461 }
3462 if( pEvent->window == frame->GetStackingWindow())
3463 return False0; // filtered later in HandleSizeEvent()
3464 // at this point we know that there is another similar event in the queue
3465 frame->setPendingSizeEvent();
3466 return False0; // but do not process the new event out of order
3467}
3468
3469void X11SalFrame::setPendingSizeEvent()
3470{
3471 mPendingSizeEvent = true;
3472}
3473
3474bool X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
3475{
3476 // NOTE: if you add more tests in this function, make sure to update size_event_predicate()
3477 // so that it finds exactly the same events
3478
3479 if ( pEvent->window != GetShellWindow()
3480 && pEvent->window != GetWindow()
3481 && pEvent->window != GetForeignParent()
3482 && pEvent->window != GetStackingWindow()
3483 )
3484 {
3485 // could be as well a sys-child window (aka SalObject)
3486 return true;
3487 }
3488
3489 if( ( nStyle_ & SalFrameStyleFlags::PLUG ) && pEvent->window == GetShellWindow() )
3490 {
3491 // just update the children's positions
3492 RestackChildren();
3493 return true;
3494 }
3495
3496 if( pEvent->window == GetForeignParent() )
3497 XResizeWindow( GetXDisplay(),
3498 GetWindow(),
3499 pEvent->width,
3500 pEvent->height );
3501
3502 ::Window hDummy;
3503 XTranslateCoordinates( GetXDisplay(),
3504 GetWindow(),
3505 pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() ),
3506 0, 0,
3507 &pEvent->x, &pEvent->y,
3508 &hDummy );
3509
3510 if( pEvent->window == GetStackingWindow() )
3511 {
3512 if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y )
3513 {
3514 maGeometry.nX = pEvent->x;
3515 maGeometry.nY = pEvent->y;
3516 CallCallback( SalEvent::Move, nullptr );
3517 }
3518 return true;
3519 }
3520
3521 // check size hints in first time SalFrame::Show
3522 if( SHOWSTATE_UNKNOWN-1 == nShowState_ && bMapped_ )
3523 nShowState_ = SHOWSTATE_NORMAL1;
3524
3525 // Avoid a race condition where resizing this window to one size and shortly after that
3526 // to another size generates first size event with the old size and only after that
3527 // with the new size, temporarily making us think the old size is valid (bnc#674806).
3528 // So if there is another size event for this window pending, ignore this one.
3529 mPendingSizeEvent = false;
3530 XEvent dummy;
3531 XCheckIfEvent( GetXDisplay(), &dummy, size_event_predicate, reinterpret_cast< XPointer >( this ));
3532 if( mPendingSizeEvent )
3533 return true;
3534
3535 nWidth_ = pEvent->width;
3536 nHeight_ = pEvent->height;
3537
3538 bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY );
3539 bool bSized = ( pEvent->width != static_cast<int>(maGeometry.nWidth) || pEvent->height != static_cast<int>(maGeometry.nHeight) );
3540
3541 maGeometry.nX = pEvent->x;
3542 maGeometry.nY = pEvent->y;
3543 maGeometry.nWidth = pEvent->width;
3544 maGeometry.nHeight = pEvent->height;
3545 updateScreenNumber();
3546
3547 // update children's position
3548 RestackChildren();
3549
3550 if( bSized && ! bMoved )
3551 CallCallback( SalEvent::Resize, nullptr );
3552 else if( bMoved && ! bSized )
3553 CallCallback( SalEvent::Move, nullptr );
3554 else if( bMoved && bSized )
3555 CallCallback( SalEvent::MoveResize, nullptr );
3556
3557 return true;
3558}
3559
3560IMPL_LINK_NOARG(X11SalFrame, HandleAlwaysOnTopRaise, Timer *, void)void X11SalFrame::LinkStubHandleAlwaysOnTopRaise(void * instance
, Timer * data) { return static_cast<X11SalFrame *>(instance
)->HandleAlwaysOnTopRaise(data); } void X11SalFrame::HandleAlwaysOnTopRaise
(__attribute__ ((unused)) Timer *)
3561{
3562 if( bMapped_ )
3563 ToTop( SalFrameToTop::NONE );
3564}
3565
3566bool X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent )
3567{
3568 Display *pDisplay = pEvent->display;
3569 ::Window hWM_Parent;
3570 ::Window hRoot, *Children, hDummy;
3571 unsigned int nChildren;
3572
3573 static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" );
3574
3575 GetGenericUnixSalData()->ErrorTrapPush();
3576
3577 /*
3578 * don't rely on the new parent from the event.
3579 * the event may be "out of date", that is the window manager
3580 * window may not exist anymore. This can happen if someone
3581 * shows a frame and hides it again quickly (not that it would
3582 * be very sensible)
3583 */
3584 hWM_Parent = GetShellWindow();
3585 do
3586 {
3587 Children = nullptr;
3588 XQueryTree( pDisplay,
3589 hWM_Parent,
3590 &hRoot,
3591 &hDummy,
3592 &Children,
3593 &nChildren );
3594
3595 bool bError = GetGenericUnixSalData()->ErrorTrapPop( false );
3596 GetGenericUnixSalData()->ErrorTrapPush();
3597
3598 if( bError )
3599 {
3600 hWM_Parent = GetShellWindow();
3601 break;
3602 }
3603 /* this sometimes happens if a Show(true) is
3604 * immediately followed by Show(false) (which is braindead anyway)
3605 */
3606 if( hDummy == hWM_Parent )
3607 hDummy = hRoot;
3608 if( hDummy != hRoot )
3609 hWM_Parent = hDummy;
3610 if( Children )
3611 XFree( Children );
3612 } while( hDummy != hRoot );
3613
3614 if( GetStackingWindow() == None0L
3615 && hWM_Parent != hPresentationWindow
3616 && hWM_Parent != GetShellWindow()
3617 && ( ! pDisableStackingCheck || ! *pDisableStackingCheck )
3618 )
3619 {
3620 mhStackingWindow = hWM_Parent;
3621 XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask(1L<<17) );
3622 }
3623
3624 if( hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() )
3625 || hWM_Parent == GetForeignParent()
3626 || pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultXScreen() )
3627 || ( nStyle_ & SalFrameStyleFlags::FLOAT ) )
3628 {
3629 // Reparenting before Destroy
3630 aPresentationReparentList.remove( GetStackingWindow() );
3631 mhStackingWindow = None0L;
3632 GetGenericUnixSalData()->ErrorTrapPop();
3633 return false;
3634 }
3635
3636 /*
3637 * evil hack to show decorated windows on top
3638 * of override redirect presentation windows:
3639 * reparent the window manager window to the presentation window
3640 * does not work with non-reparenting WMs
3641 * in future this should not be necessary anymore with
3642 * _NET_WM_STATE_FULLSCREEN available
3643 */
3644 if( hPresentationWindow != None0L
3645 && hPresentationWindow != GetWindow()
3646 && GetStackingWindow() != None0L
3647 && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nXScreen )
3648 )
3649 {
3650 int x = 0, y = 0;
3651 ::Window aChild;
3652 XTranslateCoordinates( GetXDisplay(),
3653 GetStackingWindow(),
3654 GetDisplay()->GetRootWindow( m_nXScreen ),
3655 0, 0,
3656 &x, &y,
3657 &aChild
3658 );
3659 XReparentWindow( GetXDisplay(),
3660 GetStackingWindow(),
3661 hPresentationWindow,
3662 x, y
3663 );
3664 aPresentationReparentList.push_back( GetStackingWindow() );
3665 }
3666
3667 int nLeft = 0, nTop = 0;
3668 XTranslateCoordinates( GetXDisplay(),
3669 GetShellWindow(),
3670 hWM_Parent,
3671 0, 0,
3672 &nLeft,
3673 &nTop,
3674 &hDummy );
3675 maGeometry.nLeftDecoration = nLeft > 0 ? nLeft-1 : 0;
3676 maGeometry.nTopDecoration = nTop > 0 ? nTop-1 : 0;
3677
3678 /*
3679 * decorations are not symmetric,
3680 * so need real geometries here
3681 * (this will fail with virtual roots ?)
3682 */
3683
3684 // reset error occurred
3685 GetGenericUnixSalData()->ErrorTrapPop();
3686 GetGenericUnixSalData()->ErrorTrapPush();
3687
3688 int xp, yp, x, y;
3689 unsigned int wp, w, hp, h, bw, d;
3690 XGetGeometry( GetXDisplay(),
3691 GetShellWindow(),
3692 &hRoot,
3693 &x, &y, &w, &h, &bw, &d );
3694 XGetGeometry( GetXDisplay(),
3695 hWM_Parent,
3696 &hRoot,
3697 &xp, &yp, &wp, &hp, &bw, &d );
3698 bool bResized = false;
3699 bool bError = GetGenericUnixSalData()->ErrorTrapPop( false );
3700 GetGenericUnixSalData()->ErrorTrapPush();
3701
3702 if( ! bError )
3703 {
3704 maGeometry.nRightDecoration = wp - w - maGeometry.nLeftDecoration;
3705 maGeometry.nBottomDecoration = hp - h - maGeometry.nTopDecoration;
3706 /*
3707 * note: this works because hWM_Parent is direct child of root,
3708 * not necessarily parent of GetShellWindow()
3709 */
3710 maGeometry.nX = xp + nLeft;
3711 maGeometry.nY = yp + nTop;
3712 bResized = w != maGeometry.nWidth || h != maGeometry.nHeight;
3713 maGeometry.nWidth = w;
3714 maGeometry.nHeight = h;
3715 }
3716
3717 // limit width and height if we are too large: #47757
3718 // olwm and fvwm need this, it doesn't harm the rest
3719
3720 // #i81311# do this only for sizable frames
3721 if( nStyle_ & SalFrameStyleFlags::SIZEABLE )
3722 {
3723 Size aScreenSize = GetDisplay()->GetScreenSize( m_nXScreen );
3724 int nScreenWidth = aScreenSize.Width();
3725 int nScreenHeight = aScreenSize.Height();
3726 int nFrameWidth = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
3727 int nFrameHeight = maGeometry.nHeight + maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
3728
3729 if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight))
3730 {
3731 Size aSize(maGeometry.nWidth, maGeometry.nHeight);
3732
3733 if (nFrameWidth > nScreenWidth)
3734 aSize.setWidth( nScreenWidth - maGeometry.nRightDecoration - maGeometry.nLeftDecoration );
3735 if (nFrameHeight > nScreenHeight)
3736 aSize.setHeight( nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration );
3737
3738 SetSize( aSize );
3739 bResized = false;
3740 }
3741 }
3742 if( bResized )
3743 CallCallback( SalEvent::Resize, nullptr );
3744
3745 GetGenericUnixSalData()->ErrorTrapPop();
3746
3747 return true;
3748}
3749
3750bool X11SalFrame::HandleStateEvent( XPropertyEvent const *pEvent )
3751{
3752 Atom actual_type;
3753 int actual_format;
3754 unsigned long nitems, bytes_after;
3755 unsigned char *prop = nullptr;
3756
3757 if( 0 != XGetWindowProperty( GetXDisplay(),
3758 GetShellWindow(),
3759 pEvent->atom, // property
3760 0, // long_offset (32bit)
3761 2, // long_length (32bit)
3762 False0, // delete
3763 pEvent->atom, // req_type
3764 &actual_type,
3765 &actual_format,
3766 &nitems,
3767 &bytes_after,
3768 &prop )
3769 || ! prop
3770 )
3771 return false;
3772
3773 DBG_ASSERT( actual_type == pEvent->atomdo { if (true && (!(actual_type == pEvent->atom &&
32 == actual_format && 2 == nitems && 0 == bytes_after
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3776" ": "), "%s", "HandleStateEvent"); } } while (false
)
3774 && 32 == actual_formatdo { if (true && (!(actual_type == pEvent->atom &&
32 == actual_format && 2 == nitems && 0 == bytes_after
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3776" ": "), "%s", "HandleStateEvent"); } } while (false
)
3775 && 2 == nitemsdo { if (true && (!(actual_type == pEvent->atom &&
32 == actual_format && 2 == nitems && 0 == bytes_after
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3776" ": "), "%s", "HandleStateEvent"); } } while (false
)
3776 && 0 == bytes_after, "HandleStateEvent" )do { if (true && (!(actual_type == pEvent->atom &&
32 == actual_format && 2 == nitems && 0 == bytes_after
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3776" ": "), "%s", "HandleStateEvent"); } } while (false
)
;
3777
3778 if( *reinterpret_cast<unsigned long*>(prop) == NormalState1 )
3779 nShowState_ = SHOWSTATE_NORMAL1;
3780 else if( *reinterpret_cast<unsigned long*>(prop) == IconicState3 )
3781 nShowState_ = SHOWSTATE_MINIMIZED0;
3782
3783 XFree( prop );
3784 return true;
3785}
3786
3787bool X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent )
3788{
3789 const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() );
3790
3791#if !defined(__synchronous_extinput__)
3792 if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) )
3793 {
3794 HandleExtTextEvent (pEvent);
3795 return true;
3796 }
3797#endif
3798 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) )
3799 {
3800 SAL_WARN( "vcl", "X11SalFrame::Dispatch Quit" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Dispatch Quit") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Dispatch Quit"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Dispatch Quit"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3800" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "X11SalFrame::Dispatch Quit") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "X11SalFrame::Dispatch Quit"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "X11SalFrame::Dispatch Quit"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3800" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3801 Close(); // ???
3802 return true;
3803 }
3804 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS ) )
3805 {
3806 if( static_cast<Atom>(pEvent->data.l[0]) == rWMAdaptor.getAtom( WMAdaptor::NET_WM_PING ) )
3807 rWMAdaptor.answerPing( this, pEvent );
3808 else if( ! ( nStyle_ & SalFrameStyleFlags::PLUG )
3809 && ! (( nStyle_ & SalFrameStyleFlags::FLOAT ) && (nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION))
3810 )
3811 {
3812 if( static_cast<Atom>(pEvent->data.l[0]) == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) )
3813 {
3814 Close();
3815 return true;
3816 }
3817 else if( static_cast<Atom>(pEvent->data.l[0]) == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) )
3818 {
3819 // do nothing, we set the input focus in ToTop() if necessary
3820#if OSL_DEBUG_LEVEL1 > 1
3821 SAL_INFO("vcl.window", "got WM_TAKE_FOCUS on "do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
3822 << ((nStyle_ &do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
3823 SalFrameStyleFlags::OWNERDRAWDECORATION) ?do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
3824 "ownerdraw" :do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
3825 "NON OWNERDRAW" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
3826 << " window.")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "vcl.window")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "got WM_TAKE_FOCUS on "
<< ((nStyle_ & SalFrameStyleFlags::OWNERDRAWDECORATION
) ? "ownerdraw" : "NON OWNERDRAW" ) << " window.") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.window"
), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "got WM_TAKE_FOCUS on " << ((nStyle_
& SalFrameStyleFlags::OWNERDRAWDECORATION) ? "ownerdraw"
: "NON OWNERDRAW" ) << " window."), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"got WM_TAKE_FOCUS on " << ((nStyle_ & SalFrameStyleFlags
::OWNERDRAWDECORATION) ? "ownerdraw" : "NON OWNERDRAW" ) <<
" window."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/unx/generic/window/salframe.cxx"
":" "3826" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3827#endif
3828 }
3829 }
3830 }
3831 else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) &&
3832 pEvent->window == GetWindow() )
3833 {
3834 if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
3835 pEvent->data.l[1] == 2 ) // XEMBED_WINDOW_DEACTIVATE
3836 {
3837 XFocusChangeEvent aEvent;
3838 aEvent.type = (pEvent->data.l[1] == 1 ? FocusIn9 : FocusOut10);
3839 aEvent.serial = pEvent->serial;
3840 aEvent.send_event = True1;
3841 aEvent.display = pEvent->display;
3842 aEvent.window = pEvent->window;
3843 aEvent.mode = NotifyNormal0;
3844 aEvent.detail = NotifyDetailNone7;
3845 HandleFocusEvent( &aEvent );
3846 }
3847 }
3848 return false;
3849}
3850
3851bool X11SalFrame::Dispatch( XEvent *pEvent )
3852{
3853 bool nRet = false;
3854
3855 if( -1 == nCaptured_ )
3856 {
3857 CaptureMouse( true );
3858#ifdef DBG_UTIL
3859 if( -1 != nCaptured_ )
3860 pDisplay_->DbgPrintDisplayEvent("Captured", pEvent);
3861#endif
3862 }
3863
3864 if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() )
3865 {
3866 switch( pEvent->type )
3867 {
3868 case KeyPress2:
3869 nRet = HandleKeyEvent( &pEvent->xkey );
3870 break;
3871
3872 case KeyRelease3:
3873 nRet = HandleKeyEvent( &pEvent->xkey );
3874 break;
3875
3876 case ButtonPress4:
3877 // if we lose the focus in presentation mode
3878 // there are good chances that we never get it back
3879 // since the WM ignores us
3880 if( IsOverrideRedirect() )
3881 {
3882 XSetInputFocus( GetXDisplay(), GetShellWindow(),
3883 RevertToNone(int)0L, CurrentTime0L );
3884 }
3885 [[fallthrough]];
3886 case ButtonRelease5:
3887 case MotionNotify6:
3888 case EnterNotify7:
3889 case LeaveNotify8:
3890 nRet = HandleMouseEvent( pEvent );
3891 break;
3892
3893 case FocusIn9:
3894 case FocusOut10:
3895 nRet = HandleFocusEvent( &pEvent->xfocus );
3896 break;
3897
3898 case Expose12:
3899 case GraphicsExpose13:
3900 nRet = HandleExposeEvent( pEvent );
3901 break;
3902
3903 case MapNotify19:
3904 if( pEvent->xmap.window == GetShellWindow() )
3905 {
3906 if( nShowState_ == SHOWSTATE_HIDDEN2 )
3907 {
3908 /*
3909 * workaround for (at least) KWin 2.2.2
3910 * which will map windows that were once transient
3911 * even if they are withdrawn when the respective
3912 * document is mapped.
3913 */
3914 if( ! (nStyle_ & SalFrameStyleFlags::PLUG) )
3915 XUnmapWindow( GetXDisplay(), GetShellWindow() );
3916 break;
3917 }
3918 bMapped_ = true;
3919 bViewable_ = true;
3920 nRet = true;
3921 if ( mpInputContext != nullptr )
3922 mpInputContext->Map( this );
3923 CallCallback( SalEvent::Resize, nullptr );
3924
3925 bool bSetFocus = m_bSetFocusOnMap;
3926
3927 /*
3928 * sometimes a message box/dialogue is brought up when a frame is not mapped
3929 * the corresponding TRANSIENT_FOR hint is then set to the root window
3930 * so that the dialogue shows in all cases. Correct it here if the
3931 * frame is shown afterwards.
3932 */
3933 if( ! IsChildWindow()
3934 && ! IsOverrideRedirect()
3935 && ! IsFloatGrabWindow()
3936 )
3937 {
3938 for (auto const& child : maChildren)
3939 {
3940 if( child->mbTransientForRoot )
3941 pDisplay_->getWMAdaptor()->changeReferenceFrame( child, this );
3942 }
3943 }
3944
3945 if( hPresentationWindow != None0L && GetShellWindow() == hPresentationWindow )
3946 XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent2, CurrentTime0L );
3947
3948 if( bSetFocus )
3949 {
3950 XSetInputFocus( GetXDisplay(),
3951 GetShellWindow(),
3952 RevertToParent2,
3953 CurrentTime0L );
3954 }
3955
3956 RestackChildren();
3957 m_bSetFocusOnMap = false;
3958 }
3959 break;
3960
3961 case UnmapNotify18:
3962 if( pEvent->xunmap.window == GetShellWindow() )
3963 {
3964 bMapped_ = false;
3965 bViewable_ = false;
3966 nRet = true;
3967 if ( mpInputContext != nullptr )
3968 mpInputContext->Unmap();
3969 CallCallback( SalEvent::Resize, nullptr );
3970 }
3971 break;
3972
3973 case ConfigureNotify22:
3974 if( pEvent->xconfigure.window == GetShellWindow()
3975 || pEvent->xconfigure.window == GetWindow() )
3976 nRet = HandleSizeEvent( &pEvent->xconfigure );
3977 break;
3978
3979 case VisibilityNotify15:
3980 nVisibility_ = pEvent->xvisibility.state;
3981 nRet = true;
3982 if( bAlwaysOnTop_
3983 && bMapped_
3984 && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK()
3985 && nVisibility_ != VisibilityUnobscured0 )
3986 maAlwaysOnTopRaiseTimer.Start();
3987 break;
3988
3989 case ReparentNotify21:
3990 nRet = HandleReparentEvent( &pEvent->xreparent );
3991 break;
3992
3993 case MappingNotify34:
3994 break;
3995
3996 case ColormapNotify32:
3997 nRet = false;
3998 break;
3999
4000 case PropertyNotify28:
4001 {
4002 if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) )
4003 nRet = HandleStateEvent( &pEvent->xproperty );
4004 else
4005 nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty );
4006 break;
4007 }
4008
4009 case ClientMessage33:
4010 nRet = HandleClientMessage( &pEvent->xclient );
4011 break;
4012 }
4013 }
4014 else
4015 {
4016 switch( pEvent->type )
4017 {
4018 case FocusIn9:
4019 case FocusOut10:
4020 if( ( nStyle_ & SalFrameStyleFlags::PLUG )
4021 && ( pEvent->xfocus.window == GetShellWindow()
4022 || pEvent->xfocus.window == GetForeignParent() )
4023 )
4024 {
4025 nRet = HandleFocusEvent( &pEvent->xfocus );
4026 }
4027 break;
4028
4029 case ConfigureNotify22:
4030 if( pEvent->xconfigure.window == GetForeignParent() ||
4031 pEvent->xconfigure.window == GetShellWindow() )
4032 nRet = HandleSizeEvent( &pEvent->xconfigure );
4033
4034 if( pEvent->xconfigure.window == GetStackingWindow() )
4035 nRet = HandleSizeEvent( &pEvent->xconfigure );
4036
4037 RestackChildren();
4038 break;
4039 }
4040 }
4041
4042 return nRet;
4043}
4044
4045void X11SalFrame::ResetClipRegion()
4046{
4047 m_vClipRectangles.clear();
4048
4049 const int dest_kind = ShapeBounding0;
4050 const int op = ShapeSet0;
4051 const int ordering = YSorted1;
4052
4053 XWindowAttributes win_attrib;
4054 XRectangle win_size;
4055
4056 ::Window aShapeWindow = mhShellWindow;
4057
4058 XGetWindowAttributes ( GetDisplay()->GetDisplay(),
4059 aShapeWindow,
4060 &win_attrib );
4061
4062 win_size.x = 0;
4063 win_size.y = 0;
4064 win_size.width = win_attrib.width;
4065 win_size.height = win_attrib.height;
4066
4067 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4068 aShapeWindow,
4069 dest_kind,
4070 0, 0, // x_off, y_off
4071 &win_size, // list of rectangles
4072 1, // number of rectangles
4073 op, ordering );
4074}
4075
4076void X11SalFrame::BeginSetClipRegion( sal_uInt32 /*nRects*/ )
4077{
4078 m_vClipRectangles.clear();
4079}
4080
4081void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
4082{
4083 m_vClipRectangles.emplace_back( XRectangle { static_cast<short>(nX), static_cast<short>(nY),
4084 static_cast<unsigned short>(nWidth), static_cast<unsigned short>(nHeight) } );
4085}
4086
4087void X11SalFrame::EndSetClipRegion()
4088{
4089 const int dest_kind = ShapeBounding0;
4090 const int ordering = YSorted1;
4091 const int op = ShapeSet0;
4092
4093 ::Window aShapeWindow = mhShellWindow;
4094 XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
4095 aShapeWindow,
4096 dest_kind,
4097 0, 0, // x_off, y_off
4098 m_vClipRectangles.data(),
4099 m_vClipRectangles.size(),
4100 op, ordering );
4101
4102}
4103
4104sal_uIntPtr X11SalFrame::GetNativeWindowHandle()
4105{
4106 return mhWindow;
4107}
4108
4109/* vim:set shiftwidth=4 softtabstop=4 expandtab: */