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