1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include "acceleratorexecute.hxx"
31 
32 //===============================================
33 // includes
34 
35 #ifndef __COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
36 #include <com/sun/star/frame/XModuleManager.hpp>
37 #endif
38 
39 #ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGER_HPP_
40 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
41 #endif
42 
43 #ifndef __COM_SUN_STAR_UI_XMODULEUICONFIGURATIONMANAGERSUPPLIER_HPP_
44 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
45 #endif
46 
47 #ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGERSUPPLIER_HPP_
48 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
49 #endif
50 
51 #ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
52 #include <com/sun/star/awt/KeyModifier.hpp>
53 #endif
54 
55 #ifndef __COM_SUN_STAR_UNO_SEQUENCE_HXX_
56 #include <com/sun/star/uno/Sequence.hxx>
57 #endif
58 
59 #ifndef __COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
60 #include <com/sun/star/beans/PropertyValue.hpp>
61 #endif
62 
63 //===============================================
64 // namespace
65 
66 namespace svt
67 {
68 
69 namespace css = ::com::sun::star;
70 
71 //===============================================
72 // definitions
73 
74 //-----------------------------------------------
75 AcceleratorExecute::AcceleratorExecute()
76     : TMutexInit      (                                                     )
77     , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
78 {
79 }
80 
81 //-----------------------------------------------
82 AcceleratorExecute::AcceleratorExecute(const AcceleratorExecute& rCopy)
83     : TMutexInit      (                                                     )
84     , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
85 {
86     // copy construction sint supported in real ...
87     // but we need this ctor to init our async callback ...
88 }
89 
90 //-----------------------------------------------
91 AcceleratorExecute::~AcceleratorExecute()
92 {
93     // does nothing real
94 }
95 
96 //-----------------------------------------------
97 AcceleratorExecute* AcceleratorExecute::createAcceleratorHelper()
98 {
99     AcceleratorExecute* pNew = new AcceleratorExecute();
100     return pNew;
101 }
102 
103 //-----------------------------------------------
104 void AcceleratorExecute::init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR,
105                               const css::uno::Reference< css::frame::XFrame >&              xEnv )
106 {
107     // SAFE -> ----------------------------------
108     ::osl::ResettableMutexGuard aLock(m_aLock);
109 
110     // take over the uno service manager
111     m_xSMGR = xSMGR;
112 
113     // specify our internal dispatch provider
114     // frame or desktop?! => document or global config.
115     sal_Bool bDesktopIsUsed = sal_False;
116              m_xDispatcher  = css::uno::Reference< css::frame::XDispatchProvider >(xEnv, css::uno::UNO_QUERY);
117     if (!m_xDispatcher.is())
118     {
119         aLock.clear();
120         // <- SAFE ------------------------------
121 
122         css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(
123                             xSMGR->createInstance(SERVICENAME_DESKTOP),
124                             css::uno::UNO_QUERY_THROW);
125 
126         // SAFE -> ------------------------------
127         aLock.reset();
128 
129         m_xDispatcher  = xDispatcher;
130         bDesktopIsUsed = sal_True;
131     }
132 
133     aLock.clear();
134     // <- SAFE ----------------------------------
135 
136     // open all needed configuration objects
137     css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg;
138     css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg;
139     css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg   ;
140 
141     // global cfg
142     xGlobalCfg = AcceleratorExecute::impl_st_openGlobalConfig(xSMGR);
143     if (!bDesktopIsUsed)
144     {
145         // module cfg
146         xModuleCfg = AcceleratorExecute::impl_st_openModuleConfig(xSMGR, xEnv);
147 
148         // doc cfg
149         css::uno::Reference< css::frame::XController > xController;
150         css::uno::Reference< css::frame::XModel >      xModel;
151         xController = xEnv->getController();
152         if (xController.is())
153             xModel = xController->getModel();
154         if (xModel.is())
155             xDocCfg = AcceleratorExecute::impl_st_openDocConfig(xModel);
156     }
157 
158     // SAFE -> ------------------------------
159     aLock.reset();
160 
161     m_xGlobalCfg = xGlobalCfg;
162     m_xModuleCfg = xModuleCfg;
163     m_xDocCfg    = xDocCfg   ;
164 
165     aLock.clear();
166     // <- SAFE ----------------------------------
167 }
168 
169 //-----------------------------------------------
170 void AcceleratorExecute::execute(const KeyCode& aVCLKey)
171 {
172     css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
173     execute(aAWTKey);
174 }
175 
176 //-----------------------------------------------
177 void AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
178 {
179     ::rtl::OUString sCommand = impl_ts_findCommand(aAWTKey);
180 
181     // No Command found? Do nothing! User isnt interested on any error handling .-)
182     if (!sCommand.getLength())
183         return;
184 
185     // SAFE -> ----------------------------------
186     ::osl::ResettableMutexGuard aLock(m_aLock);
187 
188     m_lCommandQueue.push_back(sCommand);
189     m_aAsyncCallback.Post(0);
190 
191     aLock.clear();
192     // <- SAFE ----------------------------------
193 }
194 
195 //-----------------------------------------------
196 css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const KeyCode& aVCLKey)
197 {
198     css::awt::KeyEvent aAWTKey;
199     aAWTKey.Modifiers = 0;
200     aAWTKey.KeyCode   = (sal_Int16)aVCLKey.GetCode();
201 
202 	if (aVCLKey.IsShift())
203         aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
204 	if (aVCLKey.IsMod1())
205         aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
206 	if (aVCLKey.IsMod2())
207         aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
208         if (aVCLKey.IsMod3())
209         aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
210 
211     return aAWTKey;
212 }
213 
214 /*
215 ViewFrame->GetObjectShell
216 ObjectShell->GetStyleSheetPool
217 */
218 
219 //-----------------------------------------------
220 KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
221 {
222     sal_Bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
223     sal_Bool bMod1  = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1  );
224     sal_Bool bMod2  = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2  );
225     sal_Bool bMod3  = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3  );
226     sal_uInt16   nKey   = (sal_uInt16)aAWTKey.KeyCode;
227 
228     return KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
229 }
230 
231 //-----------------------------------------------
232 ::rtl::OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
233 {
234     // SAFE -> ----------------------------------
235     ::osl::ResettableMutexGuard aLock(m_aLock);
236 
237     css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
238     css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
239     css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg    = m_xDocCfg   ;
240 
241     aLock.clear();
242     // <- SAFE ----------------------------------
243 
244     ::rtl::OUString sCommand;
245     try
246     {
247         if (xDocCfg.is())
248             sCommand = xDocCfg->getCommandByKeyEvent(aKey);
249     }
250     catch(const css::container::NoSuchElementException&)
251     {
252         try
253         {
254             if (xModuleCfg.is())
255                 sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
256         }
257         catch(const css::container::NoSuchElementException&)
258         {
259             try
260             {
261                 if (xGlobalCfg.is())
262                     sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
263             }
264             catch(const css::container::NoSuchElementException&)
265                 {}
266         }
267     }
268 
269     return sCommand;
270 }
271 
272 //-----------------------------------------------
273 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openGlobalConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
274 {
275     css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg(
276         xSMGR->createInstance(SERVICENAME_GLOBALACCELERATORCONFIGURATION),
277         css::uno::UNO_QUERY_THROW);
278     return xAccCfg;
279 }
280 
281 //-----------------------------------------------
282 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openModuleConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
283                                                                                                         const css::uno::Reference< css::frame::XFrame >&              xFrame)
284 {
285     css::uno::Reference< css::frame::XModuleManager > xModuleDetection(
286         xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
287         css::uno::UNO_QUERY_THROW);
288 
289     ::rtl::OUString sModule;
290     try
291     {
292         sModule = xModuleDetection->identify(xFrame);
293     }
294     catch(const css::uno::RuntimeException& exRuntime)
295         { throw exRuntime; }
296     catch(const css::uno::Exception&)
297         { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
298 
299     css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
300         xSMGR->createInstance(SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER),
301         css::uno::UNO_QUERY_THROW);
302 
303     css::uno::Reference< css::ui::XUIConfigurationManager >   xUIManager = xUISupplier->getUIConfigurationManager(sModule);
304     css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg    (xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
305     return xAccCfg;
306 }
307 
308 //-----------------------------------------------
309 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::impl_st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
310 {
311     css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY_THROW);
312     css::uno::Reference< css::ui::XUIConfigurationManager >         xUIManager = xUISupplier->getUIConfigurationManager();
313     css::uno::Reference< css::ui::XAcceleratorConfiguration >       xAccCfg    (xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
314     return xAccCfg;
315 }
316 
317 //-----------------------------------------------
318 css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
319 {
320     // SAFE -> ----------------------------------
321     ::osl::ResettableMutexGuard aLock(m_aLock);
322 
323     if (m_xURLParser.is())
324         return m_xURLParser;
325     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
326 
327     aLock.clear();
328     // <- SAFE ----------------------------------
329 
330     css::uno::Reference< css::util::XURLTransformer > xParser(
331                 xSMGR->createInstance(SERVICENAME_URLTRANSFORMER),
332                 css::uno::UNO_QUERY_THROW);
333 
334     // SAFE -> ----------------------------------
335     aLock.reset();
336     m_xURLParser = xParser;
337     aLock.clear();
338     // <- SAFE ----------------------------------
339 
340     return xParser;
341 }
342 
343 //-----------------------------------------------
344 IMPL_LINK(AcceleratorExecute, impl_ts_asyncCallback, void*, pVoid)
345 {
346     // SAFE -> ----------------------------------
347     ::osl::ResettableMutexGuard aLock(m_aLock);
348 
349     TCommandQueue::iterator pIt = m_lCommandQueue.begin();
350     if (pIt == m_lCommandQueue.end())
351         return 0;
352     ::rtl::OUString sCommand = *pIt;
353     m_lCommandQueue.erase(pIt);
354 
355     css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
356 
357     aLock.clear();
358     // <- SAFE ----------------------------------
359 
360     // convert command in URL structure
361     css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
362     css::util::URL aURL;
363     aURL.Complete = sCommand;
364     xParser->parseStrict(aURL);
365 
366     // ask for dispatch object
367     css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, ::rtl::OUString(), 0);
368     css::uno::Sequence< css::beans::PropertyValue> aArgs;
369     if (xDispatch.is())
370     {
371         if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
372         {
373             Sequence<css::beans::PropertyValue> source;
374             ::comphelper::UiEventsLogger::appendDispatchOrigin(OUString::createFromAscii("AcceleratorExecute"));
375             ::comphelper::UiEventsLogger::logDispatch(aURL, source);
376         }
377         xDispatch->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >());
378     }
379     return 0;
380 }
381 
382 } // namespace svt
383