1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 31 //_________________________________________________________________________________________________________________ 32 // my own includes 33 //_________________________________________________________________________________________________________________ 34 #include <pattern/window.hxx> 35 #include <helper/persistentwindowstate.hxx> 36 #include <threadhelp/writeguard.hxx> 37 #include <threadhelp/readguard.hxx> 38 #include <macros/generic.hxx> 39 #include <services.h> 40 41 //_________________________________________________________________________________________________________________ 42 // interface includes 43 //_________________________________________________________________________________________________________________ 44 #include <com/sun/star/awt/XWindow.hpp> 45 46 #ifndef _COM_SUN_STAR_LANG_XSERVICXEINFO_HPP_ 47 #include <com/sun/star/lang/XServiceInfo.hpp> 48 #endif 49 #include <com/sun/star/lang/IllegalArgumentException.hpp> 50 #include <com/sun/star/frame/XModuleManager.hpp> 51 52 //_________________________________________________________________________________________________________________ 53 // other includes 54 //_________________________________________________________________________________________________________________ 55 #include <comphelper/configurationhelper.hxx> 56 #include <vcl/window.hxx> 57 #include <vcl/syswin.hxx> 58 59 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 60 #include <toolkit/unohlp.hxx> 61 #endif 62 #include <vcl/svapp.hxx> 63 #include <vcl/wrkwin.hxx> 64 #include <rtl/string.hxx> 65 66 //_________________________________________________________________________________________________________________ 67 // namespace 68 69 namespace framework{ 70 71 //_________________________________________________________________________________________________________________ 72 // definitions 73 74 //***************************************************************************************************************** 75 // XInterface, XTypeProvider 76 77 DEFINE_XINTERFACE_4(PersistentWindowState , 78 OWeakObject , 79 DIRECT_INTERFACE (css::lang::XTypeProvider ), 80 DIRECT_INTERFACE (css::lang::XInitialization ), 81 DIRECT_INTERFACE (css::frame::XFrameActionListener ), 82 DERIVED_INTERFACE(css::lang::XEventListener,css::frame::XFrameActionListener)) 83 84 DEFINE_XTYPEPROVIDER_4(PersistentWindowState , 85 css::lang::XTypeProvider , 86 css::lang::XInitialization , 87 css::frame::XFrameActionListener, 88 css::lang::XEventListener ) 89 90 //***************************************************************************************************************** 91 PersistentWindowState::PersistentWindowState(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 92 : ThreadHelpBase (&Application::GetSolarMutex()) 93 , m_xSMGR (xSMGR ) 94 , m_bWindowStateAlreadySet(sal_False ) 95 { 96 } 97 98 //***************************************************************************************************************** 99 PersistentWindowState::~PersistentWindowState() 100 { 101 } 102 103 //***************************************************************************************************************** 104 void SAL_CALL PersistentWindowState::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) 105 throw(css::uno::Exception , 106 css::uno::RuntimeException) 107 { 108 // check arguments 109 css::uno::Reference< css::frame::XFrame > xFrame; 110 if (lArguments.getLength() < 1) 111 throw css::lang::IllegalArgumentException( 112 DECLARE_ASCII("Empty argument list!"), 113 static_cast< ::cppu::OWeakObject* >(this), 114 1); 115 116 lArguments[0] >>= xFrame; 117 if (!xFrame.is()) 118 throw css::lang::IllegalArgumentException( 119 DECLARE_ASCII("No valid frame specified!"), 120 static_cast< ::cppu::OWeakObject* >(this), 121 1); 122 123 // SAFE -> ---------------------------------- 124 WriteGuard aWriteLock(m_aLock); 125 // hold the frame as weak reference(!) so it can die everytimes :-) 126 m_xFrame = xFrame; 127 aWriteLock.unlock(); 128 // <- SAFE ---------------------------------- 129 130 // start listening 131 xFrame->addFrameActionListener(this); 132 } 133 134 //***************************************************************************************************************** 135 void SAL_CALL PersistentWindowState::frameAction(const css::frame::FrameActionEvent& aEvent) 136 throw(css::uno::RuntimeException) 137 { 138 // SAFE -> ---------------------------------- 139 ReadGuard aReadLock(m_aLock); 140 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ; 141 css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY); 142 sal_Bool bRestoreWindowState = !m_bWindowStateAlreadySet; 143 aReadLock.unlock(); 144 // <- SAFE ---------------------------------- 145 146 // frame already gone ? We hold it weak only ... 147 if (!xFrame.is()) 148 return; 149 150 // no window -> no position and size available 151 css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow(); 152 if (!xWindow.is()) 153 return; 154 155 // unknown module -> no configuration available! 156 ::rtl::OUString sModuleName = PersistentWindowState::implst_identifyModule(xSMGR, xFrame); 157 if (!sModuleName.getLength()) 158 return; 159 160 switch(aEvent.Action) 161 { 162 case css::frame::FrameAction_COMPONENT_ATTACHED : 163 { 164 if (bRestoreWindowState) 165 { 166 ::rtl::OUString sWindowState = PersistentWindowState::implst_getWindowStateFromConfig(xSMGR, sModuleName); 167 PersistentWindowState::implst_setWindowStateOnWindow(xWindow,sWindowState); 168 // SAFE -> ---------------------------------- 169 WriteGuard aWriteLock(m_aLock); 170 m_bWindowStateAlreadySet = sal_True; 171 aWriteLock.unlock(); 172 // <- SAFE ---------------------------------- 173 } 174 } 175 break; 176 177 case css::frame::FrameAction_COMPONENT_REATTACHED : 178 { 179 // nothing todo here, because its not allowed to change position and size 180 // of an alredy existing frame! 181 } 182 break; 183 184 case css::frame::FrameAction_COMPONENT_DETACHING : 185 { 186 ::rtl::OUString sWindowState = PersistentWindowState::implst_getWindowStateFromWindow(xWindow); 187 PersistentWindowState::implst_setWindowStateOnConfig(xSMGR, sModuleName, sWindowState); 188 } 189 break; 190 default: 191 break; 192 } 193 } 194 195 //***************************************************************************************************************** 196 void SAL_CALL PersistentWindowState::disposing(const css::lang::EventObject&) 197 throw(css::uno::RuntimeException) 198 { 199 // nothing todo here - because we hold the frame as weak reference only 200 } 201 202 //***************************************************************************************************************** 203 ::rtl::OUString PersistentWindowState::implst_identifyModule(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 204 const css::uno::Reference< css::frame::XFrame >& xFrame) 205 { 206 ::rtl::OUString sModuleName; 207 208 css::uno::Reference< css::frame::XModuleManager > xModuleManager( 209 xSMGR->createInstance(SERVICENAME_MODULEMANAGER), 210 css::uno::UNO_QUERY_THROW); 211 212 try 213 { 214 sModuleName = xModuleManager->identify(xFrame); 215 } 216 catch(const css::uno::RuntimeException& exRun) 217 { throw exRun; } 218 catch(const css::uno::Exception&) 219 { sModuleName = ::rtl::OUString(); } 220 221 return sModuleName; 222 } 223 224 //***************************************************************************************************************** 225 ::rtl::OUString PersistentWindowState::implst_getWindowStateFromConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 226 const ::rtl::OUString& sModuleName) 227 { 228 ::rtl::OUString sWindowState; 229 230 ::rtl::OUStringBuffer sRelPathBuf(256); 231 sRelPathBuf.appendAscii("Office/Factories/*[\""); 232 sRelPathBuf.append (sModuleName ); 233 sRelPathBuf.appendAscii("\"]" ); 234 235 ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup/"); 236 ::rtl::OUString sRelPath = sRelPathBuf.makeStringAndClear(); 237 ::rtl::OUString sKey = ::rtl::OUString::createFromAscii("ooSetupFactoryWindowAttributes"); 238 239 try 240 { 241 ::comphelper::ConfigurationHelper::readDirectKey(xSMGR, 242 sPackage, 243 sRelPath, 244 sKey, 245 ::comphelper::ConfigurationHelper::E_READONLY) >>= sWindowState; 246 } 247 catch(const css::uno::RuntimeException& exRun) 248 { throw exRun; } 249 catch(const css::uno::Exception&) 250 { sWindowState = ::rtl::OUString(); } 251 252 return sWindowState; 253 } 254 255 //***************************************************************************************************************** 256 void PersistentWindowState::implst_setWindowStateOnConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 257 const ::rtl::OUString& sModuleName , 258 const ::rtl::OUString& sWindowState) 259 { 260 ::rtl::OUStringBuffer sRelPathBuf(256); 261 sRelPathBuf.appendAscii("Office/Factories/*[\""); 262 sRelPathBuf.append (sModuleName ); 263 sRelPathBuf.appendAscii("\"]" ); 264 265 ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup/"); 266 ::rtl::OUString sRelPath = sRelPathBuf.makeStringAndClear(); 267 ::rtl::OUString sKey = ::rtl::OUString::createFromAscii("ooSetupFactoryWindowAttributes"); 268 269 try 270 { 271 ::comphelper::ConfigurationHelper::writeDirectKey(xSMGR, 272 sPackage, 273 sRelPath, 274 sKey, 275 css::uno::makeAny(sWindowState), 276 ::comphelper::ConfigurationHelper::E_STANDARD); 277 } 278 catch(const css::uno::RuntimeException& exRun) 279 { throw exRun; } 280 catch(const css::uno::Exception&) 281 {} 282 } 283 284 //***************************************************************************************************************** 285 ::rtl::OUString PersistentWindowState::implst_getWindowStateFromWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) 286 { 287 ::rtl::OUString sWindowState; 288 289 if (xWindow.is()) 290 { 291 // SOLAR SAFE -> ------------------------ 292 ::vos::OClearableGuard aSolarLock(Application::GetSolarMutex()); 293 294 Window* pWindow = VCLUnoHelper::GetWindow(xWindow); 295 // check for system window is neccessary to guarantee correct pointer cast! 296 if ( 297 (pWindow ) && 298 (pWindow->IsSystemWindow()) 299 ) 300 { 301 sal_uLong nMask = WINDOWSTATE_MASK_ALL; 302 nMask &= ~(WINDOWSTATE_MASK_MINIMIZED); 303 sWindowState = B2U_ENC( 304 ((SystemWindow*)pWindow)->GetWindowState(nMask), 305 RTL_TEXTENCODING_UTF8); 306 } 307 308 aSolarLock.clear(); 309 // <- SOLAR SAFE ------------------------ 310 } 311 312 return sWindowState; 313 } 314 315 316 //********************************************************************************************************* 317 void PersistentWindowState::implst_setWindowStateOnWindow(const css::uno::Reference< css::awt::XWindow >& xWindow , 318 const ::rtl::OUString& sWindowState) 319 { 320 if ( 321 (!xWindow.is() ) || 322 ( sWindowState.getLength() < 1) 323 ) 324 return; 325 326 // SOLAR SAFE -> ------------------------ 327 ::vos::OClearableGuard aSolarLock(Application::GetSolarMutex()); 328 329 Window* pWindow = VCLUnoHelper::GetWindow(xWindow); 330 if (!pWindow) 331 return; 332 333 // check for system and work window - its neccessary to guarantee correct pointer cast! 334 sal_Bool bSystemWindow = pWindow->IsSystemWindow(); 335 sal_Bool bWorkWindow = (pWindow->GetType() == WINDOW_WORKWINDOW); 336 337 if (!bSystemWindow && !bWorkWindow) 338 return; 339 340 SystemWindow* pSystemWindow = (SystemWindow*)pWindow; 341 WorkWindow* pWorkWindow = (WorkWindow* )pWindow; 342 343 // dont save this special state! 344 if (pWorkWindow->IsMinimized()) 345 return; 346 347 ::rtl::OUString sOldWindowState = ::rtl::OStringToOUString( pSystemWindow->GetWindowState(), RTL_TEXTENCODING_ASCII_US ); 348 if ( sOldWindowState != sWindowState ) 349 pSystemWindow->SetWindowState(U2B_ENC(sWindowState,RTL_TEXTENCODING_UTF8)); 350 351 aSolarLock.clear(); 352 // <- SOLAR SAFE ------------------------ 353 } 354 355 } // namespace framework 356