File: | home/maarten/src/libreoffice/core/vcl/source/window/window.cxx |
Warning: | line 2787, column 14 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 |