File: | home/maarten/src/libreoffice/core/vcl/source/window/window.cxx |
Warning: | line 1786, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <rtl/strbuf.hxx> | ||||||
21 | #include <sal/log.hxx> | ||||||
22 | |||||||
23 | #include <sal/types.h> | ||||||
24 | #include <vcl/salgtype.hxx> | ||||||
25 | #include <vcl/event.hxx> | ||||||
26 | #include <vcl/help.hxx> | ||||||
27 | #include <vcl/cursor.hxx> | ||||||
28 | #include <vcl/svapp.hxx> | ||||||
29 | #include <vcl/transfer.hxx> | ||||||
30 | #include <vcl/vclevent.hxx> | ||||||
31 | #include <vcl/window.hxx> | ||||||
32 | #include <vcl/syswin.hxx> | ||||||
33 | #include <vcl/dockwin.hxx> | ||||||
34 | #include <vcl/wall.hxx> | ||||||
35 | #include <vcl/toolkit/fixed.hxx> | ||||||
36 | #include <vcl/taskpanelist.hxx> | ||||||
37 | #include <vcl/toolkit/unowrap.hxx> | ||||||
38 | #include <vcl/lazydelete.hxx> | ||||||
39 | #include <vcl/virdev.hxx> | ||||||
40 | #include <vcl/settings.hxx> | ||||||
41 | #include <vcl/sysdata.hxx> | ||||||
42 | #include <vcl/ptrstyle.hxx> | ||||||
43 | #include <vcl/IDialogRenderable.hxx> | ||||||
44 | |||||||
45 | #include <vcl/uitest/uiobject.hxx> | ||||||
46 | |||||||
47 | #include <salframe.hxx> | ||||||
48 | #include <salobj.hxx> | ||||||
49 | #include <salinst.hxx> | ||||||
50 | #include <salgdi.hxx> | ||||||
51 | #include <svdata.hxx> | ||||||
52 | #include <window.h> | ||||||
53 | #include <toolbox.h> | ||||||
54 | #include <outdev.h> | ||||||
55 | #include <brdwin.hxx> | ||||||
56 | #include <helpwin.hxx> | ||||||
57 | |||||||
58 | #include <com/sun/star/accessibility/AccessibleRelation.hpp> | ||||||
59 | #include <com/sun/star/accessibility/XAccessible.hpp> | ||||||
60 | #include <com/sun/star/awt/XWindowPeer.hpp> | ||||||
61 | #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> | ||||||
62 | #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> | ||||||
63 | #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> | ||||||
64 | #include <com/sun/star/rendering/CanvasFactory.hpp> | ||||||
65 | #include <com/sun/star/rendering/XSpriteCanvas.hpp> | ||||||
66 | #include <comphelper/lok.hxx> | ||||||
67 | #include <comphelper/processfactory.hxx> | ||||||
68 | #include <unotools/configmgr.hxx> | ||||||
69 | #include <osl/diagnose.h> | ||||||
70 | #include <tools/debug.hxx> | ||||||
71 | #include <tools/json_writer.hxx> | ||||||
72 | #include <boost/property_tree/ptree.hpp> | ||||||
73 | |||||||
74 | #include <cassert> | ||||||
75 | #include <typeinfo> | ||||||
76 | |||||||
77 | #ifdef _WIN32 // see #140456# | ||||||
78 | #include <win/salframe.h> | ||||||
79 | #endif | ||||||
80 | |||||||
81 | |||||||
82 | using namespace ::com::sun::star::uno; | ||||||
83 | using namespace ::com::sun::star::lang; | ||||||
84 | using namespace ::com::sun::star::datatransfer::clipboard; | ||||||
85 | using namespace ::com::sun::star::datatransfer::dnd; | ||||||
86 | |||||||
87 | namespace vcl { | ||||||
88 | |||||||
89 | Window::Window( WindowType nType ) | ||||||
90 | : OutputDevice(OUTDEV_WINDOW) | ||||||
91 | , mpWindowImpl(new WindowImpl( nType )) | ||||||
92 | { | ||||||
93 | // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active | ||||||
94 | mbEnableRTL = AllSettings::GetLayoutRTL(); | ||||||
95 | } | ||||||
96 | |||||||
97 | Window::Window( vcl::Window* pParent, WinBits nStyle ) | ||||||
98 | : OutputDevice(OUTDEV_WINDOW) | ||||||
99 | , mpWindowImpl(new WindowImpl( WindowType::WINDOW )) | ||||||
100 | { | ||||||
101 | // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active | ||||||
102 | mbEnableRTL = AllSettings::GetLayoutRTL(); | ||||||
103 | |||||||
104 | ImplInit( pParent, nStyle, nullptr ); | ||||||
105 | } | ||||||
106 | |||||||
107 | #if OSL_DEBUG_LEVEL1 > 0 | ||||||
108 | namespace | ||||||
109 | { | ||||||
110 | OString lcl_createWindowInfo(const vcl::Window* pWindow) | ||||||
111 | { | ||||||
112 | // skip border windows, they do not carry information that | ||||||
113 | // would help with diagnosing the problem | ||||||
114 | const vcl::Window* pTempWin( pWindow ); | ||||||
115 | while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) { | ||||||
116 | pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild ); | ||||||
117 | } | ||||||
118 | // check if pTempWin is not null, otherwise use the | ||||||
119 | // original address | ||||||
120 | if ( pTempWin ) { | ||||||
121 | pWindow = pTempWin; | ||||||
122 | } | ||||||
123 | |||||||
124 | OStringBuffer aErrorString; | ||||||
125 | aErrorString.append(' '); | ||||||
126 | aErrorString.append(typeid( *pWindow ).name()); | ||||||
127 | aErrorString.append("("); | ||||||
128 | aErrorString.append( | ||||||
129 | OUStringToOString( | ||||||
130 | pWindow->GetText(), | ||||||
131 | RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) | ||||||
132 | ) | ||||||
133 | ); | ||||||
134 | aErrorString.append(")"); | ||||||
135 | return aErrorString.makeStringAndClear(); | ||||||
136 | } | ||||||
137 | } | ||||||
138 | #endif | ||||||
139 | |||||||
140 | bool Window::IsDisposed() const | ||||||
141 | { | ||||||
142 | return !mpWindowImpl; | ||||||
143 | } | ||||||
144 | |||||||
145 | void Window::dispose() | ||||||
146 | { | ||||||
147 | assert( mpWindowImpl )(static_cast <bool> (mpWindowImpl) ? void (0) : __assert_fail ("mpWindowImpl", "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 147, __extension__ __PRETTY_FUNCTION__)); | ||||||
148 | assert( !mpWindowImpl->mbInDispose )(static_cast <bool> (!mpWindowImpl->mbInDispose) ? void (0) : __assert_fail ("!mpWindowImpl->mbInDispose", "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 148, __extension__ __PRETTY_FUNCTION__)); // should only be called from disposeOnce() | ||||||
149 | assert( (!mpWindowImpl->mpParent ||(static_cast <bool> ((!mpWindowImpl->mpParent || !mpWindowImpl ->mpParent->IsDisposed()) && "vcl::Window child should have its parent disposed first" ) ? void (0) : __assert_fail ("(!mpWindowImpl->mpParent || !mpWindowImpl->mpParent->IsDisposed()) && \"vcl::Window child should have its parent disposed first\"" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 151, __extension__ __PRETTY_FUNCTION__)) | ||||||
150 | !mpWindowImpl->mpParent->IsDisposed()) &&(static_cast <bool> ((!mpWindowImpl->mpParent || !mpWindowImpl ->mpParent->IsDisposed()) && "vcl::Window child should have its parent disposed first" ) ? void (0) : __assert_fail ("(!mpWindowImpl->mpParent || !mpWindowImpl->mpParent->IsDisposed()) && \"vcl::Window child should have its parent disposed first\"" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 151, __extension__ __PRETTY_FUNCTION__)) | ||||||
151 | "vcl::Window child should have its parent disposed first" )(static_cast <bool> ((!mpWindowImpl->mpParent || !mpWindowImpl ->mpParent->IsDisposed()) && "vcl::Window child should have its parent disposed first" ) ? void (0) : __assert_fail ("(!mpWindowImpl->mpParent || !mpWindowImpl->mpParent->IsDisposed()) && \"vcl::Window child should have its parent disposed first\"" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 151, __extension__ __PRETTY_FUNCTION__)); | ||||||
152 | |||||||
153 | // remove Key and Mouse events issued by Application::PostKey/MouseEvent | ||||||
154 | Application::RemoveMouseAndKeyEvents( this ); | ||||||
155 | |||||||
156 | // Dispose of the canvas implementation (which, currently, has an | ||||||
157 | // own wrapper window as a child to this one. | ||||||
158 | Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas ); | ||||||
159 | if( xCanvas.is() ) | ||||||
160 | { | ||||||
161 | Reference < XComponent > xCanvasComponent( xCanvas, UNO_QUERY ); | ||||||
162 | if( xCanvasComponent.is() ) | ||||||
163 | xCanvasComponent->dispose(); | ||||||
164 | } | ||||||
165 | |||||||
166 | mpWindowImpl->mbInDispose = true; | ||||||
167 | |||||||
168 | CallEventListeners( VclEventId::ObjectDying ); | ||||||
169 | |||||||
170 | // do not send child events for frames that were registered as native frames | ||||||
171 | if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible ) | ||||||
172 | if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() ) | ||||||
173 | GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this ); | ||||||
174 | |||||||
175 | // remove associated data structures from dockingmanager | ||||||
176 | ImplGetDockingManager()->RemoveWindow( this ); | ||||||
177 | |||||||
178 | // remove ownerdraw decorated windows from list in the top-most frame window | ||||||
179 | if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame ) | ||||||
180 | { | ||||||
181 | ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList(); | ||||||
182 | auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) ); | ||||||
183 | if( p != rList.end() ) | ||||||
184 | rList.erase( p ); | ||||||
185 | } | ||||||
186 | |||||||
187 | // shutdown drag and drop | ||||||
188 | Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY ); | ||||||
189 | |||||||
190 | if( xDnDComponent.is() ) | ||||||
191 | xDnDComponent->dispose(); | ||||||
192 | |||||||
193 | if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData ) | ||||||
194 | { | ||||||
195 | try | ||||||
196 | { | ||||||
197 | // deregister drop target listener | ||||||
198 | if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() ) | ||||||
199 | { | ||||||
200 | Reference< XDragGestureRecognizer > xDragGestureRecognizer(mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY); | ||||||
201 | if( xDragGestureRecognizer.is() ) | ||||||
202 | { | ||||||
203 | xDragGestureRecognizer->removeDragGestureListener( | ||||||
204 | Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY)); | ||||||
205 | } | ||||||
206 | |||||||
207 | mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener ); | ||||||
208 | mpWindowImpl->mpFrameData->mxDropTargetListener.clear(); | ||||||
209 | } | ||||||
210 | |||||||
211 | // shutdown drag and drop for this frame window | ||||||
212 | Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY ); | ||||||
213 | |||||||
214 | // DNDEventDispatcher does not hold a reference of the DropTarget, | ||||||
215 | // so it's ok if it does not support XComponent | ||||||
216 | if( xComponent.is() ) | ||||||
217 | xComponent->dispose(); | ||||||
218 | } | ||||||
219 | catch (const Exception&) | ||||||
220 | { | ||||||
221 | // can be safely ignored here. | ||||||
222 | } | ||||||
223 | } | ||||||
224 | |||||||
225 | UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false ); | ||||||
226 | if ( pWrapper ) | ||||||
227 | pWrapper->WindowDestroyed( this ); | ||||||
228 | |||||||
229 | // MT: Must be called after WindowDestroyed! | ||||||
230 | // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again! | ||||||
231 | // But accessibility implementations from applications need this dispose. | ||||||
232 | if ( mpWindowImpl->mxAccessible.is() ) | ||||||
233 | { | ||||||
234 | Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY ); | ||||||
235 | if ( xC.is() ) | ||||||
236 | xC->dispose(); | ||||||
237 | } | ||||||
238 | |||||||
239 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
240 | |||||||
241 | if ( ImplGetSVHelpData().mpHelpWin && (ImplGetSVHelpData().mpHelpWin->GetParent() == this) ) | ||||||
242 | ImplDestroyHelpWindow( true ); | ||||||
243 | |||||||
244 | SAL_WARN_IF(pSVData->mpWinData->mpTrackWin.get() == this, "vcl.window",do { if (true && (pSVData->mpWinData->mpTrackWin .get() == this)) { 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() << "Window::~Window(): Window is in TrackingMode" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window is in TrackingMode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window is in TrackingMode"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::~Window(): Window is in TrackingMode") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window is in TrackingMode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window is in TrackingMode"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||
245 | "Window::~Window(): Window is in TrackingMode")do { if (true && (pSVData->mpWinData->mpTrackWin .get() == this)) { 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() << "Window::~Window(): Window is in TrackingMode" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window is in TrackingMode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window is in TrackingMode"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::~Window(): Window is in TrackingMode") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window is in TrackingMode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window is in TrackingMode"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "245" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
246 | SAL_WARN_IF(IsMouseCaptured(), "vcl.window",do { if (true && (IsMouseCaptured())) { 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() << "Window::~Window(): Window has the mouse captured" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window has the mouse captured" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window has the mouse captured"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::~Window(): Window has the mouse captured" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window has the mouse captured" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window has the mouse captured"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||
247 | "Window::~Window(): Window has the mouse captured")do { if (true && (IsMouseCaptured())) { 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() << "Window::~Window(): Window has the mouse captured" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window has the mouse captured" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window has the mouse captured"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::~Window(): Window has the mouse captured" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window(): Window has the mouse captured" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window(): Window has the mouse captured"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "247" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
248 | |||||||
249 | // due to old compatibility | ||||||
250 | if (pSVData->mpWinData->mpTrackWin == this) | ||||||
251 | EndTracking(); | ||||||
252 | if (IsMouseCaptured()) | ||||||
253 | ReleaseMouse(); | ||||||
254 | |||||||
255 | #if OSL_DEBUG_LEVEL1 > 0 | ||||||
256 | // always perform these tests in debug builds | ||||||
257 | { | ||||||
258 | OStringBuffer aErrorStr; | ||||||
259 | bool bError = false; | ||||||
260 | vcl::Window* pTempWin; | ||||||
261 | |||||||
262 | if ( mpWindowImpl->mpFirstChild ) | ||||||
263 | { | ||||||
264 | OStringBuffer aTempStr("Window ("); | ||||||
265 | aTempStr.append(lcl_createWindowInfo(this)); | ||||||
266 | aTempStr.append(") with live children destroyed: "); | ||||||
267 | pTempWin = mpWindowImpl->mpFirstChild; | ||||||
268 | while ( pTempWin ) | ||||||
269 | { | ||||||
270 | aTempStr.append(lcl_createWindowInfo(pTempWin)); | ||||||
271 | pTempWin = pTempWin->mpWindowImpl->mpNext; | ||||||
272 | } | ||||||
273 | OSL_FAIL( aTempStr.getStr() )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "273" ": "), "%s", aTempStr.getStr()); } } while (false); | ||||||
274 | Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))); // abort in debug builds, this must be fixed! | ||||||
275 | } | ||||||
276 | |||||||
277 | if (mpWindowImpl->mpFrameData != nullptr) | ||||||
278 | { | ||||||
279 | pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap; | ||||||
280 | while ( pTempWin ) | ||||||
281 | { | ||||||
282 | if ( ImplIsRealParentPath( pTempWin ) ) | ||||||
283 | { | ||||||
284 | bError = true; | ||||||
285 | aErrorStr.append(lcl_createWindowInfo(pTempWin)); | ||||||
286 | } | ||||||
287 | pTempWin = pTempWin->mpWindowImpl->mpNextOverlap; | ||||||
288 | } | ||||||
289 | if ( bError ) | ||||||
290 | { | ||||||
291 | OStringBuffer aTempStr; | ||||||
292 | aTempStr.append("Window ("); | ||||||
293 | aTempStr.append(lcl_createWindowInfo(this)); | ||||||
294 | aTempStr.append(") with live SystemWindows destroyed: "); | ||||||
295 | aTempStr.append(aErrorStr.toString()); | ||||||
296 | OSL_FAIL(aTempStr.getStr())do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "296" ": "), "%s", aTempStr.getStr()); } } while (false); | ||||||
297 | // abort in debug builds, must be fixed! | ||||||
298 | Application::Abort(OStringToOUString( | ||||||
299 | aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))); | ||||||
300 | } | ||||||
301 | } | ||||||
302 | |||||||
303 | bError = false; | ||||||
304 | pTempWin = pSVData->maFrameData.mpFirstFrame; | ||||||
305 | while ( pTempWin ) | ||||||
306 | { | ||||||
307 | if ( ImplIsRealParentPath( pTempWin ) ) | ||||||
308 | { | ||||||
309 | bError = true; | ||||||
310 | aErrorStr.append(lcl_createWindowInfo(pTempWin)); | ||||||
311 | } | ||||||
312 | pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
313 | } | ||||||
314 | if ( bError ) | ||||||
315 | { | ||||||
316 | OStringBuffer aTempStr( "Window (" ); | ||||||
317 | aTempStr.append(lcl_createWindowInfo(this)); | ||||||
318 | aTempStr.append(") with live SystemWindows destroyed: "); | ||||||
319 | aTempStr.append(aErrorStr.toString()); | ||||||
320 | OSL_FAIL( aTempStr.getStr() )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "320" ": "), "%s", aTempStr.getStr()); } } while (false); | ||||||
321 | Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))); // abort in debug builds, this must be fixed! | ||||||
322 | } | ||||||
323 | |||||||
324 | if ( mpWindowImpl->mpFirstOverlap ) | ||||||
325 | { | ||||||
326 | OStringBuffer aTempStr("Window ("); | ||||||
327 | aTempStr.append(lcl_createWindowInfo(this)); | ||||||
328 | aTempStr.append(") with live SystemWindows destroyed: "); | ||||||
329 | pTempWin = mpWindowImpl->mpFirstOverlap; | ||||||
330 | while ( pTempWin ) | ||||||
331 | { | ||||||
332 | aTempStr.append(lcl_createWindowInfo(pTempWin)); | ||||||
333 | pTempWin = pTempWin->mpWindowImpl->mpNext; | ||||||
334 | } | ||||||
335 | OSL_FAIL( aTempStr.getStr() )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "335" ": "), "%s", aTempStr.getStr()); } } while (false); | ||||||
336 | Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))); // abort in debug builds, this must be fixed! | ||||||
337 | } | ||||||
338 | |||||||
339 | vcl::Window* pMyParent = GetParent(); | ||||||
340 | SystemWindow* pMySysWin = nullptr; | ||||||
341 | |||||||
342 | while ( pMyParent ) | ||||||
343 | { | ||||||
344 | if ( pMyParent->IsSystemWindow() ) | ||||||
345 | { | ||||||
346 | pMySysWin = dynamic_cast<SystemWindow *>(pMyParent); | ||||||
347 | } | ||||||
348 | pMyParent = pMyParent->GetParent(); | ||||||
349 | } | ||||||
350 | if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) ) | ||||||
351 | { | ||||||
352 | OStringBuffer aTempStr("Window ("); | ||||||
353 | aTempStr.append(lcl_createWindowInfo(this)); | ||||||
354 | aTempStr.append(") still in TaskPanelList!"); | ||||||
355 | OSL_FAIL( aTempStr.getStr() )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "355" ": "), "%s", aTempStr.getStr()); } } while (false); | ||||||
356 | Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))); // abort in debug builds, this must be fixed! | ||||||
357 | } | ||||||
358 | } | ||||||
359 | #endif | ||||||
360 | |||||||
361 | if( mpWindowImpl->mbIsInTaskPaneList ) | ||||||
362 | { | ||||||
363 | vcl::Window* pMyParent = GetParent(); | ||||||
364 | SystemWindow* pMySysWin = nullptr; | ||||||
365 | |||||||
366 | while ( pMyParent ) | ||||||
367 | { | ||||||
368 | if ( pMyParent->IsSystemWindow() ) | ||||||
369 | { | ||||||
370 | pMySysWin = dynamic_cast<SystemWindow *>(pMyParent); | ||||||
371 | } | ||||||
372 | pMyParent = pMyParent->GetParent(); | ||||||
373 | } | ||||||
374 | if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) ) | ||||||
375 | { | ||||||
376 | pMySysWin->GetTaskPaneList()->RemoveWindow( this ); | ||||||
377 | } | ||||||
378 | else | ||||||
379 | { | ||||||
380 | SAL_WARN( "vcl", "Window (" << GetText() << ") not found in TaskPanelList")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 () << "Window (" << GetText() << ") not found in TaskPanelList" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "380" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window (" << GetText() << ") not found in TaskPanelList"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window (" << GetText() << ") not found in TaskPanelList"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "380" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window (" << GetText() << ") not found in TaskPanelList" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "380" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window (" << GetText() << ") not found in TaskPanelList"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window (" << GetText() << ") not found in TaskPanelList"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "380" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
381 | } | ||||||
382 | } | ||||||
383 | |||||||
384 | // remove from size-group if necessary | ||||||
385 | remove_from_all_size_groups(); | ||||||
386 | |||||||
387 | // clear mnemonic labels | ||||||
388 | std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels()); | ||||||
389 | for (auto const& mnemonicLabel : aMnemonicLabels) | ||||||
390 | { | ||||||
391 | remove_mnemonic_label(mnemonicLabel); | ||||||
392 | } | ||||||
393 | |||||||
394 | // hide window in order to trigger the Paint-Handling | ||||||
395 | Hide(); | ||||||
396 | |||||||
397 | // EndExtTextInputMode | ||||||
398 | if (pSVData->mpWinData->mpExtTextInputWin == this) | ||||||
399 | { | ||||||
400 | EndExtTextInput(); | ||||||
401 | if (pSVData->mpWinData->mpExtTextInputWin == this) | ||||||
402 | pSVData->mpWinData->mpExtTextInputWin = nullptr; | ||||||
403 | } | ||||||
404 | |||||||
405 | // check if the focus window is our child | ||||||
406 | bool bHasFocusedChild = false; | ||||||
407 | if (pSVData->mpWinData->mpFocusWin && ImplIsRealParentPath(pSVData->mpWinData->mpFocusWin)) | ||||||
408 | { | ||||||
409 | // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below | ||||||
410 | bHasFocusedChild = true; | ||||||
411 | #if OSL_DEBUG_LEVEL1 > 0 | ||||||
412 | OUString aTempStr = "Window (" + GetText() + | ||||||
413 | ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !"; | ||||||
414 | SAL_WARN( "vcl", aTempStr )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 () << aTempStr) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "414" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << aTempStr), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << aTempStr; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "414" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << aTempStr) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "414" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << aTempStr), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << aTempStr; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "414" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
415 | Application::Abort(aTempStr); // abort in debug build version, this must be fixed! | ||||||
416 | #endif | ||||||
417 | } | ||||||
418 | |||||||
419 | // if we get focus pass focus to another window | ||||||
420 | vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow(); | ||||||
421 | if (pSVData->mpWinData->mpFocusWin == this | ||||||
422 | || bHasFocusedChild) // #122232#, see above, try some cleanup | ||||||
423 | { | ||||||
424 | if ( mpWindowImpl->mbFrame ) | ||||||
425 | { | ||||||
426 | pSVData->mpWinData->mpFocusWin = nullptr; | ||||||
427 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr; | ||||||
428 | } | ||||||
429 | else | ||||||
430 | { | ||||||
431 | vcl::Window* pParent = GetParent(); | ||||||
432 | vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow; | ||||||
433 | // when windows overlap, give focus to the parent | ||||||
434 | // of the next FrameWindow | ||||||
435 | if ( pBorderWindow ) | ||||||
436 | { | ||||||
437 | if ( pBorderWindow->ImplIsOverlapWindow() ) | ||||||
438 | pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow; | ||||||
439 | } | ||||||
440 | else if ( ImplIsOverlapWindow() ) | ||||||
441 | pParent = mpWindowImpl->mpOverlapWindow; | ||||||
442 | |||||||
443 | if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() ) | ||||||
444 | pParent->GrabFocus(); | ||||||
445 | else | ||||||
446 | mpWindowImpl->mpFrameWindow->GrabFocus(); | ||||||
447 | |||||||
448 | // If the focus was set back to 'this' set it to nothing | ||||||
449 | if (pSVData->mpWinData->mpFocusWin == this) | ||||||
450 | { | ||||||
451 | pSVData->mpWinData->mpFocusWin = nullptr; | ||||||
452 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr; | ||||||
453 | } | ||||||
454 | } | ||||||
455 | } | ||||||
456 | |||||||
457 | if ( pOverlapWindow != nullptr && | ||||||
458 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this ) | ||||||
459 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr; | ||||||
460 | |||||||
461 | // reset hint for DefModalDialogParent | ||||||
462 | if( pSVData->maFrameData.mpActiveApplicationFrame == this ) | ||||||
463 | pSVData->maFrameData.mpActiveApplicationFrame = nullptr; | ||||||
464 | |||||||
465 | // reset hint of what was the last wheeled window | ||||||
466 | if (pSVData->mpWinData->mpLastWheelWindow == this) | ||||||
467 | pSVData->mpWinData->mpLastWheelWindow = nullptr; | ||||||
468 | |||||||
469 | // reset marked windows | ||||||
470 | if ( mpWindowImpl->mpFrameData != nullptr ) | ||||||
471 | { | ||||||
472 | if ( mpWindowImpl->mpFrameData->mpFocusWin == this ) | ||||||
473 | mpWindowImpl->mpFrameData->mpFocusWin = nullptr; | ||||||
474 | if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this ) | ||||||
475 | mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr; | ||||||
476 | if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this ) | ||||||
477 | mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr; | ||||||
478 | } | ||||||
479 | |||||||
480 | // reset Deactivate-Window | ||||||
481 | if (pSVData->mpWinData->mpLastDeacWin == this) | ||||||
482 | pSVData->mpWinData->mpLastDeacWin = nullptr; | ||||||
483 | |||||||
484 | if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData ) | ||||||
485 | { | ||||||
486 | if ( mpWindowImpl->mpFrameData->mnFocusId ) | ||||||
487 | Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId ); | ||||||
488 | mpWindowImpl->mpFrameData->mnFocusId = nullptr; | ||||||
489 | if ( mpWindowImpl->mpFrameData->mnMouseMoveId ) | ||||||
490 | Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId ); | ||||||
491 | mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr; | ||||||
492 | } | ||||||
493 | |||||||
494 | // release SalGraphics | ||||||
495 | OutputDevice *pOutDev = GetOutDev(); | ||||||
496 | pOutDev->ReleaseGraphics(); | ||||||
497 | |||||||
498 | // remove window from the lists | ||||||
499 | ImplRemoveWindow( true ); | ||||||
500 | |||||||
501 | // de-register as "top window child" at our parent, if necessary | ||||||
502 | if ( mpWindowImpl->mbFrame ) | ||||||
503 | { | ||||||
504 | bool bIsTopWindow | ||||||
505 | = mpWindowImpl->mpWinData && (mpWindowImpl->mpWinData->mnIsTopWindow == 1); | ||||||
506 | if ( mpWindowImpl->mpRealParent && bIsTopWindow ) | ||||||
507 | { | ||||||
508 | ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData(); | ||||||
509 | |||||||
510 | auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(), | ||||||
511 | pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) ); | ||||||
512 | SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" )do { if (true && (myPos == pParentWinData->maTopWindowChildren .end())) { 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() << "Window::~Window: inconsistency in top window chain!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "512" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window: inconsistency in top window chain!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window: inconsistency in top window chain!" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "512" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::~Window: inconsistency in top window chain!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "512" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::~Window: inconsistency in top window chain!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::~Window: inconsistency in top window chain!" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "512" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
513 | if ( myPos != pParentWinData->maTopWindowChildren.end() ) | ||||||
514 | pParentWinData->maTopWindowChildren.erase( myPos ); | ||||||
515 | } | ||||||
516 | } | ||||||
517 | |||||||
518 | delete mpWindowImpl->mpWinData; | ||||||
519 | mpWindowImpl->mpWinData = nullptr; | ||||||
520 | |||||||
521 | // remove BorderWindow or Frame window data | ||||||
522 | mpWindowImpl->mpBorderWindow.disposeAndClear(); | ||||||
523 | if ( mpWindowImpl->mbFrame ) | ||||||
524 | { | ||||||
525 | if ( pSVData->maFrameData.mpFirstFrame == this ) | ||||||
526 | pSVData->maFrameData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
527 | else | ||||||
528 | { | ||||||
529 | sal_Int32 nWindows = 0; | ||||||
530 | vcl::Window* pSysWin = pSVData->maFrameData.mpFirstFrame; | ||||||
531 | while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this ) | ||||||
532 | { | ||||||
533 | pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
534 | nWindows++; | ||||||
535 | } | ||||||
536 | |||||||
537 | if ( pSysWin ) | ||||||
538 | { | ||||||
539 | assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin)(static_cast <bool> (mpWindowImpl->mpFrameData->mpNextFrame .get() != pSysWin) ? void (0) : __assert_fail ("mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 539, __extension__ __PRETTY_FUNCTION__)); | ||||||
540 | pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
541 | } | ||||||
542 | else // if it is not in the list, we can't remove it. | ||||||
543 | SAL_WARN("vcl.window", "Window " << this << " marked as frame 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() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||
544 | "is missing from list of " << nWindows << " frames")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() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "544" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
545 | } | ||||||
546 | if (mpWindowImpl->mpFrame) // otherwise exception during init | ||||||
547 | { | ||||||
548 | mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr ); | ||||||
549 | pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame ); | ||||||
550 | } | ||||||
551 | assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr)(static_cast <bool> (mpWindowImpl->mpFrameData->mnFocusId == nullptr) ? void (0) : __assert_fail ("mpWindowImpl->mpFrameData->mnFocusId == nullptr" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 551, __extension__ __PRETTY_FUNCTION__)); | ||||||
552 | assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr)(static_cast <bool> (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr) ? void (0) : __assert_fail ("mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 552, __extension__ __PRETTY_FUNCTION__)); | ||||||
553 | |||||||
554 | mpWindowImpl->mpFrameData->mpBuffer.disposeAndClear(); | ||||||
555 | delete mpWindowImpl->mpFrameData; | ||||||
556 | mpWindowImpl->mpFrameData = nullptr; | ||||||
557 | } | ||||||
558 | |||||||
559 | // should be the last statements | ||||||
560 | mpWindowImpl.reset(); | ||||||
561 | |||||||
562 | OutputDevice::dispose(); | ||||||
563 | } | ||||||
564 | |||||||
565 | Window::~Window() | ||||||
566 | { | ||||||
567 | disposeOnce(); | ||||||
568 | } | ||||||
569 | |||||||
570 | // We will eventually being removing the inheritance of OutputDevice | ||||||
571 | // from Window. It will be replaced with a transient relationship such | ||||||
572 | // that the OutputDevice is only live for the scope of the Paint method. | ||||||
573 | // In the meantime this can help move us towards a Window use an | ||||||
574 | // OutputDevice, not being one. | ||||||
575 | |||||||
576 | ::OutputDevice const* Window::GetOutDev() const | ||||||
577 | { | ||||||
578 | return this; | ||||||
579 | } | ||||||
580 | |||||||
581 | ::OutputDevice* Window::GetOutDev() | ||||||
582 | { | ||||||
583 | return this; | ||||||
584 | } | ||||||
585 | |||||||
586 | Color Window::GetBackgroundColor() const | ||||||
587 | { | ||||||
588 | return GetDisplayBackground().GetColor(); | ||||||
589 | } | ||||||
590 | |||||||
591 | } /* namespace vcl */ | ||||||
592 | |||||||
593 | WindowImpl::WindowImpl( WindowType nType ) | ||||||
594 | { | ||||||
595 | maZoom = Fraction( 1, 1 ); | ||||||
596 | maWinRegion = vcl::Region(true); | ||||||
597 | maWinClipRegion = vcl::Region(true); | ||||||
598 | mpWinData = nullptr; // Extra Window Data, that we don't need for all windows | ||||||
599 | mpFrameData = nullptr; // Frame Data | ||||||
600 | mpFrame = nullptr; // Pointer to frame window | ||||||
601 | mpSysObj = nullptr; | ||||||
602 | mpFrameWindow = nullptr; // window to top level parent (same as frame window) | ||||||
603 | mpOverlapWindow = nullptr; // first overlap parent | ||||||
604 | mpBorderWindow = nullptr; // Border-Window | ||||||
605 | mpClientWindow = nullptr; // Client-Window of a FrameWindow | ||||||
606 | mpParent = nullptr; // parent (incl. BorderWindow) | ||||||
607 | mpRealParent = nullptr; // real parent (excl. BorderWindow) | ||||||
608 | mpFirstChild = nullptr; // first child window | ||||||
609 | mpLastChild = nullptr; // last child window | ||||||
610 | mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows) | ||||||
611 | mpLastOverlap = nullptr; // last overlap window (only set in overlap windows) | ||||||
612 | mpPrev = nullptr; // prev window | ||||||
613 | mpNext = nullptr; // next window | ||||||
614 | mpNextOverlap = nullptr; // next overlap window of frame | ||||||
615 | mpLastFocusWindow = nullptr; // window for focus restore | ||||||
616 | mpDlgCtrlDownWindow = nullptr; // window for dialog control | ||||||
617 | mnEventListenersIteratingCount = 0; | ||||||
618 | mnChildEventListenersIteratingCount = 0; | ||||||
619 | mpCursor = nullptr; // cursor | ||||||
620 | maPointer = PointerStyle::Arrow; | ||||||
621 | mpVCLXWindow = nullptr; | ||||||
622 | mpAccessibleInfos = nullptr; | ||||||
623 | maControlForeground = COL_TRANSPARENT; // no foreground set | ||||||
624 | maControlBackground = COL_TRANSPARENT; // no background set | ||||||
625 | mnLeftBorder = 0; // left border | ||||||
626 | mnTopBorder = 0; // top border | ||||||
627 | mnRightBorder = 0; // right border | ||||||
628 | mnBottomBorder = 0; // bottom border | ||||||
629 | mnWidthRequest = -1; // width request | ||||||
630 | mnHeightRequest = -1; // height request | ||||||
631 | mnOptimalWidthCache = -1; // optimal width cache | ||||||
632 | mnOptimalHeightCache = -1; // optimal height cache | ||||||
633 | mnX = 0; // X-Position to Parent | ||||||
634 | mnY = 0; // Y-Position to Parent | ||||||
635 | mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning | ||||||
636 | mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren | ||||||
637 | mpPaintRegion = nullptr; // Paint-ClipRegion | ||||||
638 | mnStyle = 0; // style (init in ImplInitWindow) | ||||||
639 | mnPrevStyle = 0; // prevstyle (set in SetStyle) | ||||||
640 | mnExtendedStyle = WindowExtendedStyle::NONE; // extended style (init in ImplInitWindow) | ||||||
641 | mnType = nType; // type | ||||||
642 | mnGetFocusFlags = GetFocusFlags::NONE; // Flags for GetFocus()-Call | ||||||
643 | mnWaitCount = 0; // Wait-Count (>1 == "wait" mouse pointer) | ||||||
644 | mnPaintFlags = ImplPaintFlags::NONE; // Flags for ImplCallPaint | ||||||
645 | mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode | ||||||
646 | mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows | ||||||
647 | mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags | ||||||
648 | meAlwaysInputMode = AlwaysInputNone; // AlwaysEnableInput not called | ||||||
649 | meHalign = VclAlign::Fill; | ||||||
650 | meValign = VclAlign::Fill; | ||||||
651 | mePackType = VclPackType::Start; | ||||||
652 | mnPadding = 0; | ||||||
653 | mnGridHeight = 1; | ||||||
654 | mnGridLeftAttach = -1; | ||||||
655 | mnGridTopAttach = -1; | ||||||
656 | mnGridWidth = 1; | ||||||
657 | mnBorderWidth = 0; | ||||||
658 | mnMarginLeft = 0; | ||||||
659 | mnMarginRight = 0; | ||||||
660 | mnMarginTop = 0; | ||||||
661 | mnMarginBottom = 0; | ||||||
662 | mbFrame = false; // true: Window is a frame window | ||||||
663 | mbBorderWin = false; // true: Window is a border window | ||||||
664 | mbOverlapWin = false; // true: Window is an overlap window | ||||||
665 | mbSysWin = false; // true: SystemWindow is the base class | ||||||
666 | mbDialog = false; // true: Dialog is the base class | ||||||
667 | mbDockWin = false; // true: DockingWindow is the base class | ||||||
668 | mbFloatWin = false; // true: FloatingWindow is the base class | ||||||
669 | mbPushButton = false; // true: PushButton is the base class | ||||||
670 | mbToolBox = false; // true: ToolBox is the base class | ||||||
671 | mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class | ||||||
672 | mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars | ||||||
673 | mbSplitter = false; // true: Splitter is the base class | ||||||
674 | mbVisible = false; // true: Show( true ) called | ||||||
675 | mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow() | ||||||
676 | mbDisabled = false; // true: Enable( false ) called | ||||||
677 | mbInputDisabled = false; // true: EnableInput( false ) called | ||||||
678 | mbNoUpdate = false; // true: SetUpdateMode( false ) called | ||||||
679 | mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called | ||||||
680 | mbActive = false; // true: Window Active | ||||||
681 | mbReallyVisible = false; // true: this and all parents to an overlapped window are visible | ||||||
682 | mbReallyShown = false; // true: this and all parents to an overlapped window are shown | ||||||
683 | mbInInitShow = false; // true: we are in InitShow | ||||||
684 | mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer | ||||||
685 | mbNoPtrVisible = false; // true: ShowPointer( false ) called | ||||||
686 | mbPaintFrame = false; // true: Paint is visible, but not painted | ||||||
687 | mbInPaint = false; // true: Inside PaintHdl | ||||||
688 | mbMouseButtonDown = false; // true: BaseMouseButtonDown called | ||||||
689 | mbMouseButtonUp = false; // true: BaseMouseButtonUp called | ||||||
690 | mbKeyInput = false; // true: BaseKeyInput called | ||||||
691 | mbKeyUp = false; // true: BaseKeyUp called | ||||||
692 | mbCommand = false; // true: BaseCommand called | ||||||
693 | mbDefPos = true; // true: Position is not Set | ||||||
694 | mbDefSize = true; // true: Size is not Set | ||||||
695 | mbCallMove = true; // true: Move must be called by Show | ||||||
696 | mbCallResize = true; // true: Resize must be called by Show | ||||||
697 | mbWaitSystemResize = true; // true: Wait for System-Resize | ||||||
698 | mbInitWinClipRegion = true; // true: Calc Window Clip Region | ||||||
699 | mbInitChildRegion = false; // true: InitChildClipRegion | ||||||
700 | mbWinRegion = false; // true: Window Region | ||||||
701 | mbClipChildren = false; // true: Child-window should be clipped | ||||||
702 | mbClipSiblings = false; // true: Adjacent Child-window should be clipped | ||||||
703 | mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN) | ||||||
704 | mbPaintTransparent = false; // true: Paints should be executed on the Parent | ||||||
705 | mbMouseTransparent = false; // true: Window is transparent for Mouse | ||||||
706 | mbDlgCtrlStart = false; // true: From here on own Dialog-Control | ||||||
707 | mbFocusVisible = false; // true: Focus Visible | ||||||
708 | mbUseNativeFocus = false; | ||||||
709 | mbNativeFocusVisible = false; // true: native Focus Visible | ||||||
710 | mbInShowFocus = false; // prevent recursion | ||||||
711 | mbInHideFocus = false; // prevent recursion | ||||||
712 | mbTrackVisible = false; // true: Tracking Visible | ||||||
713 | mbControlForeground = false; // true: Foreground-Property set | ||||||
714 | mbControlBackground = false; // true: Background-Property set | ||||||
715 | mbAlwaysOnTop = false; // true: always visible for all others windows | ||||||
716 | mbCompoundControl = false; // true: Composite Control => Listener... | ||||||
717 | mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere | ||||||
718 | mbPaintDisabled = false; // true: Paint should not be executed | ||||||
719 | mbAllResize = false; // true: Also sent ResizeEvents with 0,0 | ||||||
720 | mbInDispose = false; // true: We're still in Window::dispose() | ||||||
721 | mbExtTextInput = false; // true: ExtTextInput-Mode is active | ||||||
722 | mbInFocusHdl = false; // true: Within GetFocus-Handler | ||||||
723 | mbCreatedWithToolkit = false; | ||||||
724 | mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events | ||||||
725 | mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection | ||||||
726 | mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window | ||||||
727 | mnNativeBackground = ControlPart::NONE; // initialize later, depends on type | ||||||
728 | mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case | ||||||
729 | mbFakeFocusSet = false; // true: pretend as if the window has focus. | ||||||
730 | mbHexpand = false; | ||||||
731 | mbVexpand = false; | ||||||
732 | mbExpand = false; | ||||||
733 | mbFill = true; | ||||||
734 | mbSecondary = false; | ||||||
735 | mbNonHomogeneous = false; | ||||||
736 | static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE"); | ||||||
737 | mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext | ||||||
738 | mpLOKNotifier = nullptr; | ||||||
739 | mnLOKWindowId = 0; | ||||||
740 | mbLOKParentNotifier = false; | ||||||
741 | } | ||||||
742 | |||||||
743 | WindowImpl::~WindowImpl() | ||||||
744 | { | ||||||
745 | mpChildClipRegion.reset(); | ||||||
746 | mpAccessibleInfos.reset(); | ||||||
747 | } | ||||||
748 | |||||||
749 | ImplWinData::ImplWinData() : | ||||||
750 | mnCursorExtWidth(0), | ||||||
751 | mbVertical(false), | ||||||
752 | mnCompositionCharRects(0), | ||||||
753 | mnTrackFlags(ShowTrackFlags::NONE), | ||||||
754 | mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow()) | ||||||
755 | mbMouseOver(false), | ||||||
756 | mbEnableNativeWidget(false) | ||||||
757 | { | ||||||
758 | } | ||||||
759 | |||||||
760 | ImplWinData::~ImplWinData() | ||||||
761 | { | ||||||
762 | mpCompositionCharRects.reset(); | ||||||
763 | } | ||||||
764 | |||||||
765 | ImplFrameData::ImplFrameData( vcl::Window *pWindow ) | ||||||
766 | { | ||||||
767 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
768 | assert (pSVData->maFrameData.mpFirstFrame.get() != pWindow)(static_cast <bool> (pSVData->maFrameData.mpFirstFrame .get() != pWindow) ? void (0) : __assert_fail ("pSVData->maFrameData.mpFirstFrame.get() != pWindow" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 768, __extension__ __PRETTY_FUNCTION__)); | ||||||
769 | mpNextFrame = pSVData->maFrameData.mpFirstFrame; | ||||||
770 | pSVData->maFrameData.mpFirstFrame = pWindow; | ||||||
771 | mpFirstOverlap = nullptr; | ||||||
772 | mpFocusWin = nullptr; | ||||||
773 | mpMouseMoveWin = nullptr; | ||||||
774 | mpMouseDownWin = nullptr; | ||||||
775 | mxFontCollection = pSVData->maGDIData.mxScreenFontList; | ||||||
776 | mxFontCache = pSVData->maGDIData.mxScreenFontCache; | ||||||
777 | mnFocusId = nullptr; | ||||||
778 | mnMouseMoveId = nullptr; | ||||||
779 | mnLastMouseX = -1; | ||||||
780 | mnLastMouseY = -1; | ||||||
781 | mnBeforeLastMouseX = -1; | ||||||
782 | mnBeforeLastMouseY = -1; | ||||||
783 | mnFirstMouseX = -1; | ||||||
784 | mnFirstMouseY = -1; | ||||||
785 | mnLastMouseWinX = -1; | ||||||
786 | mnLastMouseWinY = -1; | ||||||
787 | mnModalMode = 0; | ||||||
788 | mnMouseDownTime = 0; | ||||||
789 | mnClickCount = 0; | ||||||
790 | mnFirstMouseCode = 0; | ||||||
791 | mnMouseCode = 0; | ||||||
792 | mnMouseMode = MouseEventModifiers::NONE; | ||||||
793 | mbHasFocus = false; | ||||||
794 | mbInMouseMove = false; | ||||||
795 | mbMouseIn = false; | ||||||
796 | mbStartDragCalled = false; | ||||||
797 | mbNeedSysWindow = false; | ||||||
798 | mbMinimized = false; | ||||||
799 | mbStartFocusState = false; | ||||||
800 | mbInSysObjFocusHdl = false; | ||||||
801 | mbInSysObjToTopHdl = false; | ||||||
802 | mbSysObjFocus = false; | ||||||
803 | maPaintIdle.SetPriority( TaskPriority::REPAINT ); | ||||||
804 | maPaintIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandlePaintHdl )::tools::detail::makeLink( ::tools::detail::castTo<vcl::Window *>(pWindow), &vcl::Window::LinkStubImplHandlePaintHdl ) ); | ||||||
805 | maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" ); | ||||||
806 | maResizeIdle.SetPriority( TaskPriority::RESIZE ); | ||||||
807 | maResizeIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandleResizeTimerHdl )::tools::detail::makeLink( ::tools::detail::castTo<vcl::Window *>(pWindow), &vcl::Window::LinkStubImplHandleResizeTimerHdl ) ); | ||||||
808 | maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" ); | ||||||
809 | mbInternalDragGestureRecognizer = false; | ||||||
810 | mbInBufferedPaint = false; | ||||||
811 | mnDPIX = 96; | ||||||
812 | mnDPIY = 96; | ||||||
813 | mnTouchPanPosition = -1; | ||||||
814 | } | ||||||
815 | |||||||
816 | namespace vcl { | ||||||
817 | |||||||
818 | bool Window::AcquireGraphics() const | ||||||
819 | { | ||||||
820 | DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false); | ||||||
821 | |||||||
822 | if ( mpGraphics ) | ||||||
823 | return true; | ||||||
824 | |||||||
825 | mbInitLineColor = true; | ||||||
826 | mbInitFillColor = true; | ||||||
827 | mbInitFont = true; | ||||||
828 | mbInitTextColor = true; | ||||||
829 | mbInitClipRegion = true; | ||||||
830 | |||||||
831 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
832 | |||||||
833 | mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics(); | ||||||
834 | // try harder if no wingraphics was available directly | ||||||
835 | if ( !mpGraphics ) | ||||||
836 | { | ||||||
837 | // find another output device in the same frame | ||||||
838 | OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics; | ||||||
839 | while ( pReleaseOutDev ) | ||||||
840 | { | ||||||
841 | if ( static_cast<vcl::Window*>(pReleaseOutDev)->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame ) | ||||||
842 | break; | ||||||
843 | pReleaseOutDev = pReleaseOutDev->mpPrevGraphics; | ||||||
844 | } | ||||||
845 | |||||||
846 | if ( pReleaseOutDev ) | ||||||
847 | { | ||||||
848 | // steal the wingraphics from the other outdev | ||||||
849 | mpGraphics = pReleaseOutDev->mpGraphics; | ||||||
850 | pReleaseOutDev->ReleaseGraphics( false ); | ||||||
851 | } | ||||||
852 | else | ||||||
853 | { | ||||||
854 | // if needed retry after releasing least recently used wingraphics | ||||||
855 | while ( !mpGraphics ) | ||||||
856 | { | ||||||
857 | if ( !pSVData->maGDIData.mpLastWinGraphics ) | ||||||
858 | break; | ||||||
859 | pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics(); | ||||||
860 | mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics(); | ||||||
861 | } | ||||||
862 | } | ||||||
863 | } | ||||||
864 | |||||||
865 | if ( mpGraphics ) | ||||||
866 | { | ||||||
867 | // update global LRU list of wingraphics | ||||||
868 | mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics; | ||||||
869 | pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::Window*>(this); | ||||||
870 | if ( mpNextGraphics ) | ||||||
871 | mpNextGraphics->mpPrevGraphics = const_cast<vcl::Window*>(this); | ||||||
872 | if ( !pSVData->maGDIData.mpLastWinGraphics ) | ||||||
873 | pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::Window*>(this); | ||||||
874 | |||||||
875 | mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp ); | ||||||
876 | mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable)); | ||||||
877 | } | ||||||
878 | |||||||
879 | return mpGraphics != nullptr; | ||||||
880 | } | ||||||
881 | |||||||
882 | void Window::ReleaseGraphics( bool bRelease ) | ||||||
883 | { | ||||||
884 | DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false); | ||||||
885 | |||||||
886 | if ( !mpGraphics ) | ||||||
887 | return; | ||||||
888 | |||||||
889 | // release the fonts of the physically released graphics device | ||||||
890 | if( bRelease ) | ||||||
891 | ImplReleaseFonts(); | ||||||
892 | |||||||
893 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
894 | |||||||
895 | vcl::Window* pWindow = this; | ||||||
896 | |||||||
897 | if ( bRelease ) | ||||||
898 | pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics ); | ||||||
899 | // remove from global LRU list of window graphics | ||||||
900 | if ( mpPrevGraphics ) | ||||||
901 | mpPrevGraphics->mpNextGraphics = mpNextGraphics; | ||||||
902 | else | ||||||
903 | pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics; | ||||||
904 | if ( mpNextGraphics ) | ||||||
905 | mpNextGraphics->mpPrevGraphics = mpPrevGraphics; | ||||||
906 | else | ||||||
907 | pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics; | ||||||
908 | |||||||
909 | mpGraphics = nullptr; | ||||||
910 | mpPrevGraphics = nullptr; | ||||||
911 | mpNextGraphics = nullptr; | ||||||
912 | } | ||||||
913 | |||||||
914 | static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI) | ||||||
915 | { | ||||||
916 | #ifndef MACOSX | ||||||
917 | // Setting of HiDPI is unfortunately all only a heuristic; and to add | ||||||
918 | // insult to an injury, the system is constantly lying to us about | ||||||
919 | // the DPI and whatnot | ||||||
920 | // eg. fdo#77059 - set the value from which we do consider the | ||||||
921 | // screen HiDPI to greater than 168 | ||||||
922 | if (nDPI > 216) // 96 * 2 + 96 / 4 | ||||||
923 | return 250; | ||||||
924 | else if (nDPI > 168) // 96 * 2 - 96 / 4 | ||||||
925 | return 200; | ||||||
926 | else if (nDPI > 120) // 96 * 1.5 - 96 / 4 | ||||||
927 | return 150; | ||||||
928 | #else | ||||||
929 | (void)nDPI; | ||||||
930 | #endif | ||||||
931 | |||||||
932 | return 100; | ||||||
933 | } | ||||||
934 | |||||||
935 | void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData ) | ||||||
936 | { | ||||||
937 | SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE, "vcl.window",do { if (true && (!mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE)) { 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 () << "Window::Window(): pParent == NULL") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::Window(): pParent == NULL"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::Window(): pParent == NULL"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::Window(): pParent == NULL") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::Window(): pParent == NULL"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::Window(): pParent == NULL"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||
938 | "Window::Window(): pParent == NULL" )do { if (true && (!mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE)) { 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 () << "Window::Window(): pParent == NULL") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::Window(): pParent == NULL"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::Window(): pParent == NULL"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Window::Window(): pParent == NULL") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Window::Window(): pParent == NULL"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Window::Window(): pParent == NULL"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "938" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
939 | |||||||
940 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
941 | vcl::Window* pRealParent = pParent; | ||||||
942 | |||||||
943 | // inherit 3D look | ||||||
944 | if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) ) | ||||||
945 | nStyle |= WB_3DLOOK; | ||||||
946 | |||||||
947 | // create border window if necessary | ||||||
948 | if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow | ||||||
949 | && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) ) | ||||||
950 | { | ||||||
951 | BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE; | ||||||
952 | if( nStyle & WB_SYSTEMCHILDWINDOW ) | ||||||
953 | { | ||||||
954 | // handle WB_SYSTEMCHILDWINDOW | ||||||
955 | // these should be analogous to a top level frame; meaning they | ||||||
956 | // should have a border window with style BorderWindowStyle::Frame | ||||||
957 | // which controls their size | ||||||
958 | nBorderTypeStyle |= BorderWindowStyle::Frame; | ||||||
959 | nStyle |= WB_BORDER; | ||||||
960 | } | ||||||
961 | VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle ); | ||||||
962 | static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this; | ||||||
963 | pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder ); | ||||||
964 | mpWindowImpl->mpBorderWindow = pBorderWin; | ||||||
965 | pParent = mpWindowImpl->mpBorderWindow; | ||||||
966 | } | ||||||
967 | else if( !mpWindowImpl->mbFrame && ! pParent ) | ||||||
968 | { | ||||||
969 | mpWindowImpl->mbOverlapWin = true; | ||||||
970 | mpWindowImpl->mbFrame = true; | ||||||
971 | } | ||||||
972 | |||||||
973 | // insert window in list | ||||||
974 | ImplInsertWindow( pParent ); | ||||||
975 | mpWindowImpl->mnStyle = nStyle; | ||||||
976 | |||||||
977 | if( pParent && ! mpWindowImpl->mbFrame ) | ||||||
978 | mbEnableRTL = AllSettings::GetLayoutRTL(); | ||||||
979 | |||||||
980 | // test for frame creation | ||||||
981 | if ( mpWindowImpl->mbFrame ) | ||||||
982 | { | ||||||
983 | // create frame | ||||||
984 | SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE; | ||||||
985 | |||||||
986 | if ( nStyle & WB_MOVEABLE ) | ||||||
987 | nFrameStyle |= SalFrameStyleFlags::MOVEABLE; | ||||||
988 | if ( nStyle & WB_SIZEABLE ) | ||||||
989 | nFrameStyle |= SalFrameStyleFlags::SIZEABLE; | ||||||
990 | if ( nStyle & WB_CLOSEABLE ) | ||||||
991 | nFrameStyle |= SalFrameStyleFlags::CLOSEABLE; | ||||||
992 | if ( nStyle & WB_APP ) | ||||||
993 | nFrameStyle |= SalFrameStyleFlags::DEFAULT; | ||||||
994 | // check for undecorated floating window | ||||||
995 | if( // 1. floating windows that are not moveable/sizeable (only closeable allowed) | ||||||
996 | ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) && | ||||||
997 | ( mpWindowImpl->mbFloatWin || ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) || | ||||||
998 | // 2. borderwindows of floaters with ownerdraw decoration | ||||||
999 | ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) ) | ||||||
1000 | { | ||||||
1001 | nFrameStyle = SalFrameStyleFlags::FLOAT; | ||||||
1002 | if( nStyle & WB_OWNERDRAWDECORATION ) | ||||||
1003 | nFrameStyle |= SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW; | ||||||
1004 | } | ||||||
1005 | else if( mpWindowImpl->mbFloatWin ) | ||||||
1006 | nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW; | ||||||
1007 | |||||||
1008 | if( nStyle & WB_INTROWIN ) | ||||||
1009 | nFrameStyle |= SalFrameStyleFlags::INTRO; | ||||||
1010 | if( nStyle & WB_TOOLTIPWIN ) | ||||||
1011 | nFrameStyle |= SalFrameStyleFlags::TOOLTIP; | ||||||
1012 | |||||||
1013 | if( nStyle & WB_NOSHADOW ) | ||||||
1014 | nFrameStyle |= SalFrameStyleFlags::NOSHADOW; | ||||||
1015 | |||||||
1016 | if( nStyle & WB_SYSTEMCHILDWINDOW ) | ||||||
1017 | nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD; | ||||||
1018 | |||||||
1019 | switch (mpWindowImpl->mnType) | ||||||
1020 | { | ||||||
1021 | case WindowType::DIALOG: | ||||||
1022 | case WindowType::TABDIALOG: | ||||||
1023 | case WindowType::MODELESSDIALOG: | ||||||
1024 | case WindowType::MESSBOX: | ||||||
1025 | case WindowType::INFOBOX: | ||||||
1026 | case WindowType::WARNINGBOX: | ||||||
1027 | case WindowType::ERRORBOX: | ||||||
1028 | case WindowType::QUERYBOX: | ||||||
1029 | nFrameStyle |= SalFrameStyleFlags::DIALOG; | ||||||
1030 | break; | ||||||
1031 | default: | ||||||
1032 | break; | ||||||
1033 | } | ||||||
1034 | |||||||
1035 | SalFrame* pParentFrame = nullptr; | ||||||
1036 | if ( pParent ) | ||||||
1037 | pParentFrame = pParent->mpWindowImpl->mpFrame; | ||||||
1038 | SalFrame* pFrame; | ||||||
1039 | if ( pSystemParentData ) | ||||||
1040 | pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG ); | ||||||
1041 | else | ||||||
1042 | pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle ); | ||||||
1043 | if ( !pFrame ) | ||||||
1044 | { | ||||||
1045 | // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario) | ||||||
1046 | throw RuntimeException( | ||||||
1047 | "Could not create system window!", | ||||||
1048 | Reference< XInterface >() ); | ||||||
1049 | } | ||||||
1050 | |||||||
1051 | pFrame->SetCallback( this, ImplWindowFrameProc ); | ||||||
1052 | |||||||
1053 | // set window frame data | ||||||
1054 | mpWindowImpl->mpFrameData = new ImplFrameData( this ); | ||||||
1055 | mpWindowImpl->mpFrame = pFrame; | ||||||
1056 | mpWindowImpl->mpFrameWindow = this; | ||||||
1057 | mpWindowImpl->mpOverlapWindow = this; | ||||||
1058 | |||||||
1059 | if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested) | ||||||
1060 | RequestDoubleBuffering(true); | ||||||
1061 | |||||||
1062 | if ( pRealParent && IsTopWindow() ) | ||||||
1063 | { | ||||||
1064 | ImplWinData* pParentWinData = pRealParent->ImplGetWinData(); | ||||||
1065 | pParentWinData->maTopWindowChildren.emplace_back(this ); | ||||||
1066 | } | ||||||
1067 | } | ||||||
1068 | |||||||
1069 | // init data | ||||||
1070 | mpWindowImpl->mpRealParent = pRealParent; | ||||||
1071 | |||||||
1072 | // #99318: make sure fontcache and list is available before call to SetSettings | ||||||
1073 | mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection; | ||||||
1074 | mxFontCache = mpWindowImpl->mpFrameData->mxFontCache; | ||||||
1075 | |||||||
1076 | if ( mpWindowImpl->mbFrame ) | ||||||
1077 | { | ||||||
1078 | if ( pParent ) | ||||||
1079 | { | ||||||
1080 | mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX; | ||||||
1081 | mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY; | ||||||
1082 | } | ||||||
1083 | else | ||||||
1084 | { | ||||||
1085 | OutputDevice *pOutDev = GetOutDev(); | ||||||
1086 | if ( pOutDev->AcquireGraphics() ) | ||||||
1087 | { | ||||||
1088 | mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY ); | ||||||
1089 | } | ||||||
1090 | } | ||||||
1091 | |||||||
1092 | // add ownerdraw decorated frame windows to list in the top-most frame window | ||||||
1093 | // so they can be hidden on lose focus | ||||||
1094 | if( nStyle & WB_OWNERDRAWDECORATION ) | ||||||
1095 | ImplGetOwnerDrawList().emplace_back(this ); | ||||||
1096 | |||||||
1097 | // delay settings initialization until first "real" frame | ||||||
1098 | // this relies on the IntroWindow not needing any system settings | ||||||
1099 | if ( !pSVData->maAppData.mbSettingsInit && | ||||||
1100 | ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) | ||||||
1101 | ) | ||||||
1102 | { | ||||||
1103 | // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings | ||||||
1104 | ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings ); | ||||||
1105 | OutputDevice::SetSettings( *pSVData->maAppData.mpSettings ); | ||||||
1106 | pSVData->maAppData.mbSettingsInit = true; | ||||||
1107 | } | ||||||
1108 | |||||||
1109 | // If we create a Window with default size, query this | ||||||
1110 | // size directly, because we want resize all Controls to | ||||||
1111 | // the correct size before we display the window | ||||||
1112 | if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) ) | ||||||
1113 | mpWindowImpl->mpFrame->GetClientSize( mnOutWidth, mnOutHeight ); | ||||||
1114 | } | ||||||
1115 | else | ||||||
1116 | { | ||||||
1117 | if ( pParent ) | ||||||
1118 | { | ||||||
1119 | if ( !ImplIsOverlapWindow() ) | ||||||
1120 | { | ||||||
1121 | mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled; | ||||||
1122 | mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled; | ||||||
1123 | mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode; | ||||||
1124 | } | ||||||
1125 | |||||||
1126 | if (!utl::ConfigManager::IsFuzzing()) | ||||||
1127 | OutputDevice::SetSettings( pParent->GetSettings() ); | ||||||
1128 | } | ||||||
1129 | |||||||
1130 | } | ||||||
1131 | |||||||
1132 | // setup the scale factor for HiDPI displays | ||||||
1133 | mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY); | ||||||
1134 | mnDPIX = mpWindowImpl->mpFrameData->mnDPIX; | ||||||
1135 | mnDPIY = mpWindowImpl->mpFrameData->mnDPIY; | ||||||
1136 | |||||||
1137 | if (!utl::ConfigManager::IsFuzzing()) | ||||||
1138 | { | ||||||
1139 | const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings(); | ||||||
1140 | maFont = rStyleSettings.GetAppFont(); | ||||||
1141 | |||||||
1142 | if ( nStyle & WB_3DLOOK ) | ||||||
1143 | { | ||||||
1144 | SetTextColor( rStyleSettings.GetButtonTextColor() ); | ||||||
1145 | SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) ); | ||||||
1146 | } | ||||||
1147 | else | ||||||
1148 | { | ||||||
1149 | SetTextColor( rStyleSettings.GetWindowTextColor() ); | ||||||
1150 | SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) ); | ||||||
1151 | } | ||||||
1152 | } | ||||||
1153 | else | ||||||
1154 | { | ||||||
1155 | maFont = GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_USLanguageType(0x0409), GetDefaultFontFlags::NONE ); | ||||||
1156 | } | ||||||
1157 | |||||||
1158 | ImplPointToLogic(*this, maFont); | ||||||
1159 | |||||||
1160 | (void)ImplUpdatePos(); | ||||||
1161 | |||||||
1162 | // calculate app font res (except for the Intro Window or the default window) | ||||||
1163 | if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) ) | ||||||
1164 | ImplInitAppFontData( this ); | ||||||
1165 | } | ||||||
1166 | |||||||
1167 | void Window::ImplInitAppFontData( vcl::Window const * pWindow ) | ||||||
1168 | { | ||||||
1169 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
1170 | long nTextHeight = pWindow->GetTextHeight(); | ||||||
1171 | long nTextWidth = pWindow->approximate_char_width() * 8; | ||||||
1172 | long nSymHeight = nTextHeight*4; | ||||||
1173 | // Make the basis wider if the font is too narrow | ||||||
1174 | // such that the dialog looks symmetrical and does not become too narrow. | ||||||
1175 | // Add some extra space when the dialog has the same width, | ||||||
1176 | // as a little more space is better. | ||||||
1177 | if ( nSymHeight > nTextWidth ) | ||||||
1178 | nTextWidth = nSymHeight; | ||||||
1179 | else if ( nSymHeight+5 > nTextWidth ) | ||||||
1180 | nTextWidth = nSymHeight+5; | ||||||
1181 | pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8; | ||||||
1182 | pSVData->maGDIData.mnAppFontY = nTextHeight * 10; | ||||||
1183 | |||||||
1184 | #ifdef MACOSX | ||||||
1185 | // FIXME: this is currently only on macOS, check with other | ||||||
1186 | // platforms | ||||||
1187 | if( pSVData->maNWFData.mbNoFocusRects ) | ||||||
1188 | { | ||||||
1189 | // try to find out whether there is a large correction | ||||||
1190 | // of control sizes, if yes, make app font scalings larger | ||||||
1191 | // so dialog positioning is not completely off | ||||||
1192 | ImplControlValue aControlValue; | ||||||
1193 | tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) ); | ||||||
1194 | tools::Rectangle aBoundingRgn( aCtrlRegion ); | ||||||
1195 | tools::Rectangle aContentRgn( aCtrlRegion ); | ||||||
1196 | if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion, | ||||||
1197 | ControlState::ENABLED, aControlValue, | ||||||
1198 | aBoundingRgn, aContentRgn ) ) | ||||||
1199 | { | ||||||
1200 | // comment: the magical +6 is for the extra border in bordered | ||||||
1201 | // (which is the standard) edit fields | ||||||
1202 | if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 ) | ||||||
1203 | pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10; | ||||||
1204 | } | ||||||
1205 | } | ||||||
1206 | #endif | ||||||
1207 | } | ||||||
1208 | |||||||
1209 | ImplWinData* Window::ImplGetWinData() const | ||||||
1210 | { | ||||||
1211 | if (!mpWindowImpl->mpWinData) | ||||||
1212 | { | ||||||
1213 | static const char* pNoNWF = getenv( "SAL_NO_NWF" ); | ||||||
1214 | |||||||
1215 | const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData = new ImplWinData; | ||||||
1216 | mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API | ||||||
1217 | } | ||||||
1218 | |||||||
1219 | return mpWindowImpl->mpWinData; | ||||||
1220 | } | ||||||
1221 | |||||||
1222 | |||||||
1223 | void Window::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate ) | ||||||
1224 | { | ||||||
1225 | if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0) | ||||||
1226 | return; | ||||||
1227 | |||||||
1228 | if (bWindowInvalidate) | ||||||
1229 | { | ||||||
1230 | const tools::Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY), | ||||||
1231 | Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight)); | ||||||
1232 | |||||||
1233 | ImplMoveAllInvalidateRegions(aSrcRect, | ||||||
1234 | aPosAry.mnDestX-aPosAry.mnSrcX, | ||||||
1235 | aPosAry.mnDestY-aPosAry.mnSrcY, | ||||||
1236 | false); | ||||||
1237 | |||||||
1238 | mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY, | ||||||
1239 | aPosAry.mnSrcX, aPosAry.mnSrcY, | ||||||
1240 | aPosAry.mnSrcWidth, aPosAry.mnSrcHeight, | ||||||
1241 | this); | ||||||
1242 | |||||||
1243 | return; | ||||||
1244 | } | ||||||
1245 | |||||||
1246 | OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate); | ||||||
1247 | } | ||||||
1248 | |||||||
1249 | const OutputDevice* Window::DrawOutDevDirectCheck(const OutputDevice* pSrcDev) const | ||||||
1250 | { | ||||||
1251 | const OutputDevice* pSrcDevChecked; | ||||||
1252 | if ( this == pSrcDev ) | ||||||
1253 | pSrcDevChecked = nullptr; | ||||||
1254 | else if (GetOutDevType() != pSrcDev->GetOutDevType()) | ||||||
1255 | pSrcDevChecked = pSrcDev; | ||||||
1256 | else if (this->mpWindowImpl->mpFrameWindow == static_cast<const vcl::Window*>(pSrcDev)->mpWindowImpl->mpFrameWindow) | ||||||
1257 | pSrcDevChecked = nullptr; | ||||||
1258 | else | ||||||
1259 | pSrcDevChecked = pSrcDev; | ||||||
1260 | |||||||
1261 | return pSrcDevChecked; | ||||||
1262 | } | ||||||
1263 | |||||||
1264 | void Window::DrawOutDevDirectProcess( const OutputDevice* pSrcDev, SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) | ||||||
1265 | { | ||||||
1266 | mpGraphics->CopyBits( rPosAry, pSrcGraphics, this, pSrcDev ); | ||||||
1267 | } | ||||||
1268 | |||||||
1269 | SalGraphics* Window::ImplGetFrameGraphics() const | ||||||
1270 | { | ||||||
1271 | if ( mpWindowImpl->mpFrameWindow->mpGraphics ) | ||||||
1272 | { | ||||||
1273 | mpWindowImpl->mpFrameWindow->mbInitClipRegion = true; | ||||||
1274 | } | ||||||
1275 | else | ||||||
1276 | { | ||||||
1277 | OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow; | ||||||
1278 | if ( ! pFrameWinOutDev->AcquireGraphics() ) | ||||||
1279 | { | ||||||
1280 | return nullptr; | ||||||
1281 | } | ||||||
1282 | } | ||||||
1283 | mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion(); | ||||||
1284 | return mpWindowImpl->mpFrameWindow->mpGraphics; | ||||||
1285 | } | ||||||
1286 | |||||||
1287 | void Window::ImplSetReallyVisible() | ||||||
1288 | { | ||||||
1289 | // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between | ||||||
1290 | // ImplCallInitShow() and ImplSetReallyVisible() when called from Show() | ||||||
1291 | // mbReallyShown is a useful indicator | ||||||
1292 | if( !mpWindowImpl->mbReallyShown ) | ||||||
1293 | ImplCallInitShow(); | ||||||
1294 | |||||||
1295 | bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible; | ||||||
1296 | |||||||
1297 | mbDevOutput = true; | ||||||
1298 | mpWindowImpl->mbReallyVisible = true; | ||||||
1299 | mpWindowImpl->mbReallyShown = true; | ||||||
1300 | |||||||
1301 | // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge. | ||||||
1302 | // For this, the data member of the event must not be NULL. | ||||||
1303 | // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now | ||||||
1304 | // we're doing it when the visibility really changes | ||||||
1305 | if( bBecameReallyVisible && ImplIsAccessibleCandidate() ) | ||||||
1306 | CallEventListeners( VclEventId::WindowShow, this ); | ||||||
1307 | // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should | ||||||
1308 | // introduce another event which explicitly triggers the Accessibility implementations. | ||||||
1309 | |||||||
1310 | vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap; | ||||||
1311 | while ( pWindow ) | ||||||
1312 | { | ||||||
1313 | if ( pWindow->mpWindowImpl->mbVisible ) | ||||||
1314 | pWindow->ImplSetReallyVisible(); | ||||||
1315 | pWindow = pWindow->mpWindowImpl->mpNext; | ||||||
1316 | } | ||||||
1317 | |||||||
1318 | pWindow = mpWindowImpl->mpFirstChild; | ||||||
1319 | while ( pWindow ) | ||||||
1320 | { | ||||||
1321 | if ( pWindow->mpWindowImpl->mbVisible ) | ||||||
1322 | pWindow->ImplSetReallyVisible(); | ||||||
1323 | pWindow = pWindow->mpWindowImpl->mpNext; | ||||||
1324 | } | ||||||
1325 | } | ||||||
1326 | |||||||
1327 | void Window::ImplInitResolutionSettings() | ||||||
1328 | { | ||||||
1329 | // recalculate AppFont-resolution and DPI-resolution | ||||||
1330 | if (mpWindowImpl->mbFrame) | ||||||
1331 | { | ||||||
1332 | mnDPIX = mpWindowImpl->mpFrameData->mnDPIX; | ||||||
1333 | mnDPIY = mpWindowImpl->mpFrameData->mnDPIY; | ||||||
1334 | |||||||
1335 | // setup the scale factor for HiDPI displays | ||||||
1336 | mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY); | ||||||
1337 | const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings(); | ||||||
1338 | SetPointFont(*this, rStyleSettings.GetAppFont()); | ||||||
1339 | } | ||||||
1340 | else if ( mpWindowImpl->mpParent ) | ||||||
1341 | { | ||||||
1342 | mnDPIX = mpWindowImpl->mpParent->mnDPIX; | ||||||
1343 | mnDPIY = mpWindowImpl->mpParent->mnDPIY; | ||||||
1344 | mnDPIScalePercentage = mpWindowImpl->mpParent->mnDPIScalePercentage; | ||||||
1345 | } | ||||||
1346 | |||||||
1347 | // update the recalculated values for logical units | ||||||
1348 | // and also tools belonging to the values | ||||||
1349 | if (IsMapModeEnabled()) | ||||||
1350 | { | ||||||
1351 | MapMode aMapMode = GetMapMode(); | ||||||
1352 | SetMapMode(); | ||||||
1353 | SetMapMode( aMapMode ); | ||||||
1354 | } | ||||||
1355 | } | ||||||
1356 | |||||||
1357 | void Window::ImplPointToLogic(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const | ||||||
1358 | { | ||||||
1359 | Size aSize = rFont.GetFontSize(); | ||||||
1360 | |||||||
1361 | if (aSize.Width()) | ||||||
1362 | { | ||||||
1363 | aSize.setWidth( aSize.Width() * ( mpWindowImpl->mpFrameData->mnDPIX) ); | ||||||
1364 | aSize.AdjustWidth(72 / 2 ); | ||||||
1365 | aSize.setWidth( aSize.Width() / 72 ); | ||||||
1366 | } | ||||||
1367 | aSize.setHeight( aSize.Height() * ( mpWindowImpl->mpFrameData->mnDPIY) ); | ||||||
1368 | aSize.AdjustHeight(72/2 ); | ||||||
1369 | aSize.setHeight( aSize.Height() / 72 ); | ||||||
1370 | |||||||
1371 | if (rRenderContext.IsMapModeEnabled()) | ||||||
1372 | aSize = rRenderContext.PixelToLogic(aSize); | ||||||
1373 | |||||||
1374 | rFont.SetFontSize(aSize); | ||||||
1375 | } | ||||||
1376 | |||||||
1377 | void Window::ImplLogicToPoint(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const | ||||||
1378 | { | ||||||
1379 | Size aSize = rFont.GetFontSize(); | ||||||
1380 | |||||||
1381 | if (rRenderContext.IsMapModeEnabled()) | ||||||
1382 | aSize = rRenderContext.LogicToPixel(aSize); | ||||||
1383 | |||||||
1384 | if (aSize.Width()) | ||||||
1385 | { | ||||||
1386 | aSize.setWidth( aSize.Width() * 72 ); | ||||||
1387 | aSize.AdjustWidth(mpWindowImpl->mpFrameData->mnDPIX / 2 ); | ||||||
1388 | aSize.setWidth( aSize.Width() / ( mpWindowImpl->mpFrameData->mnDPIX) ); | ||||||
1389 | } | ||||||
1390 | aSize.setHeight( aSize.Height() * 72 ); | ||||||
1391 | aSize.AdjustHeight(mpWindowImpl->mpFrameData->mnDPIY / 2 ); | ||||||
1392 | aSize.setHeight( aSize.Height() / ( mpWindowImpl->mpFrameData->mnDPIY) ); | ||||||
1393 | |||||||
1394 | rFont.SetFontSize(aSize); | ||||||
1395 | } | ||||||
1396 | |||||||
1397 | bool Window::ImplUpdatePos() | ||||||
1398 | { | ||||||
1399 | bool bSysChild = false; | ||||||
1400 | |||||||
1401 | if ( ImplIsOverlapWindow() ) | ||||||
1402 | { | ||||||
1403 | mnOutOffX = mpWindowImpl->mnX; | ||||||
1404 | mnOutOffY = mpWindowImpl->mnY; | ||||||
1405 | } | ||||||
1406 | else | ||||||
1407 | { | ||||||
1408 | vcl::Window* pParent = ImplGetParent(); | ||||||
1409 | |||||||
1410 | mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX; | ||||||
1411 | mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY; | ||||||
1412 | } | ||||||
1413 | |||||||
1414 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
1415 | while ( pChild ) | ||||||
1416 | { | ||||||
1417 | if ( pChild->ImplUpdatePos() ) | ||||||
1418 | bSysChild = true; | ||||||
1419 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
1420 | } | ||||||
1421 | |||||||
1422 | if ( mpWindowImpl->mpSysObj ) | ||||||
1423 | bSysChild = true; | ||||||
1424 | |||||||
1425 | return bSysChild; | ||||||
1426 | } | ||||||
1427 | |||||||
1428 | void Window::ImplUpdateSysObjPos() | ||||||
1429 | { | ||||||
1430 | if ( mpWindowImpl->mpSysObj ) | ||||||
1431 | mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ); | ||||||
1432 | |||||||
1433 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
1434 | while ( pChild ) | ||||||
1435 | { | ||||||
1436 | pChild->ImplUpdateSysObjPos(); | ||||||
1437 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
1438 | } | ||||||
1439 | } | ||||||
1440 | |||||||
1441 | void Window::ImplPosSizeWindow( long nX, long nY, | ||||||
1442 | long nWidth, long nHeight, PosSizeFlags nFlags ) | ||||||
1443 | { | ||||||
1444 | bool bNewPos = false; | ||||||
1445 | bool bNewSize = false; | ||||||
1446 | bool bCopyBits = false; | ||||||
1447 | long nOldOutOffX = mnOutOffX; | ||||||
1448 | long nOldOutOffY = mnOutOffY; | ||||||
1449 | long nOldOutWidth = mnOutWidth; | ||||||
1450 | long nOldOutHeight = mnOutHeight; | ||||||
1451 | std::unique_ptr<vcl::Region> pOverlapRegion; | ||||||
1452 | std::unique_ptr<vcl::Region> pOldRegion; | ||||||
1453 | |||||||
1454 | if ( IsReallyVisible() ) | ||||||
1455 | { | ||||||
1456 | tools::Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ), | ||||||
1457 | Size( nOldOutWidth, nOldOutHeight ) ); | ||||||
1458 | pOldRegion.reset( new vcl::Region( aOldWinRect ) ); | ||||||
1459 | if ( mpWindowImpl->mbWinRegion ) | ||||||
1460 | pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) ); | ||||||
1461 | |||||||
1462 | if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent && | ||||||
1463 | !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() && | ||||||
1464 | !HasPaintEvent() ) | ||||||
1465 | bCopyBits = true; | ||||||
1466 | } | ||||||
1467 | |||||||
1468 | bool bnXRecycled = false; // avoid duplicate mirroring in RTL case | ||||||
1469 | if ( nFlags & PosSizeFlags::Width ) | ||||||
1470 | { | ||||||
1471 | if(!( nFlags & PosSizeFlags::X )) | ||||||
1472 | { | ||||||
1473 | nX = mpWindowImpl->mnX; | ||||||
1474 | nFlags |= PosSizeFlags::X; | ||||||
1475 | bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case | ||||||
1476 | } | ||||||
1477 | |||||||
1478 | if ( nWidth < 0 ) | ||||||
1479 | nWidth = 0; | ||||||
1480 | if ( nWidth != mnOutWidth ) | ||||||
1481 | { | ||||||
1482 | mnOutWidth = nWidth; | ||||||
1483 | bNewSize = true; | ||||||
1484 | bCopyBits = false; | ||||||
1485 | } | ||||||
1486 | } | ||||||
1487 | if ( nFlags & PosSizeFlags::Height ) | ||||||
1488 | { | ||||||
1489 | if ( nHeight < 0 ) | ||||||
1490 | nHeight = 0; | ||||||
1491 | if ( nHeight != mnOutHeight ) | ||||||
1492 | { | ||||||
1493 | mnOutHeight = nHeight; | ||||||
1494 | bNewSize = true; | ||||||
1495 | bCopyBits = false; | ||||||
1496 | } | ||||||
1497 | } | ||||||
1498 | |||||||
1499 | if ( nFlags & PosSizeFlags::X ) | ||||||
1500 | { | ||||||
1501 | long nOrgX = nX; | ||||||
1502 | Point aPtDev( Point( nX+mnOutOffX, 0 ) ); | ||||||
1503 | OutputDevice *pOutDev = GetOutDev(); | ||||||
1504 | if( pOutDev->HasMirroredGraphics() ) | ||||||
1505 | { | ||||||
1506 | aPtDev.setX( mpGraphics->mirror2( aPtDev.X(), this ) ); | ||||||
1507 | |||||||
1508 | // #106948# always mirror our pos if our parent is not mirroring, even | ||||||
1509 | // if we are also not mirroring | ||||||
1510 | // RTL: check if parent is in different coordinates | ||||||
1511 | if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() ) | ||||||
1512 | { | ||||||
1513 | nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX; | ||||||
1514 | } | ||||||
1515 | /* #i99166# An LTR window in RTL UI that gets sized only would be | ||||||
1516 | expected to not moved its upper left point | ||||||
1517 | */ | ||||||
1518 | if( bnXRecycled ) | ||||||
1519 | { | ||||||
1520 | if( ImplIsAntiparallel() ) | ||||||
1521 | { | ||||||
1522 | aPtDev.setX( mpWindowImpl->mnAbsScreenX ); | ||||||
1523 | nOrgX = mpWindowImpl->maPos.X(); | ||||||
1524 | } | ||||||
1525 | } | ||||||
1526 | } | ||||||
1527 | else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() ) | ||||||
1528 | { | ||||||
1529 | // mirrored window in LTR UI | ||||||
1530 | nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX; | ||||||
1531 | } | ||||||
1532 | |||||||
1533 | // check maPos as well, as it could have been changed for client windows (ImplCallMove()) | ||||||
1534 | if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() ) | ||||||
1535 | { | ||||||
1536 | if ( bCopyBits && !pOverlapRegion ) | ||||||
1537 | { | ||||||
1538 | pOverlapRegion.reset( new vcl::Region() ); | ||||||
1539 | ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), | ||||||
1540 | Size( mnOutWidth, mnOutHeight ) ), | ||||||
1541 | *pOverlapRegion, false, true ); | ||||||
1542 | } | ||||||
1543 | mpWindowImpl->mnX = nX; | ||||||
1544 | mpWindowImpl->maPos.setX( nOrgX ); | ||||||
1545 | mpWindowImpl->mnAbsScreenX = aPtDev.X(); | ||||||
1546 | bNewPos = true; | ||||||
1547 | } | ||||||
1548 | } | ||||||
1549 | if ( nFlags & PosSizeFlags::Y ) | ||||||
1550 | { | ||||||
1551 | // check maPos as well, as it could have been changed for client windows (ImplCallMove()) | ||||||
1552 | if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() ) | ||||||
1553 | { | ||||||
1554 | if ( bCopyBits && !pOverlapRegion ) | ||||||
1555 | { | ||||||
1556 | pOverlapRegion.reset( new vcl::Region() ); | ||||||
1557 | ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), | ||||||
1558 | Size( mnOutWidth, mnOutHeight ) ), | ||||||
1559 | *pOverlapRegion, false, true ); | ||||||
1560 | } | ||||||
1561 | mpWindowImpl->mnY = nY; | ||||||
1562 | mpWindowImpl->maPos.setY( nY ); | ||||||
1563 | bNewPos = true; | ||||||
1564 | } | ||||||
1565 | } | ||||||
1566 | |||||||
1567 | if ( !(bNewPos || bNewSize) ) | ||||||
1568 | return; | ||||||
1569 | |||||||
1570 | bool bUpdateSysObjPos = false; | ||||||
1571 | if ( bNewPos ) | ||||||
1572 | bUpdateSysObjPos = ImplUpdatePos(); | ||||||
1573 | |||||||
1574 | // the borderwindow always specifies the position for its client window | ||||||
1575 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
1576 | mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos; | ||||||
1577 | |||||||
1578 | if ( mpWindowImpl->mpClientWindow ) | ||||||
1579 | { | ||||||
1580 | mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder, | ||||||
1581 | mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder, | ||||||
1582 | mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder, | ||||||
1583 | mnOutHeight-mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder, | ||||||
1584 | PosSizeFlags::X | PosSizeFlags::Y | | ||||||
1585 | PosSizeFlags::Width | PosSizeFlags::Height ); | ||||||
1586 | // If we have a client window, then this is the position | ||||||
1587 | // of the Application's floating windows | ||||||
1588 | mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos; | ||||||
1589 | if ( bNewPos ) | ||||||
1590 | { | ||||||
1591 | if ( mpWindowImpl->mpClientWindow->IsVisible() ) | ||||||
1592 | { | ||||||
1593 | mpWindowImpl->mpClientWindow->ImplCallMove(); | ||||||
1594 | } | ||||||
1595 | else | ||||||
1596 | { | ||||||
1597 | mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true; | ||||||
1598 | } | ||||||
1599 | } | ||||||
1600 | } | ||||||
1601 | |||||||
1602 | // Move()/Resize() will be called only for Show(), such that | ||||||
1603 | // at least one is called before Show() | ||||||
1604 | if ( IsVisible() ) | ||||||
1605 | { | ||||||
1606 | if ( bNewPos ) | ||||||
1607 | { | ||||||
1608 | ImplCallMove(); | ||||||
1609 | } | ||||||
1610 | if ( bNewSize ) | ||||||
1611 | { | ||||||
1612 | ImplCallResize(); | ||||||
1613 | } | ||||||
1614 | } | ||||||
1615 | else | ||||||
1616 | { | ||||||
1617 | if ( bNewPos ) | ||||||
1618 | mpWindowImpl->mbCallMove = true; | ||||||
1619 | if ( bNewSize ) | ||||||
1620 | mpWindowImpl->mbCallResize = true; | ||||||
1621 | } | ||||||
1622 | |||||||
1623 | bool bUpdateSysObjClip = false; | ||||||
1624 | if ( IsReallyVisible() ) | ||||||
1625 | { | ||||||
1626 | if ( bNewPos || bNewSize ) | ||||||
1627 | { | ||||||
1628 | // set Clip-Flag | ||||||
1629 | bUpdateSysObjClip = !ImplSetClipFlag( true ); | ||||||
1630 | } | ||||||
1631 | |||||||
1632 | // invalidate window content ? | ||||||
1633 | if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) ) | ||||||
1634 | { | ||||||
1635 | if ( bNewPos ) | ||||||
1636 | { | ||||||
1637 | bool bInvalidate = false; | ||||||
1638 | bool bParentPaint = true; | ||||||
1639 | if ( !ImplIsOverlapWindow() ) | ||||||
1640 | bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled(); | ||||||
1641 | if ( bCopyBits && bParentPaint && !HasPaintEvent() ) | ||||||
1642 | { | ||||||
1643 | Point aPoint( mnOutOffX, mnOutOffY ); | ||||||
1644 | vcl::Region aRegion( tools::Rectangle( aPoint, | ||||||
1645 | Size( mnOutWidth, mnOutHeight ) ) ); | ||||||
1646 | if ( mpWindowImpl->mbWinRegion ) | ||||||
1647 | aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) ); | ||||||
1648 | ImplClipBoundaries( aRegion, false, true ); | ||||||
1649 | if ( !pOverlapRegion->IsEmpty() ) | ||||||
1650 | { | ||||||
1651 | pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY ); | ||||||
1652 | aRegion.Exclude( *pOverlapRegion ); | ||||||
1653 | } | ||||||
1654 | if ( !aRegion.IsEmpty() ) | ||||||
1655 | { | ||||||
1656 | // adapt Paint areas | ||||||
1657 | ImplMoveAllInvalidateRegions( tools::Rectangle( Point( nOldOutOffX, nOldOutOffY ), | ||||||
1658 | Size( nOldOutWidth, nOldOutHeight ) ), | ||||||
1659 | mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY, | ||||||
1660 | true ); | ||||||
1661 | SalGraphics* pGraphics = ImplGetFrameGraphics(); | ||||||
1662 | if ( pGraphics ) | ||||||
1663 | { | ||||||
1664 | |||||||
1665 | OutputDevice *pOutDev = GetOutDev(); | ||||||
1666 | const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics ); | ||||||
1667 | if ( bSelectClipRegion ) | ||||||
1668 | { | ||||||
1669 | pGraphics->CopyArea( mnOutOffX, mnOutOffY, | ||||||
1670 | nOldOutOffX, nOldOutOffY, | ||||||
1671 | nOldOutWidth, nOldOutHeight, | ||||||
1672 | this ); | ||||||
1673 | } | ||||||
1674 | else | ||||||
1675 | bInvalidate = true; | ||||||
1676 | } | ||||||
1677 | else | ||||||
1678 | bInvalidate = true; | ||||||
1679 | if ( !bInvalidate ) | ||||||
1680 | { | ||||||
1681 | if ( !pOverlapRegion->IsEmpty() ) | ||||||
1682 | ImplInvalidateFrameRegion( pOverlapRegion.get(), InvalidateFlags::Children ); | ||||||
1683 | } | ||||||
1684 | } | ||||||
1685 | else | ||||||
1686 | bInvalidate = true; | ||||||
1687 | } | ||||||
1688 | else | ||||||
1689 | bInvalidate = true; | ||||||
1690 | if ( bInvalidate ) | ||||||
1691 | ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children ); | ||||||
1692 | } | ||||||
1693 | else | ||||||
1694 | { | ||||||
1695 | Point aPoint( mnOutOffX, mnOutOffY ); | ||||||
1696 | vcl::Region aRegion( tools::Rectangle( aPoint, | ||||||
1697 | Size( mnOutWidth, mnOutHeight ) ) ); | ||||||
1698 | aRegion.Exclude( *pOldRegion ); | ||||||
1699 | if ( mpWindowImpl->mbWinRegion ) | ||||||
1700 | aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) ); | ||||||
1701 | ImplClipBoundaries( aRegion, false, true ); | ||||||
1702 | if ( !aRegion.IsEmpty() ) | ||||||
1703 | ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children ); | ||||||
1704 | } | ||||||
1705 | } | ||||||
1706 | |||||||
1707 | // invalidate Parent or Overlaps | ||||||
1708 | if ( bNewPos || | ||||||
1709 | (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) ) | ||||||
1710 | { | ||||||
1711 | vcl::Region aRegion( *pOldRegion ); | ||||||
1712 | if ( !mpWindowImpl->mbPaintTransparent ) | ||||||
1713 | ImplExcludeWindowRegion( aRegion ); | ||||||
1714 | ImplClipBoundaries( aRegion, false, true ); | ||||||
1715 | if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow ) | ||||||
1716 | ImplInvalidateParentFrameRegion( aRegion ); | ||||||
1717 | } | ||||||
1718 | } | ||||||
1719 | |||||||
1720 | // adapt system objects | ||||||
1721 | if ( bUpdateSysObjClip ) | ||||||
1722 | ImplUpdateSysObjClip(); | ||||||
1723 | if ( bUpdateSysObjPos ) | ||||||
1724 | ImplUpdateSysObjPos(); | ||||||
1725 | if ( bNewSize && mpWindowImpl->mpSysObj ) | ||||||
1726 | mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ); | ||||||
1727 | } | ||||||
1728 | |||||||
1729 | void Window::ImplNewInputContext() | ||||||
1730 | { | ||||||
1731 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
1732 | vcl::Window* pFocusWin = pSVData->mpWinData->mpFocusWin; | ||||||
1733 | if ( !pFocusWin || pFocusWin->IsDisposed() ) | ||||||
1734 | return; | ||||||
1735 | |||||||
1736 | // Is InputContext changed? | ||||||
1737 | const InputContext& rInputContext = pFocusWin->GetInputContext(); | ||||||
1738 | if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext ) | ||||||
1739 | return; | ||||||
1740 | |||||||
1741 | pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext; | ||||||
1742 | |||||||
1743 | SalInputContext aNewContext; | ||||||
1744 | const vcl::Font& rFont = rInputContext.GetFont(); | ||||||
1745 | const OUString& rFontName = rFont.GetFamilyName(); | ||||||
1746 | rtl::Reference<LogicalFontInstance> pFontInstance; | ||||||
1747 | aNewContext.mpFont = nullptr; | ||||||
1748 | if (!rFontName.isEmpty()) | ||||||
1749 | { | ||||||
1750 | OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev(); | ||||||
1751 | Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() ); | ||||||
1752 | if ( !aSize.Height() ) | ||||||
1753 | { | ||||||
1754 | // only set default sizes if the font height in logical | ||||||
1755 | // coordinates equals 0 | ||||||
1756 | if ( rFont.GetFontSize().Height() ) | ||||||
1757 | aSize.setHeight( 1 ); | ||||||
1758 | else | ||||||
1759 | aSize.setHeight( (12*pFocusWin->mnDPIY)/72 ); | ||||||
1760 | } | ||||||
1761 | pFontInstance = pFocusWin->mxFontCache->GetFontInstance( pFocusWin->mxFontCollection.get(), | ||||||
1762 | rFont, aSize, static_cast<float>(aSize.Height()) ); | ||||||
1763 | if ( pFontInstance ) | ||||||
1764 | aNewContext.mpFont = pFontInstance; | ||||||
1765 | } | ||||||
1766 | aNewContext.mnOptions = rInputContext.GetOptions(); | ||||||
1767 | pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext ); | ||||||
1768 | } | ||||||
1769 | |||||||
1770 | void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink) | ||||||
1771 | { | ||||||
1772 | if (mpWindowImpl) // may be called after dispose | ||||||
1773 | { | ||||||
1774 | mpWindowImpl->maDumpAsPropertyTreeHdl = rLink; | ||||||
1775 | } | ||||||
1776 | } | ||||||
1777 | |||||||
1778 | void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink) | ||||||
1779 | { | ||||||
1780 | ImplGetFrame()->SetModalHierarchyHdl(rLink); | ||||||
1781 | } | ||||||
1782 | |||||||
1783 | void Window::SetParentToDefaultWindow() | ||||||
1784 | { | ||||||
1785 | Show(false); | ||||||
| |||||||
1786 | SetParent(ImplGetDefaultWindow()); | ||||||
| |||||||
1787 | } | ||||||
1788 | |||||||
1789 | KeyIndicatorState Window::GetIndicatorState() const | ||||||
1790 | { | ||||||
1791 | return mpWindowImpl->mpFrame->GetIndicatorState(); | ||||||
1792 | } | ||||||
1793 | |||||||
1794 | void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const | ||||||
1795 | { | ||||||
1796 | mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode); | ||||||
1797 | } | ||||||
1798 | |||||||
1799 | void Window::KeyInput( const KeyEvent& rKEvt ) | ||||||
1800 | { | ||||||
1801 | KeyCode cod = rKEvt.GetKeyCode (); | ||||||
1802 | bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel; | ||||||
1803 | |||||||
1804 | // do not respond to accelerators unless Alt or Ctrl is held */ | ||||||
1805 | if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219) | ||||||
1806 | { | ||||||
1807 | if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1)) | ||||||
1808 | return; | ||||||
1809 | } | ||||||
1810 | |||||||
1811 | NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt ); | ||||||
1812 | if ( !CompatNotify( aNEvt ) ) | ||||||
1813 | mpWindowImpl->mbKeyInput = true; | ||||||
1814 | } | ||||||
1815 | |||||||
1816 | void Window::KeyUp( const KeyEvent& rKEvt ) | ||||||
1817 | { | ||||||
1818 | NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt ); | ||||||
1819 | if ( !CompatNotify( aNEvt ) ) | ||||||
1820 | mpWindowImpl->mbKeyUp = true; | ||||||
1821 | } | ||||||
1822 | |||||||
1823 | void Window::Draw( OutputDevice*, const Point&, DrawFlags ) | ||||||
1824 | { | ||||||
1825 | } | ||||||
1826 | |||||||
1827 | void Window::Move() {} | ||||||
1828 | |||||||
1829 | void Window::Resize() {} | ||||||
1830 | |||||||
1831 | void Window::Activate() {} | ||||||
1832 | |||||||
1833 | void Window::Deactivate() {} | ||||||
1834 | |||||||
1835 | void Window::GetFocus() | ||||||
1836 | { | ||||||
1837 | if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) ) | ||||||
1838 | { | ||||||
1839 | VclPtr<vcl::Window> xWindow(this); | ||||||
1840 | mpWindowImpl->mpLastFocusWindow->GrabFocus(); | ||||||
1841 | if( xWindow->IsDisposed() ) | ||||||
1842 | return; | ||||||
1843 | } | ||||||
1844 | |||||||
1845 | NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this ); | ||||||
1846 | CompatNotify( aNEvt ); | ||||||
1847 | } | ||||||
1848 | |||||||
1849 | void Window::LoseFocus() | ||||||
1850 | { | ||||||
1851 | NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this ); | ||||||
1852 | CompatNotify( aNEvt ); | ||||||
1853 | } | ||||||
1854 | |||||||
1855 | void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink) | ||||||
1856 | { | ||||||
1857 | if (mpWindowImpl) // may be called after dispose | ||||||
1858 | { | ||||||
1859 | mpWindowImpl->maHelpRequestHdl = rLink; | ||||||
1860 | } | ||||||
1861 | } | ||||||
1862 | |||||||
1863 | void Window::RequestHelp( const HelpEvent& rHEvt ) | ||||||
1864 | { | ||||||
1865 | // if Balloon-Help is requested, show the balloon | ||||||
1866 | // with help text set | ||||||
1867 | if ( rHEvt.GetMode() & HelpEventMode::BALLOON ) | ||||||
1868 | { | ||||||
1869 | OUString rStr = GetHelpText(); | ||||||
1870 | if ( rStr.isEmpty() ) | ||||||
1871 | rStr = GetQuickHelpText(); | ||||||
1872 | if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() ) | ||||||
1873 | ImplGetParent()->RequestHelp( rHEvt ); | ||||||
1874 | else | ||||||
1875 | { | ||||||
1876 | Point aPos = GetPosPixel(); | ||||||
1877 | if ( ImplGetParent() && !ImplIsOverlapWindow() ) | ||||||
1878 | aPos = OutputToScreenPixel(Point(0, 0)); | ||||||
1879 | tools::Rectangle aRect( aPos, GetSizePixel() ); | ||||||
1880 | |||||||
1881 | Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr ); | ||||||
1882 | } | ||||||
1883 | } | ||||||
1884 | else if ( rHEvt.GetMode() & HelpEventMode::QUICK ) | ||||||
1885 | { | ||||||
1886 | const OUString& rStr = GetQuickHelpText(); | ||||||
1887 | if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() ) | ||||||
1888 | ImplGetParent()->RequestHelp( rHEvt ); | ||||||
1889 | else | ||||||
1890 | { | ||||||
1891 | Point aPos = GetPosPixel(); | ||||||
1892 | if ( ImplGetParent() && !ImplIsOverlapWindow() ) | ||||||
1893 | aPos = OutputToScreenPixel(Point(0, 0)); | ||||||
1894 | tools::Rectangle aRect( aPos, GetSizePixel() ); | ||||||
1895 | Help::ShowQuickHelp( this, aRect, rStr, QuickHelpFlags::CtrlText ); | ||||||
1896 | } | ||||||
1897 | } | ||||||
1898 | else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this)) | ||||||
1899 | { | ||||||
1900 | OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) ) ); | ||||||
1901 | if ( aStrHelpId.isEmpty() && ImplGetParent() ) | ||||||
1902 | ImplGetParent()->RequestHelp( rHEvt ); | ||||||
1903 | else | ||||||
1904 | { | ||||||
1905 | Help* pHelp = Application::GetHelp(); | ||||||
1906 | if ( pHelp ) | ||||||
1907 | { | ||||||
1908 | if( !aStrHelpId.isEmpty() ) | ||||||
1909 | pHelp->Start( aStrHelpId, this ); | ||||||
1910 | else | ||||||
1911 | pHelp->Start( OOO_HELP_INDEX".help:index", this ); | ||||||
1912 | } | ||||||
1913 | } | ||||||
1914 | } | ||||||
1915 | } | ||||||
1916 | |||||||
1917 | void Window::Command( const CommandEvent& rCEvt ) | ||||||
1918 | { | ||||||
1919 | CallEventListeners( VclEventId::WindowCommand, const_cast<CommandEvent *>(&rCEvt) ); | ||||||
1920 | |||||||
1921 | NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt ); | ||||||
1922 | if ( !CompatNotify( aNEvt ) ) | ||||||
1923 | mpWindowImpl->mbCommand = true; | ||||||
1924 | } | ||||||
1925 | |||||||
1926 | void Window::Tracking( const TrackingEvent& rTEvt ) | ||||||
1927 | { | ||||||
1928 | |||||||
1929 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
1930 | if( pWrapper ) | ||||||
1931 | pWrapper->Tracking( rTEvt ); | ||||||
1932 | } | ||||||
1933 | |||||||
1934 | void Window::StateChanged(StateChangedType eType) | ||||||
1935 | { | ||||||
1936 | switch (eType) | ||||||
1937 | { | ||||||
1938 | //stuff that doesn't invalidate the layout | ||||||
1939 | case StateChangedType::ControlForeground: | ||||||
1940 | case StateChangedType::ControlBackground: | ||||||
1941 | case StateChangedType::UpdateMode: | ||||||
1942 | case StateChangedType::ReadOnly: | ||||||
1943 | case StateChangedType::Enable: | ||||||
1944 | case StateChangedType::State: | ||||||
1945 | case StateChangedType::Data: | ||||||
1946 | case StateChangedType::InitShow: | ||||||
1947 | case StateChangedType::ControlFocus: | ||||||
1948 | break; | ||||||
1949 | //stuff that does invalidate the layout | ||||||
1950 | default: | ||||||
1951 | queue_resize(eType); | ||||||
1952 | break; | ||||||
1953 | } | ||||||
1954 | } | ||||||
1955 | |||||||
1956 | void Window::SetStyle( WinBits nStyle ) | ||||||
1957 | { | ||||||
1958 | if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle ) | ||||||
1959 | { | ||||||
1960 | mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle; | ||||||
1961 | mpWindowImpl->mnStyle = nStyle; | ||||||
1962 | CompatStateChanged( StateChangedType::Style ); | ||||||
1963 | } | ||||||
1964 | } | ||||||
1965 | |||||||
1966 | void Window::SetExtendedStyle( WindowExtendedStyle nExtendedStyle ) | ||||||
1967 | { | ||||||
1968 | |||||||
1969 | if ( mpWindowImpl->mnExtendedStyle == nExtendedStyle ) | ||||||
1970 | return; | ||||||
1971 | |||||||
1972 | vcl::Window* pWindow = ImplGetBorderWindow(); | ||||||
1973 | if( ! pWindow ) | ||||||
1974 | pWindow = this; | ||||||
1975 | if( pWindow->mpWindowImpl->mbFrame ) | ||||||
1976 | { | ||||||
1977 | SalExtStyle nExt = 0; | ||||||
1978 | if( nExtendedStyle & WindowExtendedStyle::Document ) | ||||||
1979 | nExt |= SAL_FRAME_EXT_STYLE_DOCUMENTSalExtStyle(0x00000001); | ||||||
1980 | if( nExtendedStyle & WindowExtendedStyle::DocModified ) | ||||||
1981 | nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIEDSalExtStyle(0x00000002); | ||||||
1982 | |||||||
1983 | pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt ); | ||||||
1984 | } | ||||||
1985 | mpWindowImpl->mnExtendedStyle = nExtendedStyle; | ||||||
1986 | } | ||||||
1987 | |||||||
1988 | void Window::SetBorderStyle( WindowBorderStyle nBorderStyle ) | ||||||
1989 | { | ||||||
1990 | |||||||
1991 | if ( !mpWindowImpl->mpBorderWindow ) | ||||||
1992 | return; | ||||||
1993 | |||||||
1994 | if( nBorderStyle == WindowBorderStyle::REMOVEBORDER && | ||||||
1995 | ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && | ||||||
1996 | mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent | ||||||
1997 | ) | ||||||
1998 | { | ||||||
1999 | // this is a little awkward: some controls (e.g. svtools ProgressBar) | ||||||
2000 | // cannot avoid getting constructed with WB_BORDER but want to disable | ||||||
2001 | // borders in case of NWF drawing. So they need a method to remove their border window | ||||||
2002 | VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow; | ||||||
2003 | // remove us as border window's client | ||||||
2004 | pBorderWin->mpWindowImpl->mpClientWindow = nullptr; | ||||||
2005 | mpWindowImpl->mpBorderWindow = nullptr; | ||||||
2006 | mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent; | ||||||
2007 | // reparent us above the border window | ||||||
2008 | SetParent( pBorderWin->mpWindowImpl->mpParent ); | ||||||
2009 | // set us to the position and size of our previous border | ||||||
2010 | Point aBorderPos( pBorderWin->GetPosPixel() ); | ||||||
2011 | Size aBorderSize( pBorderWin->GetSizePixel() ); | ||||||
2012 | setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() ); | ||||||
2013 | // release border window | ||||||
2014 | pBorderWin.disposeAndClear(); | ||||||
2015 | |||||||
2016 | // set new style bits | ||||||
2017 | SetStyle( GetStyle() & (~WB_BORDER) ); | ||||||
2018 | } | ||||||
2019 | else | ||||||
2020 | { | ||||||
2021 | if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW ) | ||||||
2022 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle ); | ||||||
2023 | else | ||||||
2024 | mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle ); | ||||||
2025 | } | ||||||
2026 | } | ||||||
2027 | |||||||
2028 | WindowBorderStyle Window::GetBorderStyle() const | ||||||
2029 | { | ||||||
2030 | |||||||
2031 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2032 | { | ||||||
2033 | if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW ) | ||||||
2034 | return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle(); | ||||||
2035 | else | ||||||
2036 | return mpWindowImpl->mpBorderWindow->GetBorderStyle(); | ||||||
2037 | } | ||||||
2038 | |||||||
2039 | return WindowBorderStyle::NONE; | ||||||
2040 | } | ||||||
2041 | |||||||
2042 | long Window::CalcTitleWidth() const | ||||||
2043 | { | ||||||
2044 | |||||||
2045 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2046 | { | ||||||
2047 | if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW ) | ||||||
2048 | return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth(); | ||||||
2049 | else | ||||||
2050 | return mpWindowImpl->mpBorderWindow->CalcTitleWidth(); | ||||||
2051 | } | ||||||
2052 | else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) ) | ||||||
2053 | { | ||||||
2054 | // we guess the width for frame windows as we do not know the | ||||||
2055 | // border of external dialogs | ||||||
2056 | const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); | ||||||
2057 | vcl::Font aFont = GetFont(); | ||||||
2058 | const_cast<vcl::Window*>(this)->SetPointFont(*const_cast<Window*>(this), rStyleSettings.GetTitleFont()); | ||||||
2059 | long nTitleWidth = GetTextWidth( GetText() ); | ||||||
2060 | const_cast<vcl::Window*>(this)->SetFont( aFont ); | ||||||
2061 | nTitleWidth += rStyleSettings.GetTitleHeight() * 3; | ||||||
2062 | nTitleWidth += StyleSettings::GetBorderSize() * 2; | ||||||
2063 | nTitleWidth += 10; | ||||||
2064 | return nTitleWidth; | ||||||
2065 | } | ||||||
2066 | |||||||
2067 | return 0; | ||||||
2068 | } | ||||||
2069 | |||||||
2070 | void Window::SetInputContext( const InputContext& rInputContext ) | ||||||
2071 | { | ||||||
2072 | |||||||
2073 | mpWindowImpl->maInputContext = rInputContext; | ||||||
2074 | if ( !mpWindowImpl->mbInFocusHdl && HasFocus() ) | ||||||
2075 | ImplNewInputContext(); | ||||||
2076 | } | ||||||
2077 | |||||||
2078 | void Window::PostExtTextInputEvent(VclEventId nType, const OUString& rText) | ||||||
2079 | { | ||||||
2080 | switch (nType) | ||||||
2081 | { | ||||||
2082 | case VclEventId::ExtTextInput: | ||||||
2083 | { | ||||||
2084 | std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]); | ||||||
2085 | for (int i = 0; i < rText.getLength(); ++i) { | ||||||
2086 | pAttr[i] = ExtTextInputAttr::Underline; | ||||||
2087 | } | ||||||
2088 | SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE(sal_uInt16(0x0002)) }; | ||||||
2089 | ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent); | ||||||
2090 | } | ||||||
2091 | break; | ||||||
2092 | case VclEventId::EndExtTextInput: | ||||||
2093 | ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr); | ||||||
2094 | break; | ||||||
2095 | default: | ||||||
2096 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 2096, __extension__ __PRETTY_FUNCTION__)); | ||||||
2097 | } | ||||||
2098 | } | ||||||
2099 | |||||||
2100 | void Window::EndExtTextInput() | ||||||
2101 | { | ||||||
2102 | if ( mpWindowImpl->mbExtTextInput ) | ||||||
2103 | ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete ); | ||||||
2104 | } | ||||||
2105 | |||||||
2106 | void Window::SetCursorRect( const tools::Rectangle* pRect, long nExtTextInputWidth ) | ||||||
2107 | { | ||||||
2108 | |||||||
2109 | ImplWinData* pWinData = ImplGetWinData(); | ||||||
2110 | if ( pWinData->mpCursorRect ) | ||||||
2111 | { | ||||||
2112 | if ( pRect ) | ||||||
2113 | pWinData->mpCursorRect = *pRect; | ||||||
2114 | else | ||||||
2115 | pWinData->mpCursorRect.reset(); | ||||||
2116 | } | ||||||
2117 | else | ||||||
2118 | { | ||||||
2119 | if ( pRect ) | ||||||
2120 | pWinData->mpCursorRect = *pRect; | ||||||
2121 | } | ||||||
2122 | |||||||
2123 | pWinData->mnCursorExtWidth = nExtTextInputWidth; | ||||||
2124 | |||||||
2125 | } | ||||||
2126 | |||||||
2127 | const tools::Rectangle* Window::GetCursorRect() const | ||||||
2128 | { | ||||||
2129 | |||||||
2130 | ImplWinData* pWinData = ImplGetWinData(); | ||||||
2131 | return pWinData->mpCursorRect ? &*pWinData->mpCursorRect : nullptr; | ||||||
2132 | } | ||||||
2133 | |||||||
2134 | long Window::GetCursorExtTextInputWidth() const | ||||||
2135 | { | ||||||
2136 | |||||||
2137 | ImplWinData* pWinData = ImplGetWinData(); | ||||||
2138 | return pWinData->mnCursorExtWidth; | ||||||
2139 | } | ||||||
2140 | |||||||
2141 | void Window::SetCompositionCharRect( const tools::Rectangle* pRect, long nCompositionLength, bool bVertical ) { | ||||||
2142 | |||||||
2143 | ImplWinData* pWinData = ImplGetWinData(); | ||||||
2144 | pWinData->mpCompositionCharRects.reset(); | ||||||
2145 | pWinData->mbVertical = bVertical; | ||||||
2146 | pWinData->mnCompositionCharRects = nCompositionLength; | ||||||
2147 | if ( pRect && (nCompositionLength > 0) ) | ||||||
2148 | { | ||||||
2149 | pWinData->mpCompositionCharRects.reset( new tools::Rectangle[nCompositionLength] ); | ||||||
2150 | for (long i = 0; i < nCompositionLength; ++i) | ||||||
2151 | pWinData->mpCompositionCharRects[i] = pRect[i]; | ||||||
2152 | } | ||||||
2153 | } | ||||||
2154 | |||||||
2155 | void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren ) | ||||||
2156 | { | ||||||
2157 | rAllChildren.push_back( this ); | ||||||
2158 | |||||||
2159 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
2160 | while ( pChild ) | ||||||
2161 | { | ||||||
2162 | pChild->CollectChildren( rAllChildren ); | ||||||
2163 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
2164 | } | ||||||
2165 | } | ||||||
2166 | |||||||
2167 | void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont) | ||||||
2168 | { | ||||||
2169 | vcl::Font aFont = rFont; | ||||||
2170 | ImplPointToLogic(rRenderContext, aFont); | ||||||
2171 | rRenderContext.SetFont(aFont); | ||||||
2172 | } | ||||||
2173 | |||||||
2174 | vcl::Font Window::GetPointFont(vcl::RenderContext const & rRenderContext) const | ||||||
2175 | { | ||||||
2176 | vcl::Font aFont = rRenderContext.GetFont(); | ||||||
2177 | ImplLogicToPoint(rRenderContext, aFont); | ||||||
2178 | return aFont; | ||||||
2179 | } | ||||||
2180 | |||||||
2181 | void Window::Show(bool bVisible, ShowFlags nFlags) | ||||||
2182 | { | ||||||
2183 | if ( IsDisposed() || mpWindowImpl->mbVisible == bVisible ) | ||||||
2184 | return; | ||||||
2185 | |||||||
2186 | VclPtr<vcl::Window> xWindow(this); | ||||||
2187 | |||||||
2188 | bool bRealVisibilityChanged = false; | ||||||
2189 | mpWindowImpl->mbVisible = bVisible; | ||||||
2190 | |||||||
2191 | if ( !bVisible
| ||||||
2192 | { | ||||||
2193 | ImplHideAllOverlaps(); | ||||||
2194 | if( xWindow->IsDisposed() ) | ||||||
2195 | return; | ||||||
2196 | |||||||
2197 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2198 | { | ||||||
2199 | bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate; | ||||||
2200 | if ( mpWindowImpl->mbNoParentUpdate ) | ||||||
2201 | mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true; | ||||||
2202 | mpWindowImpl->mpBorderWindow->Show( false, nFlags ); | ||||||
2203 | mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate; | ||||||
2204 | } | ||||||
2205 | else if ( mpWindowImpl->mbFrame ) | ||||||
2206 | { | ||||||
2207 | mpWindowImpl->mbSuppressAccessibilityEvents = true; | ||||||
2208 | mpWindowImpl->mpFrame->Show( false ); | ||||||
2209 | } | ||||||
2210 | |||||||
2211 | CompatStateChanged( StateChangedType::Visible ); | ||||||
2212 | |||||||
2213 | if ( mpWindowImpl->mbReallyVisible ) | ||||||
2214 | { | ||||||
2215 | if ( mpWindowImpl->mbInitWinClipRegion ) | ||||||
2216 | ImplInitWinClipRegion(); | ||||||
2217 | |||||||
2218 | vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion; | ||||||
2219 | |||||||
2220 | if( xWindow->IsDisposed() ) | ||||||
2221 | return; | ||||||
2222 | |||||||
2223 | bRealVisibilityChanged = mpWindowImpl->mbReallyVisible; | ||||||
2224 | ImplResetReallyVisible(); | ||||||
2225 | ImplSetClipFlag(); | ||||||
2226 | |||||||
2227 | if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame ) | ||||||
2228 | { | ||||||
2229 | // convert focus | ||||||
2230 | if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() ) | ||||||
2231 | { | ||||||
2232 | if ( mpWindowImpl->mpOverlapWindow->IsEnabled() && | ||||||
2233 | mpWindowImpl->mpOverlapWindow->IsInputEnabled() && | ||||||
2234 | ! mpWindowImpl->mpOverlapWindow->IsInModalMode() | ||||||
2235 | ) | ||||||
2236 | mpWindowImpl->mpOverlapWindow->GrabFocus(); | ||||||
2237 | } | ||||||
2238 | } | ||||||
2239 | |||||||
2240 | if ( !mpWindowImpl->mbFrame ) | ||||||
2241 | { | ||||||
2242 | if (mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget) | ||||||
2243 | { | ||||||
2244 | /* | ||||||
2245 | * #i48371# native theming: some themes draw outside the control | ||||||
2246 | * area we tell them to (bad thing, but we cannot do much about it ). | ||||||
2247 | * On hiding these controls they get invalidated with their window rectangle | ||||||
2248 | * which leads to the parts outside the control area being left and not | ||||||
2249 | * invalidated. Workaround: invalidate an area on the parent, too | ||||||
2250 | */ | ||||||
2251 | const int workaround_border = 5; | ||||||
2252 | tools::Rectangle aBounds( aInvRegion.GetBoundRect() ); | ||||||
2253 | aBounds.AdjustLeft( -workaround_border ); | ||||||
2254 | aBounds.AdjustTop( -workaround_border ); | ||||||
2255 | aBounds.AdjustRight(workaround_border ); | ||||||
2256 | aBounds.AdjustBottom(workaround_border ); | ||||||
2257 | aInvRegion = aBounds; | ||||||
2258 | } | ||||||
2259 | if ( !mpWindowImpl->mbNoParentUpdate ) | ||||||
2260 | { | ||||||
2261 | if ( !aInvRegion.IsEmpty() ) | ||||||
2262 | ImplInvalidateParentFrameRegion( aInvRegion ); | ||||||
2263 | } | ||||||
2264 | ImplGenerateMouseMove(); | ||||||
2265 | } | ||||||
2266 | } | ||||||
2267 | } | ||||||
2268 | else | ||||||
2269 | { | ||||||
2270 | // inherit native widget flag for form controls | ||||||
2271 | // required here, because frames never show up in the child hierarchy - which should be fixed... | ||||||
2272 | // eg, the drop down of a combobox which is a system floating window | ||||||
2273 | if( mpWindowImpl->mbFrame && GetParent() && GetParent()->IsCompoundControl() && | ||||||
2274 | GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() && | ||||||
2275 | !(GetStyle() & WB_TOOLTIPWIN) ) | ||||||
2276 | { | ||||||
2277 | EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() ); | ||||||
2278 | } | ||||||
2279 | |||||||
2280 | if ( mpWindowImpl->mbCallMove ) | ||||||
2281 | { | ||||||
2282 | ImplCallMove(); | ||||||
2283 | } | ||||||
2284 | if ( mpWindowImpl->mbCallResize ) | ||||||
2285 | { | ||||||
2286 | ImplCallResize(); | ||||||
2287 | } | ||||||
2288 | |||||||
2289 | CompatStateChanged( StateChangedType::Visible ); | ||||||
2290 | |||||||
2291 | vcl::Window* pTestParent; | ||||||
2292 | if ( ImplIsOverlapWindow() ) | ||||||
2293 | pTestParent = mpWindowImpl->mpOverlapWindow; | ||||||
2294 | else | ||||||
2295 | pTestParent = ImplGetParent(); | ||||||
2296 | if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible ) | ||||||
2297 | { | ||||||
2298 | // if a window becomes visible, send all child windows a StateChange, | ||||||
2299 | // such that these can initialise themselves | ||||||
2300 | ImplCallInitShow(); | ||||||
2301 | |||||||
2302 | // If it is a SystemWindow it automatically pops up on top of | ||||||
2303 | // all other windows if needed. | ||||||
2304 | if ( ImplIsOverlapWindow() && !(nFlags & ShowFlags::NoActivate) ) | ||||||
2305 | { | ||||||
2306 | ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE ); | ||||||
2307 | ImplFocusToTop( ToTopFlags::NONE, false ); | ||||||
2308 | } | ||||||
2309 | |||||||
2310 | // adjust mpWindowImpl->mbReallyVisible | ||||||
2311 | bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible; | ||||||
2312 | ImplSetReallyVisible(); | ||||||
2313 | |||||||
2314 | // assure clip rectangles will be recalculated | ||||||
2315 | ImplSetClipFlag(); | ||||||
2316 | |||||||
2317 | if ( !mpWindowImpl->mbFrame ) | ||||||
2318 | { | ||||||
2319 | InvalidateFlags nInvalidateFlags = InvalidateFlags::Children; | ||||||
2320 | if( ! IsPaintTransparent() ) | ||||||
2321 | nInvalidateFlags |= InvalidateFlags::NoTransparent; | ||||||
2322 | ImplInvalidate( nullptr, nInvalidateFlags ); | ||||||
2323 | ImplGenerateMouseMove(); | ||||||
2324 | } | ||||||
2325 | } | ||||||
2326 | |||||||
2327 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2328 | mpWindowImpl->mpBorderWindow->Show( true, nFlags ); | ||||||
2329 | else if ( mpWindowImpl->mbFrame ) | ||||||
2330 | { | ||||||
2331 | // #106431#, hide SplashScreen | ||||||
2332 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
2333 | if ( !pSVData->mpIntroWindow ) | ||||||
2334 | { | ||||||
2335 | // The right way would be just to call this (not even in the 'if') | ||||||
2336 | auto pApp = GetpApp(); | ||||||
2337 | if ( pApp ) | ||||||
2338 | pApp->InitFinished(); | ||||||
2339 | } | ||||||
2340 | else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) ) | ||||||
2341 | { | ||||||
2342 | // ... but the VCL splash is broken, and it needs this | ||||||
2343 | // (for ./soffice .uno:NewDoc) | ||||||
2344 | pSVData->mpIntroWindow->Hide(); | ||||||
2345 | } | ||||||
2346 | |||||||
2347 | //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated"); | ||||||
2348 | mpWindowImpl->mbSuppressAccessibilityEvents = false; | ||||||
2349 | |||||||
2350 | mpWindowImpl->mbPaintFrame = true; | ||||||
2351 | if (!Application::IsHeadlessModeEnabled()) | ||||||
2352 | { | ||||||
2353 | bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange)); | ||||||
2354 | mpWindowImpl->mpFrame->Show( true, bNoActivate ); | ||||||
2355 | } | ||||||
2356 | if( xWindow->IsDisposed() ) | ||||||
2357 | return; | ||||||
2358 | |||||||
2359 | // Query the correct size of the window, if we are waiting for | ||||||
2360 | // a system resize | ||||||
2361 | if ( mpWindowImpl->mbWaitSystemResize ) | ||||||
2362 | { | ||||||
2363 | long nOutWidth; | ||||||
2364 | long nOutHeight; | ||||||
2365 | mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight ); | ||||||
2366 | ImplHandleResize( this, nOutWidth, nOutHeight ); | ||||||
2367 | } | ||||||
2368 | |||||||
2369 | if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel()) | ||||||
2370 | // Make sure that the buffer size matches the window size, even if no resize was needed. | ||||||
2371 | mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel()); | ||||||
2372 | } | ||||||
2373 | |||||||
2374 | if( xWindow->IsDisposed() ) | ||||||
2375 | return; | ||||||
2376 | |||||||
2377 | ImplShowAllOverlaps(); | ||||||
2378 | } | ||||||
2379 | |||||||
2380 | if( xWindow->IsDisposed() ) | ||||||
2381 | return; | ||||||
2382 | |||||||
2383 | // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge | ||||||
2384 | // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that | ||||||
2385 | // we re-use the SHOW/HIDE events this way, with this particular semantics). | ||||||
2386 | // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we | ||||||
2387 | // now only notify with a NULL data pointer, for all other clients except the access bridge. | ||||||
2388 | if ( !bRealVisibilityChanged ) | ||||||
2389 | CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide ); | ||||||
2390 | if( xWindow->IsDisposed() ) | ||||||
2391 | return; | ||||||
2392 | |||||||
2393 | } | ||||||
2394 | |||||||
2395 | Size Window::GetSizePixel() const | ||||||
2396 | { | ||||||
2397 | if (!mpWindowImpl) | ||||||
2398 | { | ||||||
2399 | SAL_WARN("vcl.layout", "WTF no windowimpl")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "vcl.layout")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "WTF no windowimpl") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "2399" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "WTF no windowimpl"), 0); } else { :: std::ostringstream sal_detail_stream; sal_detail_stream << "WTF no windowimpl"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("vcl.layout"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "2399" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "WTF no windowimpl") == 1) { ::sal_detail_log( (:: SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.layout"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "2399" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "WTF no windowimpl"), 0); } else { :: std::ostringstream sal_detail_stream; sal_detail_stream << "WTF no windowimpl"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("vcl.layout"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "2399" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
2400 | return Size(0,0); | ||||||
2401 | } | ||||||
2402 | |||||||
2403 | // #i43257# trigger pending resize handler to assure correct window sizes | ||||||
2404 | if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() ) | ||||||
2405 | { | ||||||
2406 | VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) ); | ||||||
2407 | mpWindowImpl->mpFrameData->maResizeIdle.Stop(); | ||||||
2408 | mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr ); | ||||||
2409 | if( xWindow->IsDisposed() ) | ||||||
2410 | return Size(0,0); | ||||||
2411 | } | ||||||
2412 | |||||||
2413 | return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder, | ||||||
2414 | mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder ); | ||||||
2415 | } | ||||||
2416 | |||||||
2417 | void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, | ||||||
2418 | sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const | ||||||
2419 | { | ||||||
2420 | rLeftBorder = mpWindowImpl->mnLeftBorder; | ||||||
2421 | rTopBorder = mpWindowImpl->mnTopBorder; | ||||||
2422 | rRightBorder = mpWindowImpl->mnRightBorder; | ||||||
2423 | rBottomBorder = mpWindowImpl->mnBottomBorder; | ||||||
2424 | } | ||||||
2425 | |||||||
2426 | void Window::Enable( bool bEnable, bool bChild ) | ||||||
2427 | { | ||||||
2428 | if ( IsDisposed() ) | ||||||
2429 | return; | ||||||
2430 | |||||||
2431 | if ( !bEnable ) | ||||||
2432 | { | ||||||
2433 | // the tracking mode will be stopped or the capture will be stolen | ||||||
2434 | // when a window is disabled, | ||||||
2435 | if ( IsTracking() ) | ||||||
2436 | EndTracking( TrackingEventFlags::Cancel ); | ||||||
2437 | if ( IsMouseCaptured() ) | ||||||
2438 | ReleaseMouse(); | ||||||
2439 | // try to pass focus to the next control | ||||||
2440 | // if the window has focus and is contained in the dialog control | ||||||
2441 | // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow(). | ||||||
2442 | // Otherwise ImplDlgCtrlNextWindow() should be used | ||||||
2443 | if ( HasFocus() ) | ||||||
2444 | ImplDlgCtrlNextWindow(); | ||||||
2445 | } | ||||||
2446 | |||||||
2447 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2448 | { | ||||||
2449 | mpWindowImpl->mpBorderWindow->Enable( bEnable, false ); | ||||||
2450 | if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) && | ||||||
2451 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow ) | ||||||
2452 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable ); | ||||||
2453 | } | ||||||
2454 | |||||||
2455 | // #i56102# restore app focus win in case the | ||||||
2456 | // window was disabled when the frame focus changed | ||||||
2457 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
2458 | if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr | ||||||
2459 | && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this) | ||||||
2460 | pSVData->mpWinData->mpFocusWin = this; | ||||||
2461 | |||||||
2462 | if ( mpWindowImpl->mbDisabled != !bEnable ) | ||||||
2463 | { | ||||||
2464 | mpWindowImpl->mbDisabled = !bEnable; | ||||||
2465 | if ( mpWindowImpl->mpSysObj ) | ||||||
2466 | mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled ); | ||||||
2467 | CompatStateChanged( StateChangedType::Enable ); | ||||||
2468 | |||||||
2469 | CallEventListeners( bEnable ? VclEventId::WindowEnabled : VclEventId::WindowDisabled ); | ||||||
2470 | } | ||||||
2471 | |||||||
2472 | if ( bChild ) | ||||||
2473 | { | ||||||
2474 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
2475 | while ( pChild ) | ||||||
2476 | { | ||||||
2477 | pChild->Enable( bEnable, bChild ); | ||||||
2478 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
2479 | } | ||||||
2480 | } | ||||||
2481 | |||||||
2482 | if ( IsReallyVisible() ) | ||||||
2483 | ImplGenerateMouseMove(); | ||||||
2484 | } | ||||||
2485 | |||||||
2486 | void Window::EnableInput( bool bEnable, bool bChild ) | ||||||
2487 | { | ||||||
2488 | if (!mpWindowImpl) | ||||||
2489 | return; | ||||||
2490 | |||||||
2491 | bool bNotify = (bEnable != mpWindowImpl->mbInputDisabled); | ||||||
2492 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2493 | { | ||||||
2494 | mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false ); | ||||||
2495 | if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) && | ||||||
2496 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow ) | ||||||
2497 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable ); | ||||||
2498 | } | ||||||
2499 | |||||||
2500 | if ( (!bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) || bEnable ) | ||||||
2501 | { | ||||||
2502 | // automatically stop the tracking mode or steal capture | ||||||
2503 | // if the window is disabled | ||||||
2504 | if ( !bEnable ) | ||||||
2505 | { | ||||||
2506 | if ( IsTracking() ) | ||||||
2507 | EndTracking( TrackingEventFlags::Cancel ); | ||||||
2508 | if ( IsMouseCaptured() ) | ||||||
2509 | ReleaseMouse(); | ||||||
2510 | } | ||||||
2511 | |||||||
2512 | if ( mpWindowImpl->mbInputDisabled != !bEnable ) | ||||||
2513 | { | ||||||
2514 | mpWindowImpl->mbInputDisabled = !bEnable; | ||||||
2515 | if ( mpWindowImpl->mpSysObj ) | ||||||
2516 | mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable ); | ||||||
2517 | } | ||||||
2518 | } | ||||||
2519 | |||||||
2520 | // #i56102# restore app focus win in case the | ||||||
2521 | // window was disabled when the frame focus changed | ||||||
2522 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
2523 | if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr | ||||||
2524 | && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this) | ||||||
2525 | pSVData->mpWinData->mpFocusWin = this; | ||||||
2526 | |||||||
2527 | if ( bChild ) | ||||||
2528 | { | ||||||
2529 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
2530 | while ( pChild ) | ||||||
2531 | { | ||||||
2532 | pChild->EnableInput( bEnable, bChild ); | ||||||
2533 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
2534 | } | ||||||
2535 | } | ||||||
2536 | |||||||
2537 | if ( IsReallyVisible() ) | ||||||
2538 | ImplGenerateMouseMove(); | ||||||
2539 | |||||||
2540 | // #104827# notify parent | ||||||
2541 | if ( bNotify && bEnable ) | ||||||
2542 | { | ||||||
2543 | NotifyEvent aNEvt( MouseNotifyEvent::INPUTENABLE, this ); | ||||||
2544 | CompatNotify( aNEvt ); | ||||||
2545 | } | ||||||
2546 | } | ||||||
2547 | |||||||
2548 | void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow ) | ||||||
2549 | { | ||||||
2550 | if (!mpWindowImpl) | ||||||
2551 | return; | ||||||
2552 | |||||||
2553 | EnableInput( bEnable ); | ||||||
2554 | |||||||
2555 | // pExecuteWindow is the first Overlap-Frame --> if this | ||||||
2556 | // shouldn't be the case, then this must be changed in dialog.cxx | ||||||
2557 | if( pExcludeWindow ) | ||||||
2558 | pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow(); | ||||||
2559 | vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap; | ||||||
2560 | while ( pSysWin ) | ||||||
2561 | { | ||||||
2562 | // Is Window in the path from this window | ||||||
2563 | if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) ) | ||||||
2564 | { | ||||||
2565 | // Is Window not in the exclude window path or not the | ||||||
2566 | // exclude window, then change the status | ||||||
2567 | if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) ) | ||||||
2568 | pSysWin->EnableInput( bEnable ); | ||||||
2569 | } | ||||||
2570 | pSysWin = pSysWin->mpWindowImpl->mpNextOverlap; | ||||||
2571 | } | ||||||
2572 | |||||||
2573 | // enable/disable floating system windows as well | ||||||
2574 | vcl::Window* pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame; | ||||||
2575 | while ( pFrameWin ) | ||||||
2576 | { | ||||||
2577 | if( pFrameWin->ImplIsFloatingWindow() ) | ||||||
2578 | { | ||||||
2579 | // Is Window in the path from this window | ||||||
2580 | if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) ) | ||||||
2581 | { | ||||||
2582 | // Is Window not in the exclude window path or not the | ||||||
2583 | // exclude window, then change the status | ||||||
2584 | if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) ) | ||||||
2585 | pFrameWin->EnableInput( bEnable ); | ||||||
2586 | } | ||||||
2587 | } | ||||||
2588 | pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
2589 | } | ||||||
2590 | |||||||
2591 | // the same for ownerdraw floating windows | ||||||
2592 | if( !mpWindowImpl->mbFrame ) | ||||||
2593 | return; | ||||||
2594 | |||||||
2595 | ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList; | ||||||
2596 | for (auto const& elem : rList) | ||||||
2597 | { | ||||||
2598 | // Is Window in the path from this window | ||||||
2599 | if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) ) | ||||||
2600 | { | ||||||
2601 | // Is Window not in the exclude window path or not the | ||||||
2602 | // exclude window, then change the status | ||||||
2603 | if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) ) | ||||||
2604 | elem->EnableInput( bEnable ); | ||||||
2605 | } | ||||||
2606 | } | ||||||
2607 | } | ||||||
2608 | |||||||
2609 | void Window::AlwaysEnableInput( bool bAlways, bool bChild ) | ||||||
2610 | { | ||||||
2611 | |||||||
2612 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2613 | mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false ); | ||||||
2614 | |||||||
2615 | if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled ) | ||||||
2616 | { | ||||||
2617 | mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled; | ||||||
2618 | EnableInput(true, false); | ||||||
2619 | } | ||||||
2620 | else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled ) | ||||||
2621 | { | ||||||
2622 | mpWindowImpl->meAlwaysInputMode = AlwaysInputNone; | ||||||
2623 | } | ||||||
2624 | |||||||
2625 | if ( bChild ) | ||||||
2626 | { | ||||||
2627 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
2628 | while ( pChild ) | ||||||
2629 | { | ||||||
2630 | pChild->AlwaysEnableInput( bAlways, bChild ); | ||||||
2631 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
2632 | } | ||||||
2633 | } | ||||||
2634 | } | ||||||
2635 | |||||||
2636 | void Window::SetActivateMode( ActivateModeFlags nMode ) | ||||||
2637 | { | ||||||
2638 | |||||||
2639 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
2640 | mpWindowImpl->mpBorderWindow->SetActivateMode( nMode ); | ||||||
2641 | |||||||
2642 | if ( mpWindowImpl->mnActivateMode == nMode ) | ||||||
2643 | return; | ||||||
2644 | |||||||
2645 | mpWindowImpl->mnActivateMode = nMode; | ||||||
2646 | |||||||
2647 | // possibly trigger Deactivate/Activate | ||||||
2648 | if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE ) | ||||||
2649 | { | ||||||
2650 | if ( (mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW)) && | ||||||
2651 | !HasChildPathFocus( true ) ) | ||||||
2652 | { | ||||||
2653 | mpWindowImpl->mbActive = false; | ||||||
2654 | Deactivate(); | ||||||
2655 | } | ||||||
2656 | } | ||||||
2657 | else | ||||||
2658 | { | ||||||
2659 | if ( !mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW) ) | ||||||
2660 | { | ||||||
2661 | mpWindowImpl->mbActive = true; | ||||||
2662 | Activate(); | ||||||
2663 | } | ||||||
2664 | } | ||||||
2665 | } | ||||||
2666 | |||||||
2667 | void Window::setPosSizePixel( long nX, long nY, | ||||||
2668 | long nWidth, long nHeight, PosSizeFlags nFlags ) | ||||||
2669 | { | ||||||
2670 | bool bHasValidSize = !mpWindowImpl->mbDefSize; | ||||||
2671 | |||||||
2672 | if ( nFlags & PosSizeFlags::Pos ) | ||||||
2673 | mpWindowImpl->mbDefPos = false; | ||||||
2674 | if ( nFlags & PosSizeFlags::Size ) | ||||||
2675 | mpWindowImpl->mbDefSize = false; | ||||||
2676 | |||||||
2677 | // The top BorderWindow is the window which is to be positioned | ||||||
2678 | VclPtr<vcl::Window> pWindow = this; | ||||||
2679 | while ( pWindow->mpWindowImpl->mpBorderWindow ) | ||||||
2680 | pWindow = pWindow->mpWindowImpl->mpBorderWindow; | ||||||
2681 | |||||||
2682 | if ( pWindow->mpWindowImpl->mbFrame ) | ||||||
2683 | { | ||||||
2684 | // Note: if we're positioning a frame, the coordinates are interpreted | ||||||
2685 | // as being the top-left corner of the window's client area and NOT | ||||||
2686 | // as the position of the border ! (due to limitations of several UNIX window managers) | ||||||
2687 | long nOldWidth = pWindow->mnOutWidth; | ||||||
2688 | |||||||
2689 | if ( !(nFlags & PosSizeFlags::Width) ) | ||||||
2690 | nWidth = pWindow->mnOutWidth; | ||||||
2691 | if ( !(nFlags & PosSizeFlags::Height) ) | ||||||
2692 | nHeight = pWindow->mnOutHeight; | ||||||
2693 | |||||||
2694 | sal_uInt16 nSysFlags=0; | ||||||
2695 | VclPtr<vcl::Window> pParent = GetParent(); | ||||||
2696 | VclPtr<vcl::Window> pWinParent = pWindow->GetParent(); | ||||||
2697 | |||||||
2698 | if( nFlags & PosSizeFlags::Width ) | ||||||
2699 | nSysFlags |= SAL_FRAME_POSSIZE_WIDTH(sal_uInt16(0x0004)); | ||||||
2700 | if( nFlags & PosSizeFlags::Height ) | ||||||
2701 | nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT(sal_uInt16(0x0008)); | ||||||
2702 | if( nFlags & PosSizeFlags::X ) | ||||||
2703 | { | ||||||
2704 | nSysFlags |= SAL_FRAME_POSSIZE_X(sal_uInt16(0x0001)); | ||||||
2705 | if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) ) | ||||||
2706 | { | ||||||
2707 | nX += pWinParent->mnOutOffX; | ||||||
2708 | } | ||||||
2709 | if( pParent && pParent->ImplIsAntiparallel() ) | ||||||
2710 | { | ||||||
2711 | tools::Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) ); | ||||||
2712 | const OutputDevice *pParentOutDev = pParent->GetOutDev(); | ||||||
2713 | pParentOutDev->ReMirror( aRect ); | ||||||
2714 | nX = aRect.Left(); | ||||||
2715 | } | ||||||
2716 | } | ||||||
2717 | if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth ) | ||||||
2718 | { | ||||||
2719 | // RTL: make sure the old right aligned position is not changed | ||||||
2720 | // system windows will always grow to the right | ||||||
2721 | if ( pWinParent ) | ||||||
2722 | { | ||||||
2723 | OutputDevice *pParentOutDev = pWinParent->GetOutDev(); | ||||||
2724 | if( pParentOutDev->HasMirroredGraphics() ) | ||||||
2725 | { | ||||||
2726 | const SalFrameGeometry& aSysGeometry = mpWindowImpl->mpFrame->GetUnmirroredGeometry(); | ||||||
2727 | const SalFrameGeometry& aParentSysGeometry = | ||||||
2728 | pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry(); | ||||||
2729 | long myWidth = nOldWidth; | ||||||
2730 | if( !myWidth ) | ||||||
2731 | myWidth = aSysGeometry.nWidth; | ||||||
2732 | if( !myWidth ) | ||||||
2733 | myWidth = nWidth; | ||||||
2734 | nFlags |= PosSizeFlags::X; | ||||||
2735 | nSysFlags |= SAL_FRAME_POSSIZE_X(sal_uInt16(0x0001)); | ||||||
2736 | nX = aParentSysGeometry.nX - aSysGeometry.nLeftDecoration + aParentSysGeometry.nWidth | ||||||
2737 | - myWidth - 1 - aSysGeometry.nX; | ||||||
2738 | } | ||||||
2739 | } | ||||||
2740 | } | ||||||
2741 | if( nFlags & PosSizeFlags::Y ) | ||||||
2742 | { | ||||||
2743 | nSysFlags |= SAL_FRAME_POSSIZE_Y(sal_uInt16(0x0002)); | ||||||
2744 | if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) ) | ||||||
2745 | { | ||||||
2746 | nY += pWinParent->mnOutOffY; | ||||||
2747 | } | ||||||
2748 | } | ||||||
2749 | |||||||
2750 | if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH(sal_uInt16(0x0004))|SAL_FRAME_POSSIZE_HEIGHT(sal_uInt16(0x0008))) ) | ||||||
2751 | { | ||||||
2752 | // check for min/max client size and adjust size accordingly | ||||||
2753 | // otherwise it may happen that the resize event is ignored, i.e. the old size remains | ||||||
2754 | // unchanged but ImplHandleResize() is called with the wrong size | ||||||
2755 | SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() ); | ||||||
2756 | if( pSystemWindow ) | ||||||
2757 | { | ||||||
2758 | Size aMinSize = pSystemWindow->GetMinOutputSizePixel(); | ||||||
2759 | Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel(); | ||||||
2760 | if( nWidth < aMinSize.Width() ) | ||||||
2761 | nWidth = aMinSize.Width(); | ||||||
2762 | if( nHeight < aMinSize.Height() ) | ||||||
2763 | nHeight = aMinSize.Height(); | ||||||
2764 | |||||||
2765 | if( nWidth > aMaxSize.Width() ) | ||||||
2766 | nWidth = aMaxSize.Width(); | ||||||
2767 | if( nHeight > aMaxSize.Height() ) | ||||||
2768 | nHeight = aMaxSize.Height(); | ||||||
2769 | } | ||||||
2770 | } | ||||||
2771 | |||||||
2772 | pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags ); | ||||||
2773 | |||||||
2774 | // Adjust resize with the hack of different client size and frame geometries to fix | ||||||
2775 | // native menu bars. Eventually this should be replaced by proper mnTopBorder usage. | ||||||
2776 | pWindow->mpWindowImpl->mpFrame->GetClientSize(nWidth, nHeight); | ||||||
2777 | |||||||
2778 | // Resize should be called directly. If we haven't | ||||||
2779 | // set the correct size, we get a second resize from | ||||||
2780 | // the system with the correct size. This can be happened | ||||||
2781 | // if the size is too small or too large. | ||||||
2782 | ImplHandleResize( pWindow, nWidth, nHeight ); | ||||||
2783 | } | ||||||
2784 | else | ||||||
2785 | { | ||||||
2786 | pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags ); | ||||||
2787 | if ( IsReallyVisible() ) | ||||||
2788 | ImplGenerateMouseMove(); | ||||||
2789 | } | ||||||
2790 | } | ||||||
2791 | |||||||
2792 | Point Window::GetPosPixel() const | ||||||
2793 | { | ||||||
2794 | return mpWindowImpl->maPos; | ||||||
2795 | } | ||||||
2796 | |||||||
2797 | tools::Rectangle Window::GetDesktopRectPixel() const | ||||||
2798 | { | ||||||
2799 | tools::Rectangle rRect; | ||||||
2800 | mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect ); | ||||||
2801 | return rRect; | ||||||
2802 | } | ||||||
2803 | |||||||
2804 | Point Window::OutputToScreenPixel( const Point& rPos ) const | ||||||
2805 | { | ||||||
2806 | // relative to top level parent | ||||||
2807 | return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY ); | ||||||
2808 | } | ||||||
2809 | |||||||
2810 | Point Window::ScreenToOutputPixel( const Point& rPos ) const | ||||||
2811 | { | ||||||
2812 | // relative to top level parent | ||||||
2813 | return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY ); | ||||||
2814 | } | ||||||
2815 | |||||||
2816 | long Window::ImplGetUnmirroredOutOffX() | ||||||
2817 | { | ||||||
2818 | // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow | ||||||
2819 | long offx = mnOutOffX; | ||||||
2820 | OutputDevice *pOutDev = GetOutDev(); | ||||||
2821 | if( pOutDev->HasMirroredGraphics() ) | ||||||
2822 | { | ||||||
2823 | if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() ) | ||||||
2824 | { | ||||||
2825 | if ( !ImplIsOverlapWindow() ) | ||||||
2826 | offx -= mpWindowImpl->mpParent->mnOutOffX; | ||||||
2827 | |||||||
2828 | offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx; | ||||||
2829 | |||||||
2830 | if ( !ImplIsOverlapWindow() ) | ||||||
2831 | offx += mpWindowImpl->mpParent->mnOutOffX; | ||||||
2832 | |||||||
2833 | } | ||||||
2834 | } | ||||||
2835 | return offx; | ||||||
2836 | } | ||||||
2837 | |||||||
2838 | // normalized screen pixel are independent of mirroring | ||||||
2839 | Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const | ||||||
2840 | { | ||||||
2841 | // relative to top level parent | ||||||
2842 | long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX(); | ||||||
2843 | return Point( rPos.X()+offx, rPos.Y()+mnOutOffY ); | ||||||
2844 | } | ||||||
2845 | |||||||
2846 | Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const | ||||||
2847 | { | ||||||
2848 | // relative to top level parent | ||||||
2849 | long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX(); | ||||||
2850 | return Point( rPos.X()-offx, rPos.Y()-mnOutOffY ); | ||||||
2851 | } | ||||||
2852 | |||||||
2853 | Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const | ||||||
2854 | { | ||||||
2855 | // relative to the screen | ||||||
2856 | Point p = OutputToScreenPixel( rPos ); | ||||||
2857 | SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry(); | ||||||
2858 | p.AdjustX(g.nX ); | ||||||
2859 | p.AdjustY(g.nY ); | ||||||
2860 | return p; | ||||||
2861 | } | ||||||
2862 | |||||||
2863 | Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const | ||||||
2864 | { | ||||||
2865 | // relative to the screen | ||||||
2866 | Point p = ScreenToOutputPixel( rPos ); | ||||||
2867 | SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry(); | ||||||
2868 | p.AdjustX( -(g.nX) ); | ||||||
2869 | p.AdjustY( -(g.nY) ); | ||||||
2870 | return p; | ||||||
2871 | } | ||||||
2872 | |||||||
2873 | tools::Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const | ||||||
2874 | { | ||||||
2875 | // this method creates unmirrored screen coordinates to be compared with the desktop | ||||||
2876 | // and is used for positioning of RTL popup windows correctly on the screen | ||||||
2877 | SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry(); | ||||||
2878 | |||||||
2879 | Point p1 = OutputToScreenPixel( rRect.TopRight() ); | ||||||
2880 | p1.setX( g.nX+g.nWidth-p1.X() ); | ||||||
2881 | p1.AdjustY(g.nY ); | ||||||
2882 | |||||||
2883 | Point p2 = OutputToScreenPixel( rRect.BottomLeft() ); | ||||||
2884 | p2.setX( g.nX+g.nWidth-p2.X() ); | ||||||
2885 | p2.AdjustY(g.nY ); | ||||||
2886 | |||||||
2887 | return tools::Rectangle( p1, p2 ); | ||||||
2888 | } | ||||||
2889 | |||||||
2890 | tools::Rectangle Window::GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const | ||||||
2891 | { | ||||||
2892 | // with decoration | ||||||
2893 | return ImplGetWindowExtentsRelative( pRelativeWindow ); | ||||||
2894 | } | ||||||
2895 | |||||||
2896 | tools::Rectangle Window::ImplGetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const | ||||||
2897 | { | ||||||
2898 | SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry(); | ||||||
2899 | // make sure we use the extent of our border window, | ||||||
2900 | // otherwise we miss a few pixels | ||||||
2901 | const vcl::Window *pWin = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow : this; | ||||||
2902 | |||||||
2903 | Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) ); | ||||||
2904 | aPos.AdjustX(g.nX ); | ||||||
2905 | aPos.AdjustY(g.nY ); | ||||||
2906 | Size aSize ( pWin->GetSizePixel() ); | ||||||
2907 | // #104088# do not add decoration to the workwindow to be compatible to java accessibility api | ||||||
2908 | if( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW) ) | ||||||
2909 | { | ||||||
2910 | aPos.AdjustX( -sal_Int32(g.nLeftDecoration) ); | ||||||
2911 | aPos.AdjustY( -sal_Int32(g.nTopDecoration) ); | ||||||
2912 | aSize.AdjustWidth(g.nLeftDecoration + g.nRightDecoration ); | ||||||
2913 | aSize.AdjustHeight(g.nTopDecoration + g.nBottomDecoration ); | ||||||
2914 | } | ||||||
2915 | if( pRelativeWindow ) | ||||||
2916 | { | ||||||
2917 | // #106399# express coordinates relative to borderwindow | ||||||
2918 | const vcl::Window *pRelWin = pRelativeWindow->mpWindowImpl->mpBorderWindow ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow; | ||||||
2919 | aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos ); | ||||||
2920 | } | ||||||
2921 | return tools::Rectangle( aPos, aSize ); | ||||||
2922 | } | ||||||
2923 | |||||||
2924 | void Window::Scroll( long nHorzScroll, long nVertScroll, ScrollFlags nFlags ) | ||||||
2925 | { | ||||||
2926 | |||||||
2927 | ImplScroll( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), | ||||||
2928 | Size( mnOutWidth, mnOutHeight ) ), | ||||||
2929 | nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip ); | ||||||
2930 | } | ||||||
2931 | |||||||
2932 | void Window::Scroll( long nHorzScroll, long nVertScroll, | ||||||
2933 | const tools::Rectangle& rRect, ScrollFlags nFlags ) | ||||||
2934 | { | ||||||
2935 | OutputDevice *pOutDev = GetOutDev(); | ||||||
2936 | tools::Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect ); | ||||||
2937 | aRect.Intersection( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) ); | ||||||
2938 | if ( !aRect.IsEmpty() ) | ||||||
2939 | ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags ); | ||||||
2940 | } | ||||||
2941 | |||||||
2942 | void Window::Flush() | ||||||
2943 | { | ||||||
2944 | if (mpWindowImpl) | ||||||
2945 | { | ||||||
2946 | const tools::Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); | ||||||
2947 | mpWindowImpl->mpFrame->Flush( aWinRect ); | ||||||
2948 | } | ||||||
2949 | } | ||||||
2950 | |||||||
2951 | void Window::SetUpdateMode( bool bUpdate ) | ||||||
2952 | { | ||||||
2953 | if (mpWindowImpl) | ||||||
2954 | { | ||||||
2955 | mpWindowImpl->mbNoUpdate = !bUpdate; | ||||||
2956 | CompatStateChanged( StateChangedType::UpdateMode ); | ||||||
2957 | } | ||||||
2958 | } | ||||||
2959 | |||||||
2960 | void Window::GrabFocus() | ||||||
2961 | { | ||||||
2962 | ImplGrabFocus( GetFocusFlags::NONE ); | ||||||
2963 | } | ||||||
2964 | |||||||
2965 | bool Window::HasFocus() const | ||||||
2966 | { | ||||||
2967 | return (this == ImplGetSVData()->mpWinData->mpFocusWin); | ||||||
2968 | } | ||||||
2969 | |||||||
2970 | void Window::GrabFocusToDocument() | ||||||
2971 | { | ||||||
2972 | ImplGrabFocusToDocument(GetFocusFlags::NONE); | ||||||
2973 | } | ||||||
2974 | |||||||
2975 | VclPtr<vcl::Window> Window::GetFocusedWindow() const | ||||||
2976 | { | ||||||
2977 | if (mpWindowImpl && mpWindowImpl->mpFrameData) | ||||||
2978 | return mpWindowImpl->mpFrameData->mpFocusWin; | ||||||
2979 | else | ||||||
2980 | return VclPtr<vcl::Window>(); | ||||||
2981 | } | ||||||
2982 | |||||||
2983 | void Window::SetFakeFocus( bool bFocus ) | ||||||
2984 | { | ||||||
2985 | ImplGetWindowImpl()->mbFakeFocusSet = bFocus; | ||||||
2986 | } | ||||||
2987 | |||||||
2988 | bool Window::HasChildPathFocus( bool bSystemWindow ) const | ||||||
2989 | { | ||||||
2990 | |||||||
2991 | vcl::Window* pFocusWin = ImplGetSVData()->mpWinData->mpFocusWin; | ||||||
2992 | if ( pFocusWin ) | ||||||
2993 | return ImplIsWindowOrChild( pFocusWin, bSystemWindow ); | ||||||
2994 | return false; | ||||||
2995 | } | ||||||
2996 | |||||||
2997 | void Window::SetCursor( vcl::Cursor* pCursor ) | ||||||
2998 | { | ||||||
2999 | |||||||
3000 | if ( mpWindowImpl->mpCursor != pCursor ) | ||||||
3001 | { | ||||||
3002 | if ( mpWindowImpl->mpCursor ) | ||||||
3003 | mpWindowImpl->mpCursor->ImplHide(); | ||||||
3004 | mpWindowImpl->mpCursor = pCursor; | ||||||
3005 | if ( pCursor ) | ||||||
3006 | pCursor->ImplShow(); | ||||||
3007 | } | ||||||
3008 | } | ||||||
3009 | |||||||
3010 | void Window::SetText( const OUString& rStr ) | ||||||
3011 | { | ||||||
3012 | if (!mpWindowImpl || rStr == mpWindowImpl->maText) | ||||||
3013 | return; | ||||||
3014 | |||||||
3015 | OUString oldTitle( mpWindowImpl->maText ); | ||||||
3016 | mpWindowImpl->maText = rStr; | ||||||
3017 | |||||||
3018 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
3019 | mpWindowImpl->mpBorderWindow->SetText( rStr ); | ||||||
3020 | else if ( mpWindowImpl->mbFrame ) | ||||||
3021 | mpWindowImpl->mpFrame->SetTitle( rStr ); | ||||||
3022 | |||||||
3023 | CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle ); | ||||||
3024 | |||||||
3025 | // #107247# needed for accessibility | ||||||
3026 | // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes. | ||||||
3027 | // Therefore a window, which is labeled by this window, must also notify an accessible | ||||||
3028 | // name change. | ||||||
3029 | if ( IsReallyVisible() ) | ||||||
3030 | { | ||||||
3031 | vcl::Window* pWindow = GetAccessibleRelationLabelFor(); | ||||||
3032 | if ( pWindow && pWindow != this ) | ||||||
3033 | pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle ); | ||||||
3034 | } | ||||||
3035 | |||||||
3036 | CompatStateChanged( StateChangedType::Text ); | ||||||
3037 | } | ||||||
3038 | |||||||
3039 | OUString Window::GetText() const | ||||||
3040 | { | ||||||
3041 | |||||||
3042 | return mpWindowImpl->maText; | ||||||
3043 | } | ||||||
3044 | |||||||
3045 | OUString Window::GetDisplayText() const | ||||||
3046 | { | ||||||
3047 | |||||||
3048 | return GetText(); | ||||||
3049 | } | ||||||
3050 | |||||||
3051 | const Wallpaper& Window::GetDisplayBackground() const | ||||||
3052 | { | ||||||
3053 | // FIXME: fix issue 52349, need to fix this really in | ||||||
3054 | // all NWF enabled controls | ||||||
3055 | const ToolBox* pTB = dynamic_cast<const ToolBox*>(this); | ||||||
3056 | if( pTB && IsNativeWidgetEnabled() ) | ||||||
3057 | return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground; | ||||||
3058 | |||||||
3059 | if( !IsBackground() ) | ||||||
3060 | { | ||||||
3061 | if( mpWindowImpl->mpParent ) | ||||||
3062 | return mpWindowImpl->mpParent->GetDisplayBackground(); | ||||||
3063 | } | ||||||
3064 | |||||||
3065 | const Wallpaper& rBack = GetBackground(); | ||||||
3066 | if( ! rBack.IsBitmap() && | ||||||
3067 | ! rBack.IsGradient() && | ||||||
3068 | rBack.GetColor()== COL_TRANSPARENT && | ||||||
3069 | mpWindowImpl->mpParent ) | ||||||
3070 | return mpWindowImpl->mpParent->GetDisplayBackground(); | ||||||
3071 | return rBack; | ||||||
3072 | } | ||||||
3073 | |||||||
3074 | const OUString& Window::GetHelpText() const | ||||||
3075 | { | ||||||
3076 | OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) ) ); | ||||||
3077 | bool bStrHelpId = !aStrHelpId.isEmpty(); | ||||||
3078 | |||||||
3079 | if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId ) | ||||||
3080 | { | ||||||
3081 | if ( !IsDialog() && (mpWindowImpl->mnType != WindowType::TABPAGE) && (mpWindowImpl->mnType != WindowType::FLOATINGWINDOW) ) | ||||||
3082 | { | ||||||
3083 | Help* pHelp = Application::GetHelp(); | ||||||
3084 | if ( pHelp ) | ||||||
3085 | { | ||||||
3086 | mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this); | ||||||
3087 | mpWindowImpl->mbHelpTextDynamic = false; | ||||||
3088 | } | ||||||
3089 | } | ||||||
3090 | } | ||||||
3091 | else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId ) | ||||||
3092 | { | ||||||
3093 | static const char* pEnv = getenv( "HELP_DEBUG" ); | ||||||
3094 | if( pEnv && *pEnv ) | ||||||
3095 | { | ||||||
3096 | OUString aTxt = mpWindowImpl->maHelpText + "\n------------------\n" + aStrHelpId; | ||||||
3097 | mpWindowImpl->maHelpText = aTxt; | ||||||
3098 | } | ||||||
3099 | mpWindowImpl->mbHelpTextDynamic = false; | ||||||
3100 | } | ||||||
3101 | |||||||
3102 | //Fallback to Window::GetAccessibleDescription without reentry to GetHelpText() | ||||||
3103 | if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription) | ||||||
3104 | return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription; | ||||||
3105 | return mpWindowImpl->maHelpText; | ||||||
3106 | } | ||||||
3107 | |||||||
3108 | void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow ) | ||||||
3109 | { | ||||||
3110 | if (!mpWindowImpl) | ||||||
3111 | return; | ||||||
3112 | |||||||
3113 | // be safe against re-entrance: first clear the old ref, then assign the new one | ||||||
3114 | mpWindowImpl->mxWindowPeer.clear(); | ||||||
3115 | mpWindowImpl->mxWindowPeer = xPeer; | ||||||
3116 | |||||||
3117 | mpWindowImpl->mpVCLXWindow = pVCLXWindow; | ||||||
3118 | } | ||||||
3119 | |||||||
3120 | Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate ) | ||||||
3121 | { | ||||||
3122 | if ( !mpWindowImpl->mxWindowPeer.is() && bCreate ) | ||||||
3123 | { | ||||||
3124 | UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper(); | ||||||
3125 | if ( pWrapper ) | ||||||
3126 | mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this ); | ||||||
3127 | } | ||||||
3128 | return mpWindowImpl->mxWindowPeer; | ||||||
3129 | } | ||||||
3130 | |||||||
3131 | void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace ) | ||||||
3132 | { | ||||||
3133 | UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper(); | ||||||
3134 | SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" )do { if (true && (!pWrapper)) { 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() << "SetComponentInterface: No Wrapper!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "3134" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SetComponentInterface: No Wrapper!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SetComponentInterface: No Wrapper!"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "3134" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SetComponentInterface: No Wrapper!") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "3134" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SetComponentInterface: No Wrapper!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SetComponentInterface: No Wrapper!"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.window"), ("/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" ":" "3134" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
3135 | if ( pWrapper ) | ||||||
3136 | pWrapper->SetWindowInterface( this, xIFace ); | ||||||
3137 | } | ||||||
3138 | |||||||
3139 | typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap; | ||||||
3140 | |||||||
3141 | namespace { | ||||||
3142 | |||||||
3143 | LOKWindowsMap& GetLOKWindowsMap() | ||||||
3144 | { | ||||||
3145 | // Map to remember the LOKWindowId <-> Window binding. | ||||||
3146 | static LOKWindowsMap s_aLOKWindowsMap; | ||||||
3147 | |||||||
3148 | return s_aLOKWindowsMap; | ||||||
3149 | } | ||||||
3150 | |||||||
3151 | } | ||||||
3152 | |||||||
3153 | void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent) | ||||||
3154 | { | ||||||
3155 | // don't allow setting this twice | ||||||
3156 | assert(mpWindowImpl->mpLOKNotifier == nullptr)(static_cast <bool> (mpWindowImpl->mpLOKNotifier == nullptr ) ? void (0) : __assert_fail ("mpWindowImpl->mpLOKNotifier == nullptr" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 3156, __extension__ __PRETTY_FUNCTION__)); | ||||||
3157 | assert(pNotifier)(static_cast <bool> (pNotifier) ? void (0) : __assert_fail ("pNotifier", "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 3157, __extension__ __PRETTY_FUNCTION__)); | ||||||
3158 | // never use this in the desktop case | ||||||
3159 | assert(comphelper::LibreOfficeKit::isActive())(static_cast <bool> (comphelper::LibreOfficeKit::isActive ()) ? void (0) : __assert_fail ("comphelper::LibreOfficeKit::isActive()" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 3159, __extension__ __PRETTY_FUNCTION__)); | ||||||
3160 | |||||||
3161 | if (!bParent) | ||||||
3162 | { | ||||||
3163 | // Counter to be able to have unique id's for each window. | ||||||
3164 | static vcl::LOKWindowId sLastLOKWindowId = 1; | ||||||
3165 | |||||||
3166 | // assign the LOK window id | ||||||
3167 | assert(mpWindowImpl->mnLOKWindowId == 0)(static_cast <bool> (mpWindowImpl->mnLOKWindowId == 0 ) ? void (0) : __assert_fail ("mpWindowImpl->mnLOKWindowId == 0" , "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 3167, __extension__ __PRETTY_FUNCTION__)); | ||||||
3168 | mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++; | ||||||
3169 | GetLOKWindowsMap().emplace(mpWindowImpl->mnLOKWindowId, this); | ||||||
3170 | } | ||||||
3171 | else | ||||||
3172 | mpWindowImpl->mbLOKParentNotifier = true; | ||||||
3173 | |||||||
3174 | mpWindowImpl->mpLOKNotifier = pNotifier; | ||||||
3175 | } | ||||||
3176 | |||||||
3177 | VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId) | ||||||
3178 | { | ||||||
3179 | const auto it = GetLOKWindowsMap().find(nWindowId); | ||||||
3180 | if (it != GetLOKWindowsMap().end()) | ||||||
3181 | return it->second; | ||||||
3182 | |||||||
3183 | return VclPtr<Window>(); | ||||||
3184 | } | ||||||
3185 | |||||||
3186 | bool Window::IsLOKWindowsEmpty() | ||||||
3187 | { | ||||||
3188 | return GetLOKWindowsMap().empty(); | ||||||
3189 | } | ||||||
3190 | |||||||
3191 | void Window::ReleaseLOKNotifier() | ||||||
3192 | { | ||||||
3193 | // unregister the LOK window binding | ||||||
3194 | if (mpWindowImpl->mnLOKWindowId > 0) | ||||||
3195 | GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId); | ||||||
3196 | |||||||
3197 | mpWindowImpl->mpLOKNotifier = nullptr; | ||||||
3198 | mpWindowImpl->mnLOKWindowId = 0; | ||||||
3199 | } | ||||||
3200 | |||||||
3201 | ILibreOfficeKitNotifier::~ILibreOfficeKitNotifier() | ||||||
3202 | { | ||||||
3203 | if (!comphelper::LibreOfficeKit::isActive()) | ||||||
3204 | { | ||||||
3205 | return; | ||||||
3206 | } | ||||||
3207 | |||||||
3208 | for (auto it = GetLOKWindowsMap().begin(); it != GetLOKWindowsMap().end();) | ||||||
3209 | { | ||||||
3210 | WindowImpl* pWindowImpl = it->second->ImplGetWindowImpl(); | ||||||
3211 | if (pWindowImpl && pWindowImpl->mpLOKNotifier == this) | ||||||
3212 | { | ||||||
3213 | pWindowImpl->mpLOKNotifier = nullptr; | ||||||
3214 | pWindowImpl->mnLOKWindowId = 0; | ||||||
3215 | it = GetLOKWindowsMap().erase(it); | ||||||
3216 | continue; | ||||||
3217 | } | ||||||
3218 | |||||||
3219 | ++it; | ||||||
3220 | } | ||||||
3221 | } | ||||||
3222 | |||||||
3223 | const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const | ||||||
3224 | { | ||||||
3225 | return mpWindowImpl->mpLOKNotifier; | ||||||
3226 | } | ||||||
3227 | |||||||
3228 | vcl::LOKWindowId Window::GetLOKWindowId() const | ||||||
3229 | { | ||||||
3230 | return mpWindowImpl->mnLOKWindowId; | ||||||
3231 | } | ||||||
3232 | |||||||
3233 | VclPtr<vcl::Window> Window::GetParentWithLOKNotifier() | ||||||
3234 | { | ||||||
3235 | VclPtr<vcl::Window> pWindow(this); | ||||||
3236 | |||||||
3237 | while (pWindow && !pWindow->GetLOKNotifier()) | ||||||
3238 | pWindow = pWindow->GetParent(); | ||||||
3239 | |||||||
3240 | return pWindow; | ||||||
3241 | } | ||||||
3242 | |||||||
3243 | namespace | ||||||
3244 | { | ||||||
3245 | |||||||
3246 | const char* windowTypeName(WindowType nWindowType) | ||||||
3247 | { | ||||||
3248 | switch (nWindowType) | ||||||
3249 | { | ||||||
3250 | case WindowType::NONE: return "none"; | ||||||
3251 | case WindowType::MESSBOX: return "messagebox"; | ||||||
3252 | case WindowType::INFOBOX: return "infobox"; | ||||||
3253 | case WindowType::WARNINGBOX: return "warningbox"; | ||||||
3254 | case WindowType::ERRORBOX: return "errorbox"; | ||||||
3255 | case WindowType::QUERYBOX: return "querybox"; | ||||||
3256 | case WindowType::WINDOW: return "window"; | ||||||
3257 | case WindowType::WORKWINDOW: return "workwindow"; | ||||||
3258 | case WindowType::CONTAINER: return "container"; | ||||||
3259 | case WindowType::FLOATINGWINDOW: return "floatingwindow"; | ||||||
3260 | case WindowType::DIALOG: return "dialog"; | ||||||
3261 | case WindowType::MODELESSDIALOG: return "modelessdialog"; | ||||||
3262 | case WindowType::CONTROL: return "control"; | ||||||
3263 | case WindowType::PUSHBUTTON: return "pushbutton"; | ||||||
3264 | case WindowType::OKBUTTON: return "okbutton"; | ||||||
3265 | case WindowType::CANCELBUTTON: return "cancelbutton"; | ||||||
3266 | case WindowType::HELPBUTTON: return "helpbutton"; | ||||||
3267 | case WindowType::IMAGEBUTTON: return "imagebutton"; | ||||||
3268 | case WindowType::MENUBUTTON: return "menubutton"; | ||||||
3269 | case WindowType::MOREBUTTON: return "morebutton"; | ||||||
3270 | case WindowType::SPINBUTTON: return "spinbutton"; | ||||||
3271 | case WindowType::RADIOBUTTON: return "radiobutton"; | ||||||
3272 | case WindowType::CHECKBOX: return "checkbox"; | ||||||
3273 | case WindowType::TRISTATEBOX: return "tristatebox"; | ||||||
3274 | case WindowType::EDIT: return "edit"; | ||||||
3275 | case WindowType::MULTILINEEDIT: return "multilineedit"; | ||||||
3276 | case WindowType::COMBOBOX: return "combobox"; | ||||||
3277 | case WindowType::LISTBOX: return "listbox"; | ||||||
3278 | case WindowType::MULTILISTBOX: return "multilistbox"; | ||||||
3279 | case WindowType::FIXEDTEXT: return "fixedtext"; | ||||||
3280 | case WindowType::FIXEDLINE: return "fixedline"; | ||||||
3281 | case WindowType::FIXEDBITMAP: return "fixedbitmap"; | ||||||
3282 | case WindowType::FIXEDIMAGE: return "fixedimage"; | ||||||
3283 | case WindowType::GROUPBOX: return "groupbox"; | ||||||
3284 | case WindowType::SCROLLBAR: return "scrollbar"; | ||||||
3285 | case WindowType::SCROLLBARBOX: return "scrollbarbox"; | ||||||
3286 | case WindowType::SPLITTER: return "splitter"; | ||||||
3287 | case WindowType::SPLITWINDOW: return "splitwindow"; | ||||||
3288 | case WindowType::SPINFIELD: return "spinfield"; | ||||||
3289 | case WindowType::PATTERNFIELD: return "patternfield"; | ||||||
3290 | case WindowType::METRICFIELD: return "metricfield"; | ||||||
3291 | case WindowType::FORMATTEDFIELD: return "formattedfield"; | ||||||
3292 | case WindowType::CURRENCYFIELD: return "currencyfield"; | ||||||
3293 | case WindowType::DATEFIELD: return "datefield"; | ||||||
3294 | case WindowType::TIMEFIELD: return "timefield"; | ||||||
3295 | case WindowType::PATTERNBOX: return "patternbox"; | ||||||
3296 | case WindowType::NUMERICBOX: return "numericbox"; | ||||||
3297 | case WindowType::METRICBOX: return "metricbox"; | ||||||
3298 | case WindowType::CURRENCYBOX: return "currencybox"; | ||||||
3299 | case WindowType::DATEBOX: return "datebox"; | ||||||
3300 | case WindowType::TIMEBOX: return "timebox"; | ||||||
3301 | case WindowType::LONGCURRENCYBOX: return "longcurrencybox"; | ||||||
3302 | case WindowType::SCROLLWINDOW: return "scrollwindow"; | ||||||
3303 | case WindowType::TOOLBOX: return "toolbox"; | ||||||
3304 | case WindowType::DOCKINGWINDOW: return "dockingwindow"; | ||||||
3305 | case WindowType::STATUSBAR: return "statusbar"; | ||||||
3306 | case WindowType::TABPAGE: return "tabpage"; | ||||||
3307 | case WindowType::TABCONTROL: return "tabcontrol"; | ||||||
3308 | case WindowType::TABDIALOG: return "tabdialog"; | ||||||
3309 | case WindowType::BORDERWINDOW: return "borderwindow"; | ||||||
3310 | case WindowType::BUTTONDIALOG: return "buttondialog"; | ||||||
3311 | case WindowType::SYSTEMCHILDWINDOW: return "systemchildwindow"; | ||||||
3312 | case WindowType::SLIDER: return "slider"; | ||||||
3313 | case WindowType::MENUBARWINDOW: return "menubarwindow"; | ||||||
3314 | case WindowType::TREELISTBOX: return "treelistbox"; | ||||||
3315 | case WindowType::HELPTEXTWINDOW: return "helptextwindow"; | ||||||
3316 | case WindowType::INTROWINDOW: return "introwindow"; | ||||||
3317 | case WindowType::LISTBOXWINDOW: return "listboxwindow"; | ||||||
3318 | case WindowType::DOCKINGAREA: return "dockingarea"; | ||||||
3319 | case WindowType::RULER: return "ruler"; | ||||||
3320 | case WindowType::CALCINPUTLINE: return "calcinputline"; | ||||||
3321 | case WindowType::HEADERBAR: return "headerbar"; | ||||||
3322 | case WindowType::VERTICALTABCONTROL: return "verticaltabcontrol"; | ||||||
3323 | |||||||
3324 | // nothing to do here, but for completeness | ||||||
3325 | case WindowType::TOOLKIT_FRAMEWINDOW: return "toolkit_framewindow"; | ||||||
3326 | case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return "toolkit_systemchildwindow"; | ||||||
3327 | } | ||||||
3328 | |||||||
3329 | return "none"; | ||||||
3330 | } | ||||||
3331 | |||||||
3332 | } | ||||||
3333 | |||||||
3334 | void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) | ||||||
3335 | { | ||||||
3336 | rJsonWriter.put("id", get_id()); // TODO could be missing - sort out | ||||||
3337 | rJsonWriter.put("type", windowTypeName(GetType())); | ||||||
3338 | rJsonWriter.put("text", GetText()); | ||||||
3339 | rJsonWriter.put("enabled", IsEnabled()); | ||||||
3340 | |||||||
3341 | if (vcl::Window* pChild = mpWindowImpl->mpFirstChild) | ||||||
3342 | { | ||||||
3343 | auto childrenNode = rJsonWriter.startNode("children"); | ||||||
3344 | while (pChild) | ||||||
3345 | { | ||||||
3346 | if (pChild->IsVisible()) { | ||||||
3347 | auto childNode = rJsonWriter.startNode(""); | ||||||
3348 | pChild->DumpAsPropertyTree(rJsonWriter); | ||||||
3349 | sal_Int32 nLeft = pChild->get_grid_left_attach(); | ||||||
3350 | sal_Int32 nTop = pChild->get_grid_top_attach(); | ||||||
3351 | if (nLeft != -1 && nTop != -1) | ||||||
3352 | { | ||||||
3353 | rJsonWriter.put("left", nLeft); | ||||||
3354 | rJsonWriter.put("top", nTop); | ||||||
3355 | } | ||||||
3356 | } | ||||||
3357 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
3358 | } | ||||||
3359 | } | ||||||
3360 | |||||||
3361 | mpWindowImpl->maDumpAsPropertyTreeHdl.Call(rJsonWriter); | ||||||
3362 | } | ||||||
3363 | |||||||
3364 | void Window::ImplCallDeactivateListeners( vcl::Window *pNew ) | ||||||
3365 | { | ||||||
3366 | // no deactivation if the newly activated window is my child | ||||||
3367 | if ( !pNew || !ImplIsChild( pNew ) ) | ||||||
3368 | { | ||||||
3369 | VclPtr<vcl::Window> xWindow(this); | ||||||
3370 | CallEventListeners( VclEventId::WindowDeactivate, pNew ); | ||||||
3371 | if( xWindow->IsDisposed() ) | ||||||
3372 | return; | ||||||
3373 | |||||||
3374 | // #100759#, avoid walking the wrong frame's hierarchy | ||||||
3375 | // eg, undocked docking windows (ImplDockFloatWin) | ||||||
3376 | if ( ImplGetParent() && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow ) | ||||||
3377 | ImplGetParent()->ImplCallDeactivateListeners( pNew ); | ||||||
3378 | } | ||||||
3379 | } | ||||||
3380 | |||||||
3381 | void Window::ImplCallActivateListeners( vcl::Window *pOld ) | ||||||
3382 | { | ||||||
3383 | // no activation if the old active window is my child | ||||||
3384 | if ( pOld && ImplIsChild( pOld )) | ||||||
3385 | return; | ||||||
3386 | |||||||
3387 | VclPtr<vcl::Window> xWindow(this); | ||||||
3388 | CallEventListeners( VclEventId::WindowActivate, pOld ); | ||||||
3389 | if( xWindow->IsDisposed() ) | ||||||
3390 | return; | ||||||
3391 | |||||||
3392 | if ( ImplGetParent() ) | ||||||
3393 | ImplGetParent()->ImplCallActivateListeners( pOld ); | ||||||
3394 | else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 ) | ||||||
3395 | { | ||||||
3396 | // top level frame reached: store hint for DefModalDialogParent | ||||||
3397 | ImplGetSVData()->maFrameData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow; | ||||||
3398 | } | ||||||
3399 | } | ||||||
3400 | |||||||
3401 | void Window::SetClipboard(Reference<XClipboard> const & xClipboard) | ||||||
3402 | { | ||||||
3403 | if (mpWindowImpl->mpFrameData) | ||||||
3404 | mpWindowImpl->mpFrameData->mxClipboard = xClipboard; | ||||||
3405 | } | ||||||
3406 | |||||||
3407 | Reference< XClipboard > Window::GetClipboard() | ||||||
3408 | { | ||||||
3409 | if (!mpWindowImpl->mpFrameData) | ||||||
3410 | return static_cast<XClipboard*>(nullptr); | ||||||
3411 | if (!mpWindowImpl->mpFrameData->mxClipboard.is()) | ||||||
3412 | mpWindowImpl->mpFrameData->mxClipboard = GetSystemClipboard(); | ||||||
3413 | return mpWindowImpl->mpFrameData->mxClipboard; | ||||||
3414 | } | ||||||
3415 | |||||||
3416 | Reference< XClipboard > Window::GetPrimarySelection() | ||||||
3417 | { | ||||||
3418 | if (!mpWindowImpl->mpFrameData) | ||||||
3419 | return static_cast<XClipboard*>(nullptr); | ||||||
3420 | if (!mpWindowImpl->mpFrameData->mxSelection.is()) | ||||||
3421 | mpWindowImpl->mpFrameData->mxSelection = GetSystemPrimarySelection(); | ||||||
3422 | return mpWindowImpl->mpFrameData->mxSelection; | ||||||
3423 | } | ||||||
3424 | |||||||
3425 | void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const tools::Rectangle& rRect ) | ||||||
3426 | { | ||||||
3427 | assert(mpOutDevData)(static_cast <bool> (mpOutDevData) ? void (0) : __assert_fail ("mpOutDevData", "/home/maarten/src/libreoffice/core/vcl/source/window/window.cxx" , 3427, __extension__ __PRETTY_FUNCTION__)); | ||||||
3428 | mpOutDevData->mpRecordLayout = pLayout; | ||||||
3429 | mpOutDevData->maRecordRect = rRect; | ||||||
3430 | Paint(*this, rRect); | ||||||
3431 | mpOutDevData->mpRecordLayout = nullptr; | ||||||
3432 | } | ||||||
3433 | |||||||
3434 | void Window::DrawSelectionBackground( const tools::Rectangle& rRect, | ||||||
3435 | sal_uInt16 highlight, | ||||||
3436 | bool bChecked, | ||||||
3437 | bool bDrawBorder | ||||||
3438 | ) | ||||||
3439 | { | ||||||
3440 | if( rRect.IsEmpty() ) | ||||||
3441 | return; | ||||||
3442 | |||||||
3443 | const StyleSettings& rStyles = GetSettings().GetStyleSettings(); | ||||||
3444 | |||||||
3445 | // colors used for item highlighting | ||||||
3446 | Color aSelectionBorderCol( rStyles.GetHighlightColor() ); | ||||||
3447 | Color aSelectionFillCol( aSelectionBorderCol ); | ||||||
3448 | |||||||
3449 | bool bDark = rStyles.GetFaceColor().IsDark(); | ||||||
3450 | bool bBright = ( rStyles.GetFaceColor() == COL_WHITE ); | ||||||
3451 | |||||||
3452 | int c1 = aSelectionBorderCol.GetLuminance(); | ||||||
3453 | int c2 = GetBackgroundColor().GetLuminance(); | ||||||
3454 | |||||||
3455 | if( !bDark && !bBright && abs( c2-c1 ) < 75 ) | ||||||
3456 | { | ||||||
3457 | // contrast too low | ||||||
3458 | sal_uInt16 h,s,b; | ||||||
3459 | aSelectionFillCol.RGBtoHSB( h, s, b ); | ||||||
3460 | if( b > 50 ) b -= 40; | ||||||
3461 | else b += 40; | ||||||
3462 | aSelectionFillCol = Color::HSBtoRGB( h, s, b ); | ||||||
3463 | aSelectionBorderCol = aSelectionFillCol; | ||||||
3464 | } | ||||||
3465 | |||||||
3466 | tools::Rectangle aRect( rRect ); | ||||||
3467 | Color oldFillCol = GetFillColor(); | ||||||
3468 | Color oldLineCol = GetLineColor(); | ||||||
3469 | |||||||
3470 | if( bDrawBorder ) | ||||||
3471 | SetLineColor( bDark ? COL_WHITE : ( bBright ? COL_BLACK : aSelectionBorderCol ) ); | ||||||
3472 | else | ||||||
3473 | SetLineColor(); | ||||||
3474 | |||||||
3475 | sal_uInt16 nPercent = 0; | ||||||
3476 | if( !highlight ) | ||||||
3477 | { | ||||||
3478 | if( bDark ) | ||||||
3479 | aSelectionFillCol = COL_BLACK; | ||||||
3480 | else | ||||||
3481 | nPercent = 80; // just checked (light) | ||||||
3482 | } | ||||||
3483 | else | ||||||
3484 | { | ||||||
3485 | if( bChecked && highlight == 2 ) | ||||||
3486 | { | ||||||
3487 | if( bDark ) | ||||||
3488 | aSelectionFillCol = COL_LIGHTGRAY; | ||||||
3489 | else if ( bBright ) | ||||||
3490 | { | ||||||
3491 | aSelectionFillCol = COL_BLACK; | ||||||
3492 | SetLineColor( COL_BLACK ); | ||||||
3493 | nPercent = 0; | ||||||
3494 | } | ||||||
3495 | else | ||||||
3496 | nPercent = 20; // selected, pressed or checked ( very dark ) | ||||||
3497 | } | ||||||
3498 | else if( bChecked || highlight == 1 ) | ||||||
3499 | { | ||||||
3500 | if( bDark ) | ||||||
3501 | aSelectionFillCol = COL_GRAY; | ||||||
3502 | else if ( bBright ) | ||||||
3503 | { | ||||||
3504 | aSelectionFillCol = COL_BLACK; | ||||||
3505 | SetLineColor( COL_BLACK ); | ||||||
3506 | nPercent = 0; | ||||||
3507 | } | ||||||
3508 | else | ||||||
3509 | nPercent = 35; // selected, pressed or checked ( very dark ) | ||||||
3510 | } | ||||||
3511 | else | ||||||
3512 | { | ||||||
3513 | if( bDark ) | ||||||
3514 | aSelectionFillCol = COL_LIGHTGRAY; | ||||||
3515 | else if ( bBright ) | ||||||
3516 | { | ||||||
3517 | aSelectionFillCol = COL_BLACK; | ||||||
3518 | SetLineColor( COL_BLACK ); | ||||||
3519 | if( highlight == 3 ) | ||||||
3520 | nPercent = 80; | ||||||
3521 | else | ||||||
3522 | nPercent = 0; | ||||||
3523 | } | ||||||
3524 | else | ||||||
3525 | nPercent = 70; // selected ( dark ) | ||||||
3526 | } | ||||||
3527 | } | ||||||
3528 | |||||||
3529 | SetFillColor( aSelectionFillCol ); | ||||||
3530 | |||||||
3531 | if( bDark ) | ||||||
3532 | { | ||||||
3533 | DrawRect( aRect ); | ||||||
3534 | } | ||||||
3535 | else | ||||||
3536 | { | ||||||
3537 | tools::Polygon aPoly( aRect ); | ||||||
3538 | tools::PolyPolygon aPolyPoly( aPoly ); | ||||||
3539 | DrawTransparent( aPolyPoly, nPercent ); | ||||||
3540 | } | ||||||
3541 | |||||||
3542 | SetFillColor( oldFillCol ); | ||||||
3543 | SetLineColor( oldLineCol ); | ||||||
3544 | } | ||||||
3545 | |||||||
3546 | bool Window::IsScrollable() const | ||||||
3547 | { | ||||||
3548 | // check for scrollbars | ||||||
3549 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
3550 | while( pChild ) | ||||||
3551 | { | ||||||
3552 | if( pChild->GetType() == WindowType::SCROLLBAR ) | ||||||
3553 | return true; | ||||||
3554 | else | ||||||
3555 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
3556 | } | ||||||
3557 | return false; | ||||||
3558 | } | ||||||
3559 | |||||||
3560 | void Window::ImplMirrorFramePos( Point &pt ) const | ||||||
3561 | { | ||||||
3562 | pt.setX( mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X() ); | ||||||
3563 | } | ||||||
3564 | |||||||
3565 | // frame based modal counter (dialogs are not modal to the whole application anymore) | ||||||
3566 | bool Window::IsInModalMode() const | ||||||
3567 | { | ||||||
3568 | return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0); | ||||||
3569 | } | ||||||
3570 | |||||||
3571 | void Window::IncModalCount() | ||||||
3572 | { | ||||||
3573 | vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow; | ||||||
3574 | vcl::Window* pParent = pFrameWindow; | ||||||
3575 | while( pFrameWindow ) | ||||||
3576 | { | ||||||
3577 | pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++; | ||||||
3578 | while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow ) | ||||||
3579 | { | ||||||
3580 | pParent = pParent->GetParent(); | ||||||
3581 | } | ||||||
3582 | pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr; | ||||||
3583 | } | ||||||
3584 | } | ||||||
3585 | void Window::DecModalCount() | ||||||
3586 | { | ||||||
3587 | vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow; | ||||||
3588 | vcl::Window* pParent = pFrameWindow; | ||||||
3589 | while( pFrameWindow ) | ||||||
3590 | { | ||||||
3591 | pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--; | ||||||
3592 | while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow ) | ||||||
3593 | { | ||||||
3594 | pParent = pParent->GetParent(); | ||||||
3595 | } | ||||||
3596 | pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr; | ||||||
3597 | } | ||||||
3598 | } | ||||||
3599 | |||||||
3600 | void Window::ImplIsInTaskPaneList( bool mbIsInTaskList ) | ||||||
3601 | { | ||||||
3602 | mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList; | ||||||
3603 | } | ||||||
3604 | |||||||
3605 | void Window::ImplNotifyIconifiedState( bool bIconified ) | ||||||
3606 | { | ||||||
3607 | mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize ); | ||||||
3608 | // #109206# notify client window as well to have toolkit topwindow listeners notified | ||||||
3609 | if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow ) | ||||||
3610 | mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize ); | ||||||
3611 | } | ||||||
3612 | |||||||
3613 | bool Window::HasActiveChildFrame() const | ||||||
3614 | { | ||||||
3615 | bool bRet = false; | ||||||
3616 | vcl::Window *pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame; | ||||||
3617 | while( pFrameWin ) | ||||||
3618 | { | ||||||
3619 | if( pFrameWin != mpWindowImpl->mpFrameWindow ) | ||||||
3620 | { | ||||||
3621 | bool bDecorated = false; | ||||||
3622 | VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow(); | ||||||
3623 | // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can | ||||||
3624 | // be removed for ToolBoxes to influence the keyboard accessibility | ||||||
3625 | // thus WB_MOVEABLE is no indicator for decoration anymore | ||||||
3626 | // but FloatingWindows carry this information in their TitleType... | ||||||
3627 | // TODO: avoid duplicate WinBits !!! | ||||||
3628 | if( pChildFrame && pChildFrame->ImplIsFloatingWindow() ) | ||||||
3629 | bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE; | ||||||
3630 | if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) ) | ||||||
3631 | if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() ) | ||||||
3632 | { | ||||||
3633 | if( ImplIsChild( pChildFrame, true ) ) | ||||||
3634 | { | ||||||
3635 | bRet = true; | ||||||
3636 | break; | ||||||
3637 | } | ||||||
3638 | } | ||||||
3639 | } | ||||||
3640 | pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
3641 | } | ||||||
3642 | return bRet; | ||||||
3643 | } | ||||||
3644 | |||||||
3645 | LanguageType Window::GetInputLanguage() const | ||||||
3646 | { | ||||||
3647 | return mpWindowImpl->mpFrame->GetInputLanguage(); | ||||||
3648 | } | ||||||
3649 | |||||||
3650 | void Window::EnableNativeWidget( bool bEnable ) | ||||||
3651 | { | ||||||
3652 | static const char* pNoNWF = getenv( "SAL_NO_NWF" ); | ||||||
3653 | if( pNoNWF && *pNoNWF ) | ||||||
3654 | bEnable = false; | ||||||
3655 | |||||||
3656 | if( bEnable != ImplGetWinData()->mbEnableNativeWidget ) | ||||||
3657 | { | ||||||
3658 | ImplGetWinData()->mbEnableNativeWidget = bEnable; | ||||||
3659 | |||||||
3660 | // send datachanged event to allow for internal changes required for NWF | ||||||
3661 | // like clipmode, transparency, etc. | ||||||
3662 | DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, mxSettings.get(), AllSettingsFlags::STYLE ); | ||||||
3663 | CompatDataChanged( aDCEvt ); | ||||||
3664 | |||||||
3665 | // sometimes the borderwindow is queried, so keep it in sync | ||||||
3666 | if( mpWindowImpl->mpBorderWindow ) | ||||||
3667 | mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable; | ||||||
3668 | } | ||||||
3669 | |||||||
3670 | // push down, useful for compound controls | ||||||
3671 | VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild; | ||||||
3672 | while( pChild ) | ||||||
3673 | { | ||||||
3674 | pChild->EnableNativeWidget( bEnable ); | ||||||
3675 | pChild = pChild->mpWindowImpl->mpNext; | ||||||
3676 | } | ||||||
3677 | } | ||||||
3678 | |||||||
3679 | bool Window::IsNativeWidgetEnabled() const | ||||||
3680 | { | ||||||
3681 | return ImplGetWinData()->mbEnableNativeWidget; | ||||||
3682 | } | ||||||
3683 | |||||||
3684 | Reference< css::rendering::XCanvas > Window::ImplGetCanvas( bool bSpriteCanvas ) const | ||||||
3685 | { | ||||||
3686 | // try to retrieve hard reference from weak member | ||||||
3687 | Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas ); | ||||||
3688 | |||||||
3689 | // canvas still valid? Then we're done. | ||||||
3690 | if( xCanvas.is() ) | ||||||
3691 | return xCanvas; | ||||||
3692 | |||||||
3693 | Sequence< Any > aArg(5); | ||||||
3694 | |||||||
3695 | // Feed any with operating system's window handle | ||||||
3696 | |||||||
3697 | // common: first any is VCL pointer to window (for VCL canvas) | ||||||
3698 | aArg[ 0 ] <<= reinterpret_cast<sal_Int64>(this); | ||||||
3699 | aArg[ 1 ] <<= css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ); | ||||||
3700 | aArg[ 2 ] <<= mpWindowImpl->mbAlwaysOnTop; | ||||||
3701 | aArg[ 3 ] <<= Reference< css::awt::XWindow >( | ||||||
3702 | const_cast<vcl::Window*>(this)->GetComponentInterface(), | ||||||
3703 | UNO_QUERY ); | ||||||
3704 | aArg[ 4 ] = GetSystemGfxDataAny(); | ||||||
3705 | |||||||
3706 | Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); | ||||||
3707 | |||||||
3708 | // Create canvas instance with window handle | ||||||
3709 | |||||||
3710 | static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory( | ||||||
3711 | css::rendering::CanvasFactory::create( xContext ) ); | ||||||
3712 | Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get()); | ||||||
3713 | |||||||
3714 | if(xCanvasFactory.is()) | ||||||
3715 | { | ||||||
3716 | #ifdef _WIN32 | ||||||
3717 | // see #140456# - if we're running on a multiscreen setup, | ||||||
3718 | // request special, multi-screen safe sprite canvas | ||||||
3719 | // implementation (not DX5 canvas, as it cannot cope with | ||||||
3720 | // surfaces spanning multiple displays). Note: canvas | ||||||
3721 | // (without sprite) stays the same) | ||||||
3722 | const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay; | ||||||
3723 | if( nDisplay >= Application::GetScreenCount() ) | ||||||
3724 | { | ||||||
3725 | xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext( | ||||||
3726 | bSpriteCanvas ? | ||||||
3727 | OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) : | ||||||
3728 | OUString( "com.sun.star.rendering.Canvas.MultiScreen" ), | ||||||
3729 | aArg, | ||||||
3730 | xContext ), | ||||||
3731 | UNO_QUERY ); | ||||||
3732 | |||||||
3733 | } | ||||||
3734 | else | ||||||
3735 | #endif | ||||||
3736 | { | ||||||
3737 | xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext( | ||||||
3738 | bSpriteCanvas ? | ||||||
3739 | OUString( "com.sun.star.rendering.SpriteCanvas" ) : | ||||||
3740 | OUString( "com.sun.star.rendering.Canvas" ), | ||||||
3741 | aArg, | ||||||
3742 | xContext ), | ||||||
3743 | UNO_QUERY ); | ||||||
3744 | |||||||
3745 | } | ||||||
3746 | mpWindowImpl->mxCanvas = xCanvas; | ||||||
3747 | } | ||||||
3748 | |||||||
3749 | // no factory??? Empty reference, then. | ||||||
3750 | return xCanvas; | ||||||
3751 | } | ||||||
3752 | |||||||
3753 | Reference< css::rendering::XCanvas > Window::GetCanvas() const | ||||||
3754 | { | ||||||
3755 | return ImplGetCanvas( false ); | ||||||
3756 | } | ||||||
3757 | |||||||
3758 | Reference< css::rendering::XSpriteCanvas > Window::GetSpriteCanvas() const | ||||||
3759 | { | ||||||
3760 | Reference< css::rendering::XSpriteCanvas > xSpriteCanvas( | ||||||
3761 | ImplGetCanvas( true ), UNO_QUERY ); | ||||||
3762 | return xSpriteCanvas; | ||||||
3763 | } | ||||||
3764 | |||||||
3765 | OUString Window::GetSurroundingText() const | ||||||
3766 | { | ||||||
3767 | return OUString(); | ||||||
3768 | } | ||||||
3769 | |||||||
3770 | Selection Window::GetSurroundingTextSelection() const | ||||||
3771 | { | ||||||
3772 | return Selection( 0, 0 ); | ||||||
3773 | } | ||||||
3774 | |||||||
3775 | bool Window::UsePolyPolygonForComplexGradient() | ||||||
3776 | { | ||||||
3777 | return meRasterOp != RasterOp::OverPaint; | ||||||
3778 | } | ||||||
3779 | |||||||
3780 | void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/) | ||||||
3781 | { | ||||||
3782 | } | ||||||
3783 | |||||||
3784 | const SystemEnvData* Window::GetSystemData() const | ||||||
3785 | { | ||||||
3786 | |||||||
3787 | return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr; | ||||||
3788 | } | ||||||
3789 | |||||||
3790 | bool Window::SupportsDoubleBuffering() const | ||||||
3791 | { | ||||||
3792 | return mpWindowImpl->mpFrameData->mpBuffer; | ||||||
3793 | } | ||||||
3794 | |||||||
3795 | void Window::RequestDoubleBuffering(bool bRequest) | ||||||
3796 | { | ||||||
3797 | if (bRequest) | ||||||
3798 | { | ||||||
3799 | mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>(); | ||||||
3800 | // Make sure that the buffer size matches the frame size. | ||||||
3801 | mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel()); | ||||||
3802 | } | ||||||
3803 | else | ||||||
3804 | mpWindowImpl->mpFrameData->mpBuffer.reset(); | ||||||
3805 | } | ||||||
3806 | |||||||
3807 | /* | ||||||
3808 | * The rationale here is that we moved destructors to | ||||||
3809 | * dispose and this altered a lot of code paths, that | ||||||
3810 | * are better left unchanged for now. | ||||||
3811 | */ | ||||||
3812 | #define COMPAT_BODY(method,args)if (!mpWindowImpl || mpWindowImpl->mbInDispose) Window::method args; else method args; \ | ||||||
3813 | if (!mpWindowImpl || mpWindowImpl->mbInDispose) \ | ||||||
3814 | Window::method args; \ | ||||||
3815 | else \ | ||||||
3816 | method args; | ||||||
3817 | |||||||
3818 | void Window::CompatGetFocus() | ||||||
3819 | { | ||||||
3820 | COMPAT_BODY(GetFocus,())if (!mpWindowImpl || mpWindowImpl->mbInDispose) Window::GetFocus (); else GetFocus (); | ||||||
3821 | } | ||||||
3822 | |||||||
3823 | void Window::CompatLoseFocus() | ||||||
3824 | { | ||||||
3825 | COMPAT_BODY(LoseFocus,())if (!mpWindowImpl || mpWindowImpl->mbInDispose) Window::LoseFocus (); else LoseFocus (); | ||||||
3826 | } | ||||||
3827 | |||||||
3828 | void Window::CompatStateChanged( StateChangedType nStateChange ) | ||||||
3829 | { | ||||||
3830 | COMPAT_BODY(StateChanged,(nStateChange))if (!mpWindowImpl || mpWindowImpl->mbInDispose) Window::StateChanged (nStateChange); else StateChanged (nStateChange); | ||||||
3831 | } | ||||||
3832 | |||||||
3833 | void Window::CompatDataChanged( const DataChangedEvent& rDCEvt ) | ||||||
3834 | { | ||||||
3835 | COMPAT_BODY(DataChanged,(rDCEvt))if (!mpWindowImpl || mpWindowImpl->mbInDispose) Window::DataChanged (rDCEvt); else DataChanged (rDCEvt); | ||||||
3836 | } | ||||||
3837 | |||||||
3838 | bool Window::CompatPreNotify( NotifyEvent& rNEvt ) | ||||||
3839 | { | ||||||
3840 | if (!mpWindowImpl || mpWindowImpl->mbInDispose) | ||||||
3841 | return Window::PreNotify( rNEvt ); | ||||||
3842 | else | ||||||
3843 | return PreNotify( rNEvt ); | ||||||
3844 | } | ||||||
3845 | |||||||
3846 | bool Window::CompatNotify( NotifyEvent& rNEvt ) | ||||||
3847 | { | ||||||
3848 | if (!mpWindowImpl || mpWindowImpl->mbInDispose) | ||||||
3849 | return Window::EventNotify( rNEvt ); | ||||||
3850 | else | ||||||
3851 | return EventNotify( rNEvt ); | ||||||
3852 | } | ||||||
3853 | |||||||
3854 | void Window::set_id(const OUString& rID) | ||||||
3855 | { | ||||||
3856 | mpWindowImpl->maID = rID; | ||||||
3857 | } | ||||||
3858 | |||||||
3859 | const OUString& Window::get_id() const | ||||||
3860 | { | ||||||
3861 | return mpWindowImpl->maID; | ||||||
3862 | } | ||||||
3863 | |||||||
3864 | FactoryFunction Window::GetUITestFactory() const | ||||||
3865 | { | ||||||
3866 | return WindowUIObject::create; | ||||||
3867 | } | ||||||
3868 | |||||||
3869 | } /* namespace vcl */ | ||||||
3870 | |||||||
3871 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||
22 | |||||||
23 | #include "sal/config.h" | ||||||
24 | |||||||
25 | #include <cassert> | ||||||
26 | #include <cstddef> | ||||||
27 | #include <functional> | ||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
29 | #include <type_traits> | ||||||
30 | #endif | ||||||
31 | |||||||
32 | #include "sal/types.h" | ||||||
33 | |||||||
34 | namespace rtl | ||||||
35 | { | ||||||
36 | |||||||
37 | /** Template reference class for reference type. | ||||||
38 | */ | ||||||
39 | template <class reference_type> | ||||||
40 | class Reference | ||||||
41 | { | ||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||
43 | */ | ||||||
44 | reference_type * m_pBody; | ||||||
45 | |||||||
46 | |||||||
47 | public: | ||||||
48 | /** Constructor... | ||||||
49 | */ | ||||||
50 | Reference() | ||||||
51 | : m_pBody (NULL__null) | ||||||
52 | {} | ||||||
53 | |||||||
54 | |||||||
55 | /** Constructor... | ||||||
56 | */ | ||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||
58 | : m_pBody (pBody) | ||||||
59 | { | ||||||
60 | } | ||||||
61 | |||||||
62 | /** Constructor... | ||||||
63 | */ | ||||||
64 | Reference (reference_type * pBody) | ||||||
65 | : m_pBody (pBody) | ||||||
66 | { | ||||||
67 | if (m_pBody) | ||||||
68 | m_pBody->acquire(); | ||||||
69 | } | ||||||
70 | |||||||
71 | /** Copy constructor... | ||||||
72 | */ | ||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||
74 | : m_pBody (handle.m_pBody) | ||||||
75 | { | ||||||
76 | if (m_pBody) | ||||||
77 | m_pBody->acquire(); | ||||||
78 | } | ||||||
79 | |||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
81 | /** Move constructor... | ||||||
82 | */ | ||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||
84 | : m_pBody (handle.m_pBody) | ||||||
85 | { | ||||||
86 | handle.m_pBody = nullptr; | ||||||
87 | } | ||||||
88 | #endif | ||||||
89 | |||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||
92 | |||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||
94 | |||||||
95 | @param rRef another reference | ||||||
96 | */ | ||||||
97 | template< class derived_type > | ||||||
98 | inline Reference( | ||||||
99 | const Reference< derived_type > & rRef, | ||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||
101 | : m_pBody (rRef.get()) | ||||||
102 | { | ||||||
103 | if (m_pBody) | ||||||
104 | m_pBody->acquire(); | ||||||
105 | } | ||||||
106 | #endif | ||||||
107 | |||||||
108 | /** Destructor... | ||||||
109 | */ | ||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||
111 | { | ||||||
112 | if (m_pBody
| ||||||
113 | m_pBody->release(); | ||||||
114 | } | ||||||
115 | |||||||
116 | /** Set... | ||||||
117 | Similar to assignment. | ||||||
118 | */ | ||||||
119 | Reference<reference_type> & | ||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||
121 | { | ||||||
122 | if (pBody) | ||||||
123 | pBody->acquire(); | ||||||
124 | reference_type * const pOld = m_pBody; | ||||||
125 | m_pBody = pBody; | ||||||
126 | if (pOld) | ||||||
127 | pOld->release(); | ||||||
128 | return *this; | ||||||
129 | } | ||||||
130 | |||||||
131 | /** Assignment. | ||||||
132 | Unbinds this instance from its body (if bound) and | ||||||
133 | bind it to the body represented by the handle. | ||||||
134 | */ | ||||||
135 | Reference<reference_type> & | ||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||
137 | { | ||||||
138 | return set( handle.m_pBody ); | ||||||
139 | } | ||||||
140 | |||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
142 | /** Assignment. | ||||||
143 | * Unbinds this instance from its body (if bound), | ||||||
144 | * bind it to the body represented by the handle, and | ||||||
145 | * set the body represented by the handle to nullptr. | ||||||
146 | */ | ||||||
147 | Reference<reference_type> & | ||||||
148 | operator= (Reference<reference_type> && handle) | ||||||
149 | { | ||||||
150 | // self-movement guts ourself | ||||||
151 | if (m_pBody) | ||||||
152 | m_pBody->release(); | ||||||
153 | m_pBody = handle.m_pBody; | ||||||
154 | handle.m_pBody = nullptr; | ||||||
155 | return *this; | ||||||
156 | } | ||||||
157 | #endif | ||||||
158 | |||||||
159 | /** Assignment... | ||||||
160 | */ | ||||||
161 | Reference<reference_type> & | ||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||
163 | { | ||||||
164 | return set( pBody ); | ||||||
165 | } | ||||||
166 | |||||||
167 | /** Unbind the body from this handle. | ||||||
168 | Note that for a handle representing a large body, | ||||||
169 | "handle.clear().set(new body());" _might_ | ||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||
171 | since in the second case two large objects exist in memory | ||||||
172 | (the old body and the new body). | ||||||
173 | */ | ||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||
175 | { | ||||||
176 | if (m_pBody) | ||||||
177 | { | ||||||
178 | reference_type * const pOld = m_pBody; | ||||||
179 | m_pBody = NULL__null; | ||||||
180 | pOld->release(); | ||||||
181 | } | ||||||
182 | return *this; | ||||||
183 | } | ||||||
184 | |||||||
185 | |||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||
188 | are the same. | ||||||
189 | */ | ||||||
190 | reference_type * SAL_CALL get() const | ||||||
191 | { | ||||||
192 | return m_pBody; | ||||||
193 | } | ||||||
194 | |||||||
195 | |||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||
197 | */ | ||||||
198 | reference_type * SAL_CALL operator->() const | ||||||
199 | { | ||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||
201 | return m_pBody; | ||||||
202 | } | ||||||
203 | |||||||
204 | |||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||
206 | */ | ||||||
207 | reference_type & SAL_CALL operator*() const | ||||||
208 | { | ||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||
210 | return *m_pBody; | ||||||
211 | } | ||||||
212 | |||||||
213 | |||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||
215 | */ | ||||||
216 | bool SAL_CALL is() const | ||||||
217 | { | ||||||
218 | return (m_pBody != NULL__null); | ||||||
219 | } | ||||||
220 | |||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||
223 | */ | ||||||
224 | explicit operator bool() const | ||||||
225 | { | ||||||
226 | return is(); | ||||||
227 | } | ||||||
228 | #endif | ||||||
229 | |||||||
230 | /** Returns True if this points to pBody. | ||||||
231 | */ | ||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||
233 | { | ||||||
234 | return (m_pBody == pBody); | ||||||
235 | } | ||||||
236 | |||||||
237 | |||||||
238 | /** Returns True if handle points to the same body. | ||||||
239 | */ | ||||||
240 | bool | ||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||
242 | { | ||||||
243 | return (m_pBody == handle.m_pBody); | ||||||
244 | } | ||||||
245 | |||||||
246 | |||||||
247 | /** Needed to place References into STL collection. | ||||||
248 | */ | ||||||
249 | bool | ||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||
251 | { | ||||||
252 | return (m_pBody != handle.m_pBody); | ||||||
253 | } | ||||||
254 | |||||||
255 | |||||||
256 | /** Needed to place References into STL collection. | ||||||
257 | */ | ||||||
258 | bool | ||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||
260 | { | ||||||
261 | return (m_pBody < handle.m_pBody); | ||||||
262 | } | ||||||
263 | |||||||
264 | |||||||
265 | /** Needed to place References into STL collection. | ||||||
266 | */ | ||||||
267 | bool | ||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||
269 | { | ||||||
270 | return (m_pBody > handle.m_pBody); | ||||||
271 | } | ||||||
272 | }; | ||||||
273 | |||||||
274 | } // namespace rtl | ||||||
275 | |||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
277 | namespace std | ||||||
278 | { | ||||||
279 | |||||||
280 | /// @cond INTERNAL | ||||||
281 | /** | ||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||
283 | |||||||
284 | @since LibreOffice 6.3 | ||||||
285 | */ | ||||||
286 | template<typename T> | ||||||
287 | struct hash<::rtl::Reference<T>> | ||||||
288 | { | ||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||
290 | { return std::size_t(s.get()); } | ||||||
291 | }; | ||||||
292 | /// @endcond | ||||||
293 | |||||||
294 | } | ||||||
295 | |||||||
296 | #endif | ||||||
297 | |||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||
299 | |||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |