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/helper/vclunohelper.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 { 102 // check arguments 103 css::uno::Reference< css::frame::XFrame > xFrame; 104 if (lArguments.getLength() < 1) 105 throw css::lang::IllegalArgumentException( 106 DECLARE_ASCII("Empty argument list!"), 107 static_cast< ::cppu::OWeakObject* >(this), 108 1); 109 110 lArguments[0] >>= xFrame; 111 if (!xFrame.is()) 112 throw css::lang::IllegalArgumentException( 113 DECLARE_ASCII("No valid frame specified!"), 114 static_cast< ::cppu::OWeakObject* >(this), 115 1); 116 117 // SAFE -> ---------------------------------- 118 WriteGuard aWriteLock(m_aLock); 119 // hold the frame as weak reference(!) so it can die everytimes :-) 120 m_xFrame = xFrame; 121 aWriteLock.unlock(); 122 // <- SAFE ---------------------------------- 123 124 // start listening 125 xFrame->addFrameActionListener(this); 126 } 127 128 //***************************************************************************************************************** 129 void SAL_CALL PersistentWindowState::frameAction(const css::frame::FrameActionEvent& aEvent) 130 { 131 // SAFE -> ---------------------------------- 132 ReadGuard aReadLock(m_aLock); 133 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ; 134 css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY); 135 sal_Bool bRestoreWindowState = !m_bWindowStateAlreadySet; 136 aReadLock.unlock(); 137 // <- SAFE ---------------------------------- 138 139 // frame already gone ? We hold it weak only ... 140 if (!xFrame.is()) 141 return; 142 143 // no window -> no position and size available 144 css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow(); 145 if (!xWindow.is()) 146 return; 147 148 // unknown module -> no configuration available! 149 ::rtl::OUString sModuleName = PersistentWindowState::implst_identifyModule(xSMGR, xFrame); 150 if (!sModuleName.getLength()) 151 return; 152 153 switch(aEvent.Action) 154 { 155 case css::frame::FrameAction_COMPONENT_ATTACHED : 156 { 157 if (bRestoreWindowState) 158 { 159 ::rtl::OUString sWindowState = PersistentWindowState::implst_getWindowStateFromConfig(xSMGR, sModuleName); 160 PersistentWindowState::implst_setWindowStateOnWindow(xWindow,sWindowState); 161 // SAFE -> ---------------------------------- 162 WriteGuard aWriteLock(m_aLock); 163 m_bWindowStateAlreadySet = sal_True; 164 aWriteLock.unlock(); 165 // <- SAFE ---------------------------------- 166 } 167 } 168 break; 169 170 case css::frame::FrameAction_COMPONENT_REATTACHED : 171 { 172 // nothing todo here, because its not allowed to change position and size 173 // of an already existing frame! 174 } 175 break; 176 177 case css::frame::FrameAction_COMPONENT_DETACHING : 178 { 179 ::rtl::OUString sWindowState = PersistentWindowState::implst_getWindowStateFromWindow(xWindow); 180 PersistentWindowState::implst_setWindowStateOnConfig(xSMGR, sModuleName, sWindowState); 181 } 182 break; 183 default: 184 break; 185 } 186 } 187 188 //***************************************************************************************************************** 189 void SAL_CALL PersistentWindowState::disposing(const css::lang::EventObject&) 190 { 191 // nothing todo here - because we hold the frame as weak reference only 192 } 193 194 //***************************************************************************************************************** 195 ::rtl::OUString PersistentWindowState::implst_identifyModule(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 196 const css::uno::Reference< css::frame::XFrame >& xFrame) 197 { 198 ::rtl::OUString sModuleName; 199 200 css::uno::Reference< css::frame::XModuleManager > xModuleManager( 201 xSMGR->createInstance(SERVICENAME_MODULEMANAGER), 202 css::uno::UNO_QUERY_THROW); 203 204 try 205 { 206 sModuleName = xModuleManager->identify(xFrame); 207 } 208 catch(const css::uno::RuntimeException& exRun) 209 { throw exRun; } 210 catch(const css::uno::Exception&) 211 { sModuleName = ::rtl::OUString(); } 212 213 return sModuleName; 214 } 215 216 //***************************************************************************************************************** 217 ::rtl::OUString PersistentWindowState::implst_getWindowStateFromConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 218 const ::rtl::OUString& sModuleName) 219 { 220 ::rtl::OUString sWindowState; 221 222 ::rtl::OUStringBuffer sRelPathBuf(256); 223 sRelPathBuf.appendAscii("Office/Factories/*[\""); 224 sRelPathBuf.append (sModuleName ); 225 sRelPathBuf.appendAscii("\"]" ); 226 227 ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup/"); 228 ::rtl::OUString sRelPath = sRelPathBuf.makeStringAndClear(); 229 ::rtl::OUString sKey = ::rtl::OUString::createFromAscii("ooSetupFactoryWindowAttributes"); 230 231 try 232 { 233 ::comphelper::ConfigurationHelper::readDirectKey(xSMGR, 234 sPackage, 235 sRelPath, 236 sKey, 237 ::comphelper::ConfigurationHelper::E_READONLY) >>= sWindowState; 238 } 239 catch(const css::uno::RuntimeException& exRun) 240 { throw exRun; } 241 catch(const css::uno::Exception&) 242 { sWindowState = ::rtl::OUString(); } 243 244 return sWindowState; 245 } 246 247 //***************************************************************************************************************** 248 void PersistentWindowState::implst_setWindowStateOnConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 249 const ::rtl::OUString& sModuleName , 250 const ::rtl::OUString& sWindowState) 251 { 252 ::rtl::OUStringBuffer sRelPathBuf(256); 253 sRelPathBuf.appendAscii("Office/Factories/*[\""); 254 sRelPathBuf.append (sModuleName ); 255 sRelPathBuf.appendAscii("\"]" ); 256 257 ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup/"); 258 ::rtl::OUString sRelPath = sRelPathBuf.makeStringAndClear(); 259 ::rtl::OUString sKey = ::rtl::OUString::createFromAscii("ooSetupFactoryWindowAttributes"); 260 261 try 262 { 263 ::comphelper::ConfigurationHelper::writeDirectKey(xSMGR, 264 sPackage, 265 sRelPath, 266 sKey, 267 css::uno::makeAny(sWindowState), 268 ::comphelper::ConfigurationHelper::E_STANDARD); 269 } 270 catch(const css::uno::RuntimeException& exRun) 271 { throw exRun; } 272 catch(const css::uno::Exception&) 273 {} 274 } 275 276 //***************************************************************************************************************** 277 ::rtl::OUString PersistentWindowState::implst_getWindowStateFromWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) 278 { 279 ::rtl::OUString sWindowState; 280 281 if (xWindow.is()) 282 { 283 // SOLAR SAFE -> ------------------------ 284 ::vos::OClearableGuard aSolarLock(Application::GetSolarMutex()); 285 286 Window* pWindow = VCLUnoHelper::GetWindow(xWindow); 287 // check for system window is necessary to guarantee correct pointer cast! 288 if ( 289 (pWindow ) && 290 (pWindow->IsSystemWindow()) 291 ) 292 { 293 sal_uLong nMask = WINDOWSTATE_MASK_ALL; 294 nMask &= ~(WINDOWSTATE_MASK_MINIMIZED); 295 sWindowState = B2U_ENC( 296 ((SystemWindow*)pWindow)->GetWindowState(nMask), 297 RTL_TEXTENCODING_UTF8); 298 } 299 300 aSolarLock.clear(); 301 // <- SOLAR SAFE ------------------------ 302 } 303 304 return sWindowState; 305 } 306 307 308 //********************************************************************************************************* 309 void PersistentWindowState::implst_setWindowStateOnWindow(const css::uno::Reference< css::awt::XWindow >& xWindow , 310 const ::rtl::OUString& sWindowState) 311 { 312 if ( 313 (!xWindow.is() ) || 314 ( sWindowState.getLength() < 1) 315 ) 316 return; 317 318 // SOLAR SAFE -> ------------------------ 319 ::vos::OClearableGuard aSolarLock(Application::GetSolarMutex()); 320 321 Window* pWindow = VCLUnoHelper::GetWindow(xWindow); 322 if (!pWindow) 323 return; 324 325 // check for system and work window - its necessary to guarantee correct pointer cast! 326 sal_Bool bSystemWindow = pWindow->IsSystemWindow(); 327 sal_Bool bWorkWindow = (pWindow->GetType() == WINDOW_WORKWINDOW); 328 329 if (!bSystemWindow && !bWorkWindow) 330 return; 331 332 SystemWindow* pSystemWindow = (SystemWindow*)pWindow; 333 WorkWindow* pWorkWindow = (WorkWindow* )pWindow; 334 335 // dont save this special state! 336 if (pWorkWindow->IsMinimized()) 337 return; 338 339 ::rtl::OUString sOldWindowState = ::rtl::OStringToOUString( pSystemWindow->GetWindowState(), RTL_TEXTENCODING_ASCII_US ); 340 if ( sOldWindowState != sWindowState ) 341 pSystemWindow->SetWindowState(U2B_ENC(sWindowState,RTL_TEXTENCODING_UTF8)); 342 343 aSolarLock.clear(); 344 // <- SOLAR SAFE ------------------------ 345 } 346 347 } // namespace framework 348