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 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 //*****************************************************************************************************************
frameAction(const css::frame::FrameActionEvent & aEvent)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 //*****************************************************************************************************************
disposing(const css::lang::EventObject &)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 //*****************************************************************************************************************
implst_identifyModule(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const css::uno::Reference<css::frame::XFrame> & xFrame)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 //*****************************************************************************************************************
implst_getWindowStateFromConfig(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sModuleName)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 //*****************************************************************************************************************
implst_setWindowStateOnConfig(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sModuleName,const::rtl::OUString & sWindowState)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 //*****************************************************************************************************************
implst_getWindowStateFromWindow(const css::uno::Reference<css::awt::XWindow> & xWindow)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 necessary 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 //*********************************************************************************************************
implst_setWindowStateOnWindow(const css::uno::Reference<css::awt::XWindow> & xWindow,const::rtl::OUString & sWindowState)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 necessary 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