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
DEFINE_XINTERFACE_4(PersistentWindowState,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XInitialization),DIRECT_INTERFACE (css::frame::XFrameActionListener),DERIVED_INTERFACE (css::lang::XEventListener,css::frame::XFrameActionListener))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 //*****************************************************************************************************************
~PersistentWindowState()95 PersistentWindowState::~PersistentWindowState()
96 {
97 }
98
99 //*****************************************************************************************************************
initialize(const css::uno::Sequence<css::uno::Any> & lArguments)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 //*****************************************************************************************************************
frameAction(const css::frame::FrameActionEvent & aEvent)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 //*****************************************************************************************************************
disposing(const css::lang::EventObject &)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 //*****************************************************************************************************************
implst_identifyModule(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const css::uno::Reference<css::frame::XFrame> & xFrame)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 //*****************************************************************************************************************
implst_getWindowStateFromConfig(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sModuleName)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 //*****************************************************************************************************************
implst_setWindowStateOnConfig(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sModuleName,const::rtl::OUString & sWindowState)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 //*****************************************************************************************************************
implst_getWindowStateFromWindow(const css::uno::Reference<css::awt::XWindow> & xWindow)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 //*********************************************************************************************************
implst_setWindowStateOnWindow(const css::uno::Reference<css::awt::XWindow> & xWindow,const::rtl::OUString & sWindowState)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