/src/libreoffice/toolkit/source/helper/unowrapper.cxx
Line | Count | Source |
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 <toolkit/helper/vclunohelper.hxx> |
21 | | #include <toolkit/awt/vclxwindow.hxx> |
22 | | #include <toolkit/awt/vclxwindows.hxx> |
23 | | #include <toolkit/awt/vclxmenu.hxx> |
24 | | #include <awt/vclxcontainer.hxx> |
25 | | #include <awt/vclxgraphics.hxx> |
26 | | #include <awt/vclxtopwindow.hxx> |
27 | | #include <awt/vclxwindows.hxx> |
28 | | |
29 | | #include <toolkit/dllapi.h> |
30 | | #include <vcl/menu.hxx> |
31 | | |
32 | | #include <helper/unowrapper.hxx> |
33 | | |
34 | | using namespace ::com::sun::star; |
35 | | |
36 | | static rtl::Reference<VCLXWindow> CreateXWindow( vcl::Window const * pWindow ) |
37 | 58.3k | { |
38 | 58.3k | switch ( pWindow->GetType() ) |
39 | 58.3k | { |
40 | 0 | case WindowType::IMAGEBUTTON: |
41 | 0 | case WindowType::SPINBUTTON: |
42 | 0 | case WindowType::MENUBUTTON: |
43 | 0 | case WindowType::MOREBUTTON: |
44 | 0 | case WindowType::PUSHBUTTON: |
45 | 0 | case WindowType::HELPBUTTON: |
46 | 0 | case WindowType::OKBUTTON: |
47 | 0 | case WindowType::CANCELBUTTON: return new VCLXButton; |
48 | 0 | case WindowType::CHECKBOX: return new VCLXCheckBox; |
49 | | // #i95042# |
50 | | // A Window of type <MetricBox> is inherited from type <ComboBox>. |
51 | | // Thus, it does make more sense to return a <VCLXComboBox> instance |
52 | | // instead of only a <VCLXWindow> instance, especially regarding its |
53 | | // corresponding accessibility API. |
54 | 0 | case WindowType::METRICBOX: |
55 | 0 | case WindowType::COMBOBOX: return new VCLXComboBox; |
56 | 0 | case WindowType::FORMATTEDFIELD: return new SVTXNumericField; |
57 | 0 | case WindowType::SPINFIELD: |
58 | 0 | case WindowType::CURRENCYFIELD: return new VCLXNumericField; |
59 | 0 | case WindowType::DATEFIELD: return new VCLXDateField; |
60 | 0 | case WindowType::MULTILINEEDIT: |
61 | 0 | case WindowType::EDIT: return new VCLXEdit; |
62 | 0 | case WindowType::METRICFIELD: return new VCLXSpinField; |
63 | 0 | case WindowType::MESSBOX: |
64 | 0 | case WindowType::INFOBOX: |
65 | 0 | case WindowType::WARNINGBOX: |
66 | 0 | case WindowType::QUERYBOX: |
67 | 0 | case WindowType::ERRORBOX: return new VCLXMessageBox; |
68 | 0 | case WindowType::FIXEDIMAGE: return new VCLXImageControl; |
69 | 0 | case WindowType::FIXEDTEXT: return new VCLXFixedText; |
70 | 0 | case WindowType::MULTILISTBOX: |
71 | 0 | case WindowType::LISTBOX: return new VCLXListBox; |
72 | 0 | case WindowType::DIALOG: |
73 | 0 | case WindowType::TABDIALOG: |
74 | 0 | case WindowType::BUTTONDIALOG: |
75 | 0 | case WindowType::MODELESSDIALOG: return new VCLXDialog; |
76 | 0 | case WindowType::PATTERNFIELD: return new VCLXPatternField; |
77 | 0 | case WindowType::RADIOBUTTON: return new VCLXRadioButton; |
78 | 0 | case WindowType::SCROLLBAR: return new VCLXScrollBar; |
79 | 0 | case WindowType::TIMEFIELD: return new VCLXTimeField; |
80 | | |
81 | 30 | case WindowType::WORKWINDOW: |
82 | 30 | case WindowType::DOCKINGWINDOW: |
83 | 30 | case WindowType::FLOATINGWINDOW: |
84 | 30 | case WindowType::HELPTEXTWINDOW: return new VCLXTopWindow; |
85 | | |
86 | 3.68k | case WindowType::WINDOW: |
87 | 3.68k | case WindowType::TABPAGE: return new VCLXContainer; |
88 | 0 | case WindowType::TABCONTROL: return new VCLXMultiPage; |
89 | | |
90 | 3.70k | case WindowType::BORDERWINDOW: |
91 | 3.70k | { |
92 | 3.70k | if (pWindow->IsNativeFrame()) |
93 | 3.67k | return new VCLXTopWindow; |
94 | 30 | return new VCLXWindow(true); |
95 | 3.70k | } |
96 | | |
97 | | // case WindowType::FIXEDLINE: |
98 | | // case WindowType::FIXEDBITMAP: |
99 | | // case WindowType::DATEBOX: |
100 | | // case WindowType::GROUPBOX: |
101 | | // case WindowType::LONGCURRENCYBOX: |
102 | | // case WindowType::SPLITTER: |
103 | | // case WindowType::STATUSBAR: |
104 | | // case WindowType::TABCONTROL: |
105 | | // case WindowType::NUMERICBOX: |
106 | | // case WindowType::TRISTATEBOX: |
107 | | // case WindowType::TIMEBOX: |
108 | | // case WindowType::SPLITWINDOW: |
109 | | // case WindowType::SCROLLBARBOX: |
110 | | // case WindowType::PATTERNBOX: |
111 | | // case WindowType::CURRENCYBOX: |
112 | 0 | case WindowType::HEADERBAR: |
113 | 0 | case WindowType::TOOLBOX: |
114 | 50.9k | default: return new VCLXWindow( true ); |
115 | 58.3k | } |
116 | 58.3k | } |
117 | | |
118 | | |
119 | | |
120 | | |
121 | | extern "C" { |
122 | | |
123 | | TOOLKIT_DLLPUBLIC UnoWrapperBase* CreateUnoWrapper() |
124 | 30 | { |
125 | 30 | return new UnoWrapper( nullptr ); |
126 | 30 | } |
127 | | |
128 | | } // extern "C" |
129 | | |
130 | | |
131 | | UnoWrapper::UnoWrapper( const css::uno::Reference< css::awt::XToolkit>& rxToolkit ) |
132 | 30 | { |
133 | 30 | mxToolkit = rxToolkit; |
134 | 30 | } |
135 | | |
136 | | void UnoWrapper::Destroy() |
137 | 0 | { |
138 | 0 | delete this; |
139 | 0 | } |
140 | | |
141 | | UnoWrapper::~UnoWrapper() |
142 | 0 | { |
143 | 0 | } |
144 | | |
145 | | css::uno::Reference< css::awt::XToolkit> UnoWrapper::GetVCLToolkit() |
146 | 0 | { |
147 | 0 | if ( !mxToolkit.is() ) |
148 | 0 | mxToolkit = VCLUnoHelper::CreateToolkit(); |
149 | 0 | return mxToolkit; |
150 | 0 | } |
151 | | |
152 | | css::uno::Reference< css::awt::XVclWindowPeer> UnoWrapper::GetWindowInterface( vcl::Window* pWindow ) |
153 | 58.3k | { |
154 | 58.3k | css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer(); |
155 | 58.3k | if ( xPeer ) |
156 | 0 | return xPeer; |
157 | | |
158 | 58.3k | rtl::Reference<VCLXWindow> xVCLXWindow = CreateXWindow( pWindow ); |
159 | 58.3k | xVCLXWindow->SetWindow( pWindow ); |
160 | 58.3k | pWindow->SetWindowPeer( xVCLXWindow, xVCLXWindow.get() ); |
161 | 58.3k | return xVCLXWindow; |
162 | 58.3k | } |
163 | | |
164 | | VclPtr<vcl::Window> UnoWrapper::GetWindow(const css::uno::Reference<css::awt::XWindow>& rWindow) |
165 | 0 | { |
166 | 0 | return VCLUnoHelper::GetWindow(rWindow); |
167 | 0 | } |
168 | | |
169 | | void UnoWrapper::SetWindowInterface( vcl::Window* pWindow, const css::uno::Reference< css::awt::XVclWindowPeer> & xIFace ) |
170 | 44.0k | { |
171 | 44.0k | VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( xIFace.get() ); |
172 | | |
173 | 44.0k | assert( pVCLXWindow && "must be a VCLXWindow subclass" ); |
174 | 44.0k | if ( !pVCLXWindow ) |
175 | 0 | return; |
176 | | |
177 | 44.0k | if (!pWindow) |
178 | 36.7k | { |
179 | | // we are disconnecting a peer from a window |
180 | 36.7k | pVCLXWindow->SetWindow( nullptr ); |
181 | 36.7k | } |
182 | 7.24k | else |
183 | 7.24k | { |
184 | 7.24k | css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer(); |
185 | 7.24k | if( xPeer.is() ) |
186 | 0 | { |
187 | 0 | bool bSameInstance( pVCLXWindow == dynamic_cast< VCLXWindow* >( xPeer.get() )); |
188 | 0 | SAL_WARN_IF( !bSameInstance, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" ); |
189 | 0 | if ( bSameInstance ) |
190 | 0 | return; |
191 | 0 | } |
192 | 7.24k | pVCLXWindow->SetWindow( pWindow ); |
193 | 7.24k | pWindow->SetWindowPeer( xIFace, pVCLXWindow ); |
194 | 7.24k | } |
195 | 44.0k | } |
196 | | |
197 | | css::uno::Reference<css::awt::XPopupMenu> UnoWrapper::CreateMenuInterface( PopupMenu* pPopupMenu ) |
198 | 0 | { |
199 | 0 | return new VCLXPopupMenu(pPopupMenu); |
200 | 0 | } |
201 | | |
202 | | css::uno::Reference< css::awt::XGraphics> UnoWrapper::CreateGraphics( OutputDevice* pOutDev ) |
203 | 0 | { |
204 | 0 | rtl::Reference<VCLXGraphics> pGrf = new VCLXGraphics; |
205 | 0 | pGrf->Init( pOutDev ); |
206 | 0 | return pGrf; |
207 | 0 | } |
208 | | |
209 | | void UnoWrapper::ReleaseAllGraphics( OutputDevice* pOutDev ) |
210 | 0 | { |
211 | 0 | std::vector< VCLXGraphics* > *pLst = pOutDev->GetUnoGraphicsList(); |
212 | 0 | if ( pLst ) |
213 | 0 | { |
214 | 0 | for (VCLXGraphics* pGrf : *pLst) |
215 | 0 | { |
216 | 0 | pGrf->SetOutputDevice( nullptr ); |
217 | 0 | } |
218 | 0 | } |
219 | |
|
220 | 0 | } |
221 | | |
222 | | static bool lcl_ImplIsParent( vcl::Window const * pParentWindow, vcl::Window* pPossibleChild ) |
223 | 0 | { |
224 | 0 | vcl::Window* pWindow = ( pPossibleChild != pParentWindow ) ? pPossibleChild : nullptr; |
225 | 0 | while ( pWindow && ( pWindow != pParentWindow ) ) |
226 | 0 | pWindow = pWindow->GetParent(); |
227 | |
|
228 | 0 | return pWindow != nullptr; |
229 | 0 | } |
230 | | |
231 | | void UnoWrapper::WindowDestroyed( vcl::Window* pWindow ) |
232 | 91.9k | { |
233 | | // their still might be some children created with css::loader::Java |
234 | | // that would otherwise not be destroyed until the garbage collector cleans up |
235 | 91.9k | VclPtr< vcl::Window > pChild = pWindow->GetWindow( GetWindowType::FirstChild ); |
236 | 121k | while ( pChild ) |
237 | 29.4k | { |
238 | 29.4k | VclPtr< vcl::Window > pNextChild = pChild->GetWindow( GetWindowType::Next ); |
239 | | |
240 | 29.4k | VclPtr< vcl::Window > pClient = pChild->GetWindow( GetWindowType::Client ); |
241 | 29.4k | if ( pClient && pClient->GetWindowPeer() ) |
242 | 29.4k | { |
243 | 29.4k | css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false ); |
244 | 29.4k | xComp->dispose(); |
245 | 29.4k | } |
246 | 0 | else |
247 | 0 | { |
248 | | // We need it to dispose the child windows properly (even without window peer), |
249 | | // otherwise the vcl::Window will be leaked. |
250 | 0 | pClient.disposeAndClear(); |
251 | 0 | } |
252 | | |
253 | 29.4k | pChild = std::move(pNextChild); |
254 | 29.4k | } |
255 | | |
256 | | // find system windows... |
257 | 91.9k | VclPtr< vcl::Window > pOverlap = pWindow->GetWindow( GetWindowType::Overlap ); |
258 | 91.9k | if ( pOverlap ) |
259 | 91.9k | { |
260 | 91.9k | pOverlap = pOverlap->GetWindow( GetWindowType::FirstOverlap ); |
261 | 91.9k | while ( pOverlap ) |
262 | 0 | { |
263 | 0 | VclPtr< vcl::Window > pNextOverlap = pOverlap->GetWindow( GetWindowType::Next ); |
264 | 0 | VclPtr< vcl::Window > pClient = pOverlap->GetWindow( GetWindowType::Client ); |
265 | |
|
266 | 0 | if ( pClient && pClient->GetWindowPeer() && lcl_ImplIsParent( pWindow, pClient ) ) |
267 | 0 | { |
268 | 0 | css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false ); |
269 | 0 | xComp->dispose(); |
270 | 0 | } |
271 | |
|
272 | 0 | pOverlap = std::move(pNextOverlap); |
273 | 0 | } |
274 | 91.9k | } |
275 | | |
276 | 91.9k | { |
277 | 91.9k | VclPtr< vcl::Window > pParent = pWindow->GetParent(); |
278 | 91.9k | if ( pParent && pParent->GetWindowPeer() ) |
279 | 47.8k | pParent->GetWindowPeer()->notifyWindowRemoved( *pWindow ); |
280 | 91.9k | } |
281 | | |
282 | 91.9k | VCLXWindow* pWindowPeer = pWindow->GetWindowPeer(); |
283 | 91.9k | uno::Reference< lang::XComponent > xWindowPeerComp = pWindow->GetComponentInterface( false ); |
284 | 91.9k | OSL_ENSURE( ( pWindowPeer != nullptr ) == xWindowPeerComp.is(), |
285 | 91.9k | "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" ); |
286 | 91.9k | if ( pWindowPeer ) |
287 | 7.36k | { |
288 | 7.36k | pWindowPeer->SetWindow( nullptr ); |
289 | 7.36k | pWindow->SetWindowPeer( nullptr, nullptr ); |
290 | 7.36k | } |
291 | 91.9k | if ( xWindowPeerComp.is() ) |
292 | 7.36k | xWindowPeerComp->dispose(); |
293 | | |
294 | | // #102132# Iterate over frames after setting Window peer to NULL, |
295 | | // because while destroying other frames, we get into the method again and try |
296 | | // to destroy this window again... |
297 | | // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children |
298 | | // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme |
299 | | // performance penalties) |
300 | 91.9k | VclPtr< vcl::Window > pTopWindowChild = pWindow->GetWindow( GetWindowType::FirstTopWindowChild ); |
301 | 91.9k | while ( pTopWindowChild ) |
302 | 0 | { |
303 | 0 | OSL_ENSURE( pTopWindowChild->GetParent() == pWindow, |
304 | 0 | "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" ); |
305 | |
|
306 | 0 | VclPtr< vcl::Window > pNextTopChild = pTopWindowChild->GetWindow( GetWindowType::NextTopWindowSibling ); |
307 | |
|
308 | 0 | pTopWindowChild.disposeAndClear(); |
309 | 0 | pTopWindowChild = std::move(pNextTopChild); |
310 | 0 | } |
311 | 91.9k | } |
312 | | |
313 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |