xref: /trunk/main/framework/source/helper/persistentwindowstate.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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