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