1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
29 #include <toolkit/dllapi.h>
30 #include <vcl/menu.hxx>
32 #include <helper/unowrapper.hxx>
34 using namespace ::com::sun::star
;
36 static rtl::Reference
<VCLXWindow
> CreateXWindow( vcl::Window
const * pWindow
)
38 switch ( pWindow
->GetType() )
40 case WindowType::IMAGEBUTTON
:
41 case WindowType::SPINBUTTON
:
42 case WindowType::MENUBUTTON
:
43 case WindowType::MOREBUTTON
:
44 case WindowType::PUSHBUTTON
:
45 case WindowType::HELPBUTTON
:
46 case WindowType::OKBUTTON
:
47 case WindowType::CANCELBUTTON
: return new VCLXButton
;
48 case WindowType::CHECKBOX
: return new VCLXCheckBox
;
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 case WindowType::METRICBOX
:
55 case WindowType::COMBOBOX
: return new VCLXComboBox
;
56 case WindowType::FORMATTEDFIELD
: return new SVTXNumericField
;
57 case WindowType::SPINFIELD
:
58 case WindowType::CURRENCYFIELD
: return new VCLXNumericField
;
59 case WindowType::DATEFIELD
: return new VCLXDateField
;
60 case WindowType::MULTILINEEDIT
:
61 case WindowType::EDIT
: return new VCLXEdit
;
62 case WindowType::METRICFIELD
: return new VCLXSpinField
;
63 case WindowType::MESSBOX
:
64 case WindowType::INFOBOX
:
65 case WindowType::WARNINGBOX
:
66 case WindowType::QUERYBOX
:
67 case WindowType::ERRORBOX
: return new VCLXMessageBox
;
68 case WindowType::FIXEDIMAGE
: return new VCLXImageControl
;
69 case WindowType::FIXEDTEXT
: return new VCLXFixedText
;
70 case WindowType::MULTILISTBOX
:
71 case WindowType::LISTBOX
: return new VCLXListBox
;
72 case WindowType::DIALOG
:
73 case WindowType::TABDIALOG
:
74 case WindowType::BUTTONDIALOG
:
75 case WindowType::MODELESSDIALOG
: return new VCLXDialog
;
76 case WindowType::PATTERNFIELD
: return new VCLXPatternField
;
77 case WindowType::RADIOBUTTON
: return new VCLXRadioButton
;
78 case WindowType::SCROLLBAR
: return new VCLXScrollBar
;
79 case WindowType::TIMEFIELD
: return new VCLXTimeField
;
81 case WindowType::WORKWINDOW
:
82 case WindowType::DOCKINGWINDOW
:
83 case WindowType::FLOATINGWINDOW
:
84 case WindowType::HELPTEXTWINDOW
: return new VCLXTopWindow
;
86 case WindowType::WINDOW
:
87 case WindowType::TABPAGE
: return new VCLXContainer
;
89 case WindowType::TOOLBOX
: return new VCLXToolBox
;
90 case WindowType::TABCONTROL
: return new VCLXMultiPage
;
92 case WindowType::HEADERBAR
: return new VCLXHeaderBar
;
94 // case WindowType::FIXEDLINE:
95 // case WindowType::FIXEDBITMAP:
96 // case WindowType::DATEBOX:
97 // case WindowType::GROUPBOX:
98 // case WindowType::LONGCURRENCYBOX:
99 // case WindowType::SPLITTER:
100 // case WindowType::STATUSBAR:
101 // case WindowType::TABCONTROL:
102 // case WindowType::NUMERICBOX:
103 // case WindowType::TRISTATEBOX:
104 // case WindowType::TIMEBOX:
105 // case WindowType::SPLITWINDOW:
106 // case WindowType::SCROLLBARBOX:
107 // case WindowType::PATTERNBOX:
108 // case WindowType::CURRENCYBOX:
109 default: return new VCLXWindow( true );
118 TOOLKIT_DLLPUBLIC UnoWrapperBase
* CreateUnoWrapper()
120 return new UnoWrapper( nullptr );
126 UnoWrapper::UnoWrapper( const css::uno::Reference
< css::awt::XToolkit
>& rxToolkit
)
128 mxToolkit
= rxToolkit
;
131 void UnoWrapper::Destroy()
136 UnoWrapper::~UnoWrapper()
140 css::uno::Reference
< css::awt::XToolkit
> UnoWrapper::GetVCLToolkit()
142 if ( !mxToolkit
.is() )
143 mxToolkit
= VCLUnoHelper::CreateToolkit();
147 css::uno::Reference
< css::awt::XVclWindowPeer
> UnoWrapper::GetWindowInterface( vcl::Window
* pWindow
)
149 css::uno::Reference
< css::awt::XVclWindowPeer
> xPeer
= pWindow
->GetWindowPeer();
153 rtl::Reference
<VCLXWindow
> xVCLXWindow
= CreateXWindow( pWindow
);
154 xVCLXWindow
->SetWindow( pWindow
);
155 pWindow
->SetWindowPeer( xVCLXWindow
, xVCLXWindow
.get() );
159 VclPtr
<vcl::Window
> UnoWrapper::GetWindow(const css::uno::Reference
<css::awt::XWindow
>& rWindow
)
161 return VCLUnoHelper::GetWindow(rWindow
);
164 void UnoWrapper::SetWindowInterface( vcl::Window
* pWindow
, const css::uno::Reference
< css::awt::XVclWindowPeer
> & xIFace
)
166 VCLXWindow
* pVCLXWindow
= dynamic_cast<VCLXWindow
*>( xIFace
.get() );
168 assert( pVCLXWindow
&& "must be a VCLXWindow subclass" );
174 // we are disconnecting a peer from a window
175 pVCLXWindow
->SetWindow( nullptr );
179 css::uno::Reference
< css::awt::XVclWindowPeer
> xPeer
= pWindow
->GetWindowPeer();
182 bool bSameInstance( pVCLXWindow
== dynamic_cast< VCLXWindow
* >( xPeer
.get() ));
183 SAL_WARN_IF( !bSameInstance
, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" );
187 pVCLXWindow
->SetWindow( pWindow
);
188 pWindow
->SetWindowPeer( xIFace
, pVCLXWindow
);
192 css::uno::Reference
<css::awt::XPopupMenu
> UnoWrapper::CreateMenuInterface( PopupMenu
* pPopupMenu
)
194 return new VCLXPopupMenu(pPopupMenu
);
197 css::uno::Reference
< css::awt::XGraphics
> UnoWrapper::CreateGraphics( OutputDevice
* pOutDev
)
199 rtl::Reference
<VCLXGraphics
> pGrf
= new VCLXGraphics
;
200 pGrf
->Init( pOutDev
);
204 void UnoWrapper::ReleaseAllGraphics( OutputDevice
* pOutDev
)
206 std::vector
< VCLXGraphics
* > *pLst
= pOutDev
->GetUnoGraphicsList();
209 for (VCLXGraphics
* pGrf
: *pLst
)
211 pGrf
->SetOutputDevice( nullptr );
217 static bool lcl_ImplIsParent( vcl::Window
const * pParentWindow
, vcl::Window
* pPossibleChild
)
219 vcl::Window
* pWindow
= ( pPossibleChild
!= pParentWindow
) ? pPossibleChild
: nullptr;
220 while ( pWindow
&& ( pWindow
!= pParentWindow
) )
221 pWindow
= pWindow
->GetParent();
223 return pWindow
!= nullptr;
226 void UnoWrapper::WindowDestroyed( vcl::Window
* pWindow
)
228 // their still might be some children created with css::loader::Java
229 // that would otherwise not be destroyed until the garbage collector cleans up
230 VclPtr
< vcl::Window
> pChild
= pWindow
->GetWindow( GetWindowType::FirstChild
);
233 VclPtr
< vcl::Window
> pNextChild
= pChild
->GetWindow( GetWindowType::Next
);
235 VclPtr
< vcl::Window
> pClient
= pChild
->GetWindow( GetWindowType::Client
);
236 if ( pClient
&& pClient
->GetWindowPeer() )
238 css::uno::Reference
< css::lang::XComponent
> xComp
= pClient
->GetComponentInterface( false );
243 // We need it to dispose the child windows properly (even without window peer),
244 // otherwise the vcl::Window will be leaked.
245 pClient
.disposeAndClear();
251 // find system windows...
252 VclPtr
< vcl::Window
> pOverlap
= pWindow
->GetWindow( GetWindowType::Overlap
);
255 pOverlap
= pOverlap
->GetWindow( GetWindowType::FirstOverlap
);
258 VclPtr
< vcl::Window
> pNextOverlap
= pOverlap
->GetWindow( GetWindowType::Next
);
259 VclPtr
< vcl::Window
> pClient
= pOverlap
->GetWindow( GetWindowType::Client
);
261 if ( pClient
&& pClient
->GetWindowPeer() && lcl_ImplIsParent( pWindow
, pClient
) )
263 css::uno::Reference
< css::lang::XComponent
> xComp
= pClient
->GetComponentInterface( false );
267 pOverlap
= pNextOverlap
;
272 VclPtr
< vcl::Window
> pParent
= pWindow
->GetParent();
273 if ( pParent
&& pParent
->GetWindowPeer() )
274 pParent
->GetWindowPeer()->notifyWindowRemoved( *pWindow
);
277 VCLXWindow
* pWindowPeer
= pWindow
->GetWindowPeer();
278 uno::Reference
< lang::XComponent
> xWindowPeerComp
= pWindow
->GetComponentInterface( false );
279 OSL_ENSURE( ( pWindowPeer
!= nullptr ) == xWindowPeerComp
.is(),
280 "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" );
283 pWindowPeer
->SetWindow( nullptr );
284 pWindow
->SetWindowPeer( nullptr, nullptr );
286 if ( xWindowPeerComp
.is() )
287 xWindowPeerComp
->dispose();
289 // #102132# Iterate over frames after setting Window peer to NULL,
290 // because while destroying other frames, we get into the method again and try
291 // to destroy this window again...
292 // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children
293 // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme
294 // performance penalties)
295 VclPtr
< vcl::Window
> pTopWindowChild
= pWindow
->GetWindow( GetWindowType::FirstTopWindowChild
);
296 while ( pTopWindowChild
)
298 OSL_ENSURE( pTopWindowChild
->GetParent() == pWindow
,
299 "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" );
301 VclPtr
< vcl::Window
> pNextTopChild
= pTopWindowChild
->GetWindow( GetWindowType::NextTopWindowSibling
);
303 pTopWindowChild
.disposeAndClear();
304 pTopWindowChild
= pNextTopChild
;
309 css::uno::Reference
< css::accessibility::XAccessible
> UnoWrapper::CreateAccessible( Menu
* pMenu
, bool bIsMenuBar
)
311 return maAccessibleFactoryAccess
.getFactory().createAccessible( pMenu
, bIsMenuBar
);
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */