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::BORDERWINDOW
:
96 if (pWindow
->IsNativeFrame())
97 return new VCLXTopWindow
;
98 return new VCLXWindow(true);
101 // case WindowType::FIXEDLINE:
102 // case WindowType::FIXEDBITMAP:
103 // case WindowType::DATEBOX:
104 // case WindowType::GROUPBOX:
105 // case WindowType::LONGCURRENCYBOX:
106 // case WindowType::SPLITTER:
107 // case WindowType::STATUSBAR:
108 // case WindowType::TABCONTROL:
109 // case WindowType::NUMERICBOX:
110 // case WindowType::TRISTATEBOX:
111 // case WindowType::TIMEBOX:
112 // case WindowType::SPLITWINDOW:
113 // case WindowType::SCROLLBARBOX:
114 // case WindowType::PATTERNBOX:
115 // case WindowType::CURRENCYBOX:
116 default: return new VCLXWindow( true );
125 TOOLKIT_DLLPUBLIC UnoWrapperBase
* CreateUnoWrapper()
127 return new UnoWrapper( nullptr );
133 UnoWrapper::UnoWrapper( const css::uno::Reference
< css::awt::XToolkit
>& rxToolkit
)
135 mxToolkit
= rxToolkit
;
138 void UnoWrapper::Destroy()
143 UnoWrapper::~UnoWrapper()
147 css::uno::Reference
< css::awt::XToolkit
> UnoWrapper::GetVCLToolkit()
149 if ( !mxToolkit
.is() )
150 mxToolkit
= VCLUnoHelper::CreateToolkit();
154 css::uno::Reference
< css::awt::XVclWindowPeer
> UnoWrapper::GetWindowInterface( vcl::Window
* pWindow
)
156 css::uno::Reference
< css::awt::XVclWindowPeer
> xPeer
= pWindow
->GetWindowPeer();
160 rtl::Reference
<VCLXWindow
> xVCLXWindow
= CreateXWindow( pWindow
);
161 xVCLXWindow
->SetWindow( pWindow
);
162 pWindow
->SetWindowPeer( xVCLXWindow
, xVCLXWindow
.get() );
166 VclPtr
<vcl::Window
> UnoWrapper::GetWindow(const css::uno::Reference
<css::awt::XWindow
>& rWindow
)
168 return VCLUnoHelper::GetWindow(rWindow
);
171 void UnoWrapper::SetWindowInterface( vcl::Window
* pWindow
, const css::uno::Reference
< css::awt::XVclWindowPeer
> & xIFace
)
173 VCLXWindow
* pVCLXWindow
= dynamic_cast<VCLXWindow
*>( xIFace
.get() );
175 assert( pVCLXWindow
&& "must be a VCLXWindow subclass" );
181 // we are disconnecting a peer from a window
182 pVCLXWindow
->SetWindow( nullptr );
186 css::uno::Reference
< css::awt::XVclWindowPeer
> xPeer
= pWindow
->GetWindowPeer();
189 bool bSameInstance( pVCLXWindow
== dynamic_cast< VCLXWindow
* >( xPeer
.get() ));
190 SAL_WARN_IF( !bSameInstance
, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" );
194 pVCLXWindow
->SetWindow( pWindow
);
195 pWindow
->SetWindowPeer( xIFace
, pVCLXWindow
);
199 css::uno::Reference
<css::awt::XPopupMenu
> UnoWrapper::CreateMenuInterface( PopupMenu
* pPopupMenu
)
201 return new VCLXPopupMenu(pPopupMenu
);
204 css::uno::Reference
< css::awt::XGraphics
> UnoWrapper::CreateGraphics( OutputDevice
* pOutDev
)
206 rtl::Reference
<VCLXGraphics
> pGrf
= new VCLXGraphics
;
207 pGrf
->Init( pOutDev
);
211 void UnoWrapper::ReleaseAllGraphics( OutputDevice
* pOutDev
)
213 std::vector
< VCLXGraphics
* > *pLst
= pOutDev
->GetUnoGraphicsList();
216 for (VCLXGraphics
* pGrf
: *pLst
)
218 pGrf
->SetOutputDevice( nullptr );
224 static bool lcl_ImplIsParent( vcl::Window
const * pParentWindow
, vcl::Window
* pPossibleChild
)
226 vcl::Window
* pWindow
= ( pPossibleChild
!= pParentWindow
) ? pPossibleChild
: nullptr;
227 while ( pWindow
&& ( pWindow
!= pParentWindow
) )
228 pWindow
= pWindow
->GetParent();
230 return pWindow
!= nullptr;
233 void UnoWrapper::WindowDestroyed( vcl::Window
* pWindow
)
235 // their still might be some children created with css::loader::Java
236 // that would otherwise not be destroyed until the garbage collector cleans up
237 VclPtr
< vcl::Window
> pChild
= pWindow
->GetWindow( GetWindowType::FirstChild
);
240 VclPtr
< vcl::Window
> pNextChild
= pChild
->GetWindow( GetWindowType::Next
);
242 VclPtr
< vcl::Window
> pClient
= pChild
->GetWindow( GetWindowType::Client
);
243 if ( pClient
&& pClient
->GetWindowPeer() )
245 css::uno::Reference
< css::lang::XComponent
> xComp
= pClient
->GetComponentInterface( false );
250 // We need it to dispose the child windows properly (even without window peer),
251 // otherwise the vcl::Window will be leaked.
252 pClient
.disposeAndClear();
258 // find system windows...
259 VclPtr
< vcl::Window
> pOverlap
= pWindow
->GetWindow( GetWindowType::Overlap
);
262 pOverlap
= pOverlap
->GetWindow( GetWindowType::FirstOverlap
);
265 VclPtr
< vcl::Window
> pNextOverlap
= pOverlap
->GetWindow( GetWindowType::Next
);
266 VclPtr
< vcl::Window
> pClient
= pOverlap
->GetWindow( GetWindowType::Client
);
268 if ( pClient
&& pClient
->GetWindowPeer() && lcl_ImplIsParent( pWindow
, pClient
) )
270 css::uno::Reference
< css::lang::XComponent
> xComp
= pClient
->GetComponentInterface( false );
274 pOverlap
= pNextOverlap
;
279 VclPtr
< vcl::Window
> pParent
= pWindow
->GetParent();
280 if ( pParent
&& pParent
->GetWindowPeer() )
281 pParent
->GetWindowPeer()->notifyWindowRemoved( *pWindow
);
284 VCLXWindow
* pWindowPeer
= pWindow
->GetWindowPeer();
285 uno::Reference
< lang::XComponent
> xWindowPeerComp
= pWindow
->GetComponentInterface( false );
286 OSL_ENSURE( ( pWindowPeer
!= nullptr ) == xWindowPeerComp
.is(),
287 "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" );
290 pWindowPeer
->SetWindow( nullptr );
291 pWindow
->SetWindowPeer( nullptr, nullptr );
293 if ( xWindowPeerComp
.is() )
294 xWindowPeerComp
->dispose();
296 // #102132# Iterate over frames after setting Window peer to NULL,
297 // because while destroying other frames, we get into the method again and try
298 // to destroy this window again...
299 // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children
300 // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme
301 // performance penalties)
302 VclPtr
< vcl::Window
> pTopWindowChild
= pWindow
->GetWindow( GetWindowType::FirstTopWindowChild
);
303 while ( pTopWindowChild
)
305 OSL_ENSURE( pTopWindowChild
->GetParent() == pWindow
,
306 "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" );
308 VclPtr
< vcl::Window
> pNextTopChild
= pTopWindowChild
->GetWindow( GetWindowType::NextTopWindowSibling
);
310 pTopWindowChild
.disposeAndClear();
311 pTopWindowChild
= pNextTopChild
;
316 css::uno::Reference
< css::accessibility::XAccessible
> UnoWrapper::CreateAccessible( Menu
* pMenu
, bool bIsMenuBar
)
318 return maAccessibleFactoryAccess
.getFactory().createAccessible( pMenu
, bIsMenuBar
);
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */