1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_toolkit.hxx" 26 #include <com/sun/star/awt/WindowEvent.hpp> 27 #include <comphelper/processfactory.hxx> 28 29 #include <toolkit/helper/unowrapper.hxx> 30 #include <toolkit/helper/vclunohelper.hxx> 31 #include <toolkit/helper/convert.hxx> 32 #include <toolkit/awt/vclxwindow.hxx> 33 #include <toolkit/awt/vclxwindows.hxx> 34 #include <toolkit/awt/vclxcontainer.hxx> 35 #include <toolkit/awt/vclxtopwindow.hxx> 36 #include <toolkit/awt/vclxgraphics.hxx> 37 38 #include "toolkit/dllapi.h" 39 #include <vcl/svapp.hxx> 40 #include <vcl/syswin.hxx> 41 #include <vcl/menu.hxx> 42 43 #include <tools/debug.hxx> 44 45 using namespace ::com::sun::star; 46 47 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > CreateXWindow( Window* pWindow ) 48 { 49 switch ( pWindow->GetType() ) 50 { 51 case WINDOW_IMAGERADIOBUTTON: 52 case WINDOW_IMAGEBUTTON: 53 case WINDOW_SPINBUTTON: 54 case WINDOW_MENUBUTTON: 55 case WINDOW_MOREBUTTON: 56 case WINDOW_PUSHBUTTON: 57 case WINDOW_HELPBUTTON: 58 case WINDOW_OKBUTTON: 59 case WINDOW_CANCELBUTTON: return new VCLXButton; 60 case WINDOW_CHECKBOX: return new VCLXCheckBox; 61 // --> OD 2009-06-29 #i95042# 62 // A Window of type <MetricBox> is inherited from type <ComboBox>. 63 // Thus, it does make more sense to return a <VCLXComboBox> instance 64 // instead of only a <VCLXWindow> instance, especially regarding its 65 // corresponding accessibility API. 66 case WINDOW_METRICBOX: 67 case WINDOW_COMBOBOX: return new VCLXComboBox; 68 case WINDOW_SPINFIELD: 69 case WINDOW_NUMERICFIELD: 70 case WINDOW_CURRENCYFIELD: return new VCLXNumericField; 71 case WINDOW_DATEFIELD: return new VCLXDateField; 72 case WINDOW_MULTILINEEDIT: 73 case WINDOW_EDIT: return new VCLXEdit; 74 case WINDOW_METRICFIELD: return new VCLXSpinField; 75 case WINDOW_MESSBOX: 76 case WINDOW_INFOBOX: 77 case WINDOW_WARNINGBOX: 78 case WINDOW_QUERYBOX: 79 case WINDOW_ERRORBOX: return new VCLXMessageBox; 80 case WINDOW_FIXEDIMAGE: return new VCLXImageControl; 81 case WINDOW_FIXEDTEXT: return new VCLXFixedText; 82 case WINDOW_MULTILISTBOX: 83 case WINDOW_LISTBOX: return new VCLXListBox; 84 case WINDOW_LONGCURRENCYFIELD: return new VCLXCurrencyField; 85 case WINDOW_DIALOG: 86 case WINDOW_MODALDIALOG: 87 case WINDOW_TABDIALOG: 88 case WINDOW_BUTTONDIALOG: 89 case WINDOW_MODELESSDIALOG: return new VCLXDialog; 90 case WINDOW_PATTERNFIELD: return new VCLXPatternField; 91 case WINDOW_RADIOBUTTON: return new VCLXRadioButton; 92 case WINDOW_SCROLLBAR: return new VCLXScrollBar; 93 case WINDOW_TIMEFIELD: return new VCLXTimeField; 94 95 case WINDOW_SYSWINDOW: 96 case WINDOW_WORKWINDOW: 97 case WINDOW_DOCKINGWINDOW: 98 case WINDOW_FLOATINGWINDOW: 99 case WINDOW_HELPTEXTWINDOW: return new VCLXTopWindow; 100 101 case WINDOW_WINDOW: 102 case WINDOW_TABPAGE: return new VCLXContainer; 103 104 case WINDOW_TOOLBOX: return new VCLXToolBox; 105 106 // case WINDOW_FIXEDLINE: 107 // case WINDOW_FIXEDBITMAP: 108 // case WINDOW_DATEBOX: 109 // case WINDOW_GROUPBOX: 110 // case WINDOW_LONGCURRENCYBOX: 111 // case WINDOW_SPLITTER: 112 // case WINDOW_STATUSBAR: 113 // case WINDOW_TABCONTROL: 114 // case WINDOW_NUMERICBOX: 115 // case WINDOW_TRISTATEBOX: 116 // case WINDOW_TIMEBOX: 117 // case WINDOW_SPLITWINDOW: 118 // case WINDOW_SCROLLBARBOX: 119 // case WINDOW_PATTERNBOX: 120 // case WINDOW_CURRENCYBOX: 121 default: return new VCLXWindow( true ); 122 } 123 } 124 125 // ---------------------------------------------------- 126 // class UnoWrapper 127 // ---------------------------------------------------- 128 129 extern "C" { 130 131 TOOLKIT_DLLPUBLIC UnoWrapperBase* CreateUnoWrapper() 132 { 133 return new UnoWrapper( NULL ); 134 } 135 136 } // extern "C" 137 138 139 UnoWrapper::UnoWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit>& rxToolkit ) 140 { 141 mxToolkit = rxToolkit; 142 } 143 144 void UnoWrapper::Destroy() 145 { 146 delete this; 147 } 148 149 UnoWrapper::~UnoWrapper() 150 { 151 } 152 153 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit> UnoWrapper::GetVCLToolkit() 154 { 155 if ( !mxToolkit.is() ) 156 mxToolkit = VCLUnoHelper::CreateToolkit(); 157 return mxToolkit.get(); 158 } 159 160 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer> UnoWrapper::GetWindowInterface( Window* pWindow, sal_Bool bCreate ) 161 { 162 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer> xPeer = pWindow->GetWindowPeer(); 163 if ( !xPeer.is() && bCreate ) 164 { 165 xPeer = CreateXWindow( pWindow ); 166 SetWindowInterface( pWindow, xPeer ); 167 } 168 return xPeer; 169 } 170 171 void UnoWrapper::SetWindowInterface( Window* pWindow, ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer> xIFace ) 172 { 173 VCLXWindow* pVCLXWindow = VCLXWindow::GetImplementation( xIFace ); 174 175 DBG_ASSERT( pVCLXWindow, "SetComponentInterface - unsupported type" ); 176 if ( pVCLXWindow ) 177 { 178 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer> xPeer = pWindow->GetWindowPeer(); 179 if( xPeer.is() ) 180 { 181 bool bSameInstance( pVCLXWindow == dynamic_cast< VCLXWindow* >( xPeer.get() )); 182 DBG_ASSERT( bSameInstance, "UnoWrapper::SetWindowInterface: there already *is* a WindowInterface for this window!" ); 183 if ( bSameInstance ) 184 return; 185 } 186 pVCLXWindow->SetWindow( pWindow ); 187 pWindow->SetWindowPeer( xIFace, pVCLXWindow ); 188 } 189 } 190 191 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics> UnoWrapper::CreateGraphics( OutputDevice* pOutDev ) 192 { 193 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics> xGrf; 194 VCLXGraphics* pGrf = new VCLXGraphics; 195 xGrf = pGrf; 196 pGrf->Init( pOutDev ); 197 return xGrf; 198 } 199 200 void UnoWrapper::ReleaseAllGraphics( OutputDevice* pOutDev ) 201 { 202 List* pLst = pOutDev->GetUnoGraphicsList(); 203 if ( pLst ) 204 { 205 for ( sal_uInt32 n = 0; n < pLst->Count(); n++ ) 206 { 207 VCLXGraphics* pGrf = (VCLXGraphics*)pLst->GetObject( n ); 208 pGrf->SetOutputDevice( NULL ); 209 } 210 } 211 212 } 213 214 // MT: Wurde im Window-CTOR gerufen, damit Container-Listener 215 // vom Parent reagieren, aber hat sowieso nicht richtig funktioniert, 216 // weil im Window-CTOR das Interface noch nicht da ist! 217 // => Nur Listener rufen, wenn ueber das ::com::sun::star::awt::Toolkit erzeugt 218 219 /* 220 void ImplSmartWindowCreated( Window* pNewWindow ) 221 { 222 UNOWindowData* pParentUNOData = pNewWindow->GetParent() ? 223 pNewWindow->GetParent()->GetUNOData() : NULL; 224 225 if ( pParentUNOData && pParentUNOData->GetListeners( EL_CONTAINER ) ) 226 { 227 UNOWindowData* pUNOData = pNewWindow->GetUNOData(); 228 if ( !pUNOData ) 229 pUNOData = ImplSmartCreateUNOData( pNewWindow ); 230 231 ::com::sun::star::awt::VclContainerEvent aEvent; 232 aEvent.Source = (UsrObject*)pParentUNOData->GetWindowPeer(); 233 aEvent.Id = VCLCOMPONENT_ADDED; 234 aEvent.Child = (UsrObject*)pUNOData->GetWindowPeer(); 235 236 EventList* pLst = pParentUNOData->GetListeners( EL_CONTAINER ); 237 for ( sal_uInt32 n = 0; n < pLst->Count(); n++ ) 238 { 239 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > * pRef = pLst->GetObject( n ); 240 ((::com::sun::star::awt::XVclContainerListener*)(::com::sun::star::lang::XEventListener*)*pRef)->windowAdded( aEvent ); 241 } 242 } 243 } 244 */ 245 246 sal_Bool lcl_ImplIsParent( Window* pParentWindow, Window* pPossibleChild ) 247 { 248 Window* pWindow = ( pPossibleChild != pParentWindow ) ? pPossibleChild : NULL; 249 while ( pWindow && ( pWindow != pParentWindow ) ) 250 pWindow = pWindow->GetParent(); 251 252 return pWindow ? sal_True : sal_False; 253 } 254 255 void UnoWrapper::WindowDestroyed( Window* pWindow ) 256 { 257 // ggf. existieren noch von ::com::sun::star::loader::Java erzeugte Childs, die sonst erst 258 // im Garbage-Collector zerstoert werden... 259 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD ); 260 while ( pChild ) 261 { 262 Window* pNextChild = pChild->GetWindow( WINDOW_NEXT ); 263 264 Window* pClient = pChild->GetWindow( WINDOW_CLIENT ); 265 if ( pClient->GetWindowPeer() ) 266 { 267 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xComp( pClient->GetComponentInterface( sal_False ), ::com::sun::star::uno::UNO_QUERY ); 268 xComp->dispose(); 269 } 270 271 pChild = pNextChild; 272 } 273 274 // ::com::sun::star::chaos::System-Windows suchen... 275 Window* pOverlap = pWindow->GetWindow( WINDOW_OVERLAP ); 276 pOverlap = pOverlap->GetWindow( WINDOW_FIRSTOVERLAP ); 277 while ( pOverlap ) 278 { 279 Window* pNextOverlap = pOverlap->GetWindow( WINDOW_NEXT ); 280 Window* pClient = pOverlap->GetWindow( WINDOW_CLIENT ); 281 282 if ( pClient->GetWindowPeer() && lcl_ImplIsParent( pWindow, pClient ) ) 283 { 284 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xComp( pClient->GetComponentInterface( sal_False ), ::com::sun::star::uno::UNO_QUERY ); 285 xComp->dispose(); 286 } 287 288 pOverlap = pNextOverlap; 289 } 290 291 Window* pParent = pWindow->GetParent(); 292 if ( pParent && pParent->GetWindowPeer() ) 293 pParent->GetWindowPeer()->notifyWindowRemoved( *pWindow ); 294 295 VCLXWindow* pWindowPeer = pWindow->GetWindowPeer(); 296 uno::Reference< lang::XComponent > xWindowPeerComp( pWindow->GetComponentInterface( sal_False ), uno::UNO_QUERY ); 297 OSL_ENSURE( ( pWindowPeer != NULL ) == ( xWindowPeerComp.is() == sal_True ), 298 "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" ); 299 if ( pWindowPeer ) 300 { 301 pWindowPeer->SetWindow( NULL ); 302 pWindow->SetWindowPeer( NULL, NULL ); 303 } 304 if ( xWindowPeerComp.is() ) 305 xWindowPeerComp->dispose(); 306 307 // #102132# Iterate over frames after setting Window peer to NULL, 308 // because while destroying other frames, we get get into the method again and try 309 // to destroy this window again... 310 // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children 311 // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme 312 // performance penalties) 313 if ( pWindow ) 314 { 315 Window* pTopWindowChild = pWindow->GetWindow( WINDOW_FIRSTTOPWINDOWCHILD ); 316 while ( pTopWindowChild ) 317 { 318 OSL_ENSURE( pTopWindowChild->GetParent() == pWindow, 319 "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" ); 320 321 Window* pNextTopChild = pTopWindowChild->GetWindow( WINDOW_NEXTTOPWINDOWSIBLING ); 322 323 //the window still could be on the stack, so we have to 324 // use lazy delete ( it will automatically 325 // disconnect from the currently destroyed parent window ) 326 pTopWindowChild->doLazyDelete(); 327 328 pTopWindowChild = pNextTopChild; 329 } 330 } 331 } 332 333 // ---------------------------------------------------------------------------- 334 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > UnoWrapper::CreateAccessible( Menu* pMenu, sal_Bool bIsMenuBar ) 335 { 336 return maAccessibleFactoryAccess.getFactory().createAccessible( pMenu, bIsMenuBar ); 337 } 338