tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / svtools / source / misc / acceleratorexecute.cxx
blob82918676b649b04ba692759dd1eb992e61ddc2bd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <svtools/acceleratorexecute.hxx>
23 #include <com/sun/star/frame/ModuleManager.hpp>
24 #include <com/sun/star/frame/Desktop.hpp>
25 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
26 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
27 #include <com/sun/star/ui/XUIConfigurationManager2.hpp>
28 #include <com/sun/star/ui/XModuleUIConfigurationManager2.hpp>
29 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
30 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
31 #include <com/sun/star/awt/KeyModifier.hpp>
32 #include <com/sun/star/uno/Sequence.hxx>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/util/URLTransformer.hpp>
35 #include <cppuhelper/implbase.hxx>
37 #include <utility>
38 #include <vcl/evntpost.hxx>
39 #include <sal/log.hxx>
40 #include <vcl/lok.hxx>
41 #include <rtl/ref.hxx>
43 #include <comphelper/lok.hxx>
45 namespace svt
48 namespace {
50 class AsyncAccelExec : public cppu::WeakImplHelper<css::lang::XEventListener>
52 private:
53 css::uno::Reference<css::lang::XComponent> m_xFrame;
54 css::uno::Reference< css::frame::XDispatch > m_xDispatch;
55 css::util::URL m_aURL;
56 vcl::EventPoster m_aAsyncCallback;
57 public:
59 /** creates a new instance of this class, which can be used
60 one times only!
62 This instance can be forced to execute its internal set request
63 asynchronous. After that it deletes itself!
65 static rtl::Reference<AsyncAccelExec> createOneShotInstance(const css::uno::Reference<css::lang::XComponent>& xFrame,
66 const css::uno::Reference<css::frame::XDispatch>& xDispatch,
67 const css::util::URL& rURL);
69 void execAsync();
70 private:
72 virtual void SAL_CALL disposing(const css::lang::EventObject&) override
74 m_xFrame->removeEventListener(this);
75 m_xFrame.clear();
76 m_xDispatch.clear();
79 /** @short allow creation of instances of this class
80 by using our factory only!
82 AsyncAccelExec(css::uno::Reference<css::lang::XComponent> xFrame,
83 css::uno::Reference< css::frame::XDispatch > xDispatch,
84 css::util::URL aURL);
86 DECL_LINK(impl_ts_asyncCallback, LinkParamNone*, void);
91 AcceleratorExecute::AcceleratorExecute()
95 AcceleratorExecute::~AcceleratorExecute()
97 // does nothing real
101 std::unique_ptr<AcceleratorExecute> AcceleratorExecute::createAcceleratorHelper()
103 return std::unique_ptr<AcceleratorExecute>(new AcceleratorExecute);
107 void AcceleratorExecute::init(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
108 const css::uno::Reference< css::frame::XFrame >& xEnv )
110 // SAFE -> ----------------------------------
111 std::unique_lock aLock(m_aLock);
113 // take over the uno service manager
114 m_xContext = rxContext;
116 // specify our internal dispatch provider
117 // frame or desktop?! => document or global config.
118 bool bDesktopIsUsed = false;
119 m_xDispatcher.set(xEnv, css::uno::UNO_QUERY);
120 if (!m_xDispatcher.is())
122 aLock.unlock();
123 // <- SAFE ------------------------------
125 css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(css::frame::Desktop::create(rxContext), css::uno::UNO_QUERY_THROW);
127 // SAFE -> ------------------------------
128 aLock.lock();
130 m_xDispatcher = std::move(xDispatcher);
131 bDesktopIsUsed = true;
134 aLock.unlock();
135 // <- SAFE ----------------------------------
137 // open all needed configuration objects
138 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg;
139 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg;
140 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg ;
142 // global cfg
143 xGlobalCfg = css::ui::GlobalAcceleratorConfiguration::create(rxContext);
144 if (!bDesktopIsUsed)
146 // module cfg
147 xModuleCfg = AcceleratorExecute::st_openModuleConfig(rxContext, xEnv);
149 // doc cfg
150 css::uno::Reference< css::frame::XController > xController;
151 css::uno::Reference< css::frame::XModel > xModel;
152 xController = xEnv->getController();
153 if (xController.is())
154 xModel = xController->getModel();
155 if (xModel.is())
156 xDocCfg = AcceleratorExecute::st_openDocConfig(xModel);
159 // SAFE -> ------------------------------
160 aLock.lock();
162 m_xGlobalCfg = std::move(xGlobalCfg);
163 m_xModuleCfg = std::move(xModuleCfg);
164 m_xDocCfg = std::move(xDocCfg);
166 aLock.unlock();
167 // <- SAFE ----------------------------------
171 bool AcceleratorExecute::execute(const vcl::KeyCode& aVCLKey)
173 css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
174 return execute(aAWTKey);
178 bool AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
180 OUString sCommand = impl_ts_findCommand(aAWTKey);
182 // No Command found? Do nothing! User is not interested on any error handling .-)
183 if (sCommand.isEmpty())
184 return false;
186 // SAFE -> ----------------------------------
187 std::unique_lock aLock(m_aLock);
189 // or for some reason m_xContext is NULL (which would crash impl_ts_getURLParser()
190 if (!m_xContext.is())
191 return false;
193 css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
195 aLock.unlock();
196 // <- SAFE ----------------------------------
198 // convert command in URL structure
199 css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
200 css::util::URL aURL;
201 aURL.Complete = sCommand;
202 xParser->parseStrict(aURL);
204 // ask for dispatch object
205 css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, OUString(), 0);
206 bool bRet = xDispatch.is();
207 if ( bRet )
209 // Note: Such instance can be used one times only and destroy itself afterwards .-)
210 css::uno::Reference<css::lang::XComponent> xFrame(xProvider, css::uno::UNO_QUERY);
211 if (vcl::lok::isUnipoll())
212 { // tdf#130382 - all synchronous really.
213 try {
214 xDispatch->dispatch (aURL, css::uno::Sequence< css::beans::PropertyValue >());
216 catch(const css::uno::Exception&ev)
218 SAL_INFO("svtools", "exception on key emission: " << ev.Message);
221 else
223 rtl::Reference<AsyncAccelExec> pExec = AsyncAccelExec::createOneShotInstance(xFrame, xDispatch, aURL);
224 pExec->execAsync();
228 return bRet;
232 css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const vcl::KeyCode& aVCLKey)
234 css::awt::KeyEvent aAWTKey;
235 aAWTKey.Modifiers = 0;
236 aAWTKey.KeyCode = static_cast<sal_Int16>(aVCLKey.GetCode());
238 if (aVCLKey.IsShift())
239 aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
240 if (aVCLKey.IsMod1())
241 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
242 if (aVCLKey.IsMod2())
243 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
244 if (aVCLKey.IsMod3())
245 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
246 return aAWTKey;
250 vcl::KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
252 bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
253 bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
254 bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
255 bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
256 sal_uInt16 nKey = static_cast<sal_uInt16>(aAWTKey.KeyCode);
258 return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
261 OUString AcceleratorExecute::findCommand(const css::awt::KeyEvent& aKey)
263 return impl_ts_findCommand(aKey);
266 OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
268 // SAFE -> ----------------------------------
269 std::unique_lock aLock(m_aLock);
271 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
272 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
273 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg = m_xDocCfg ;
275 aLock.unlock();
276 // <- SAFE ----------------------------------
278 OUString sCommand;
282 if (xDocCfg.is())
283 sCommand = xDocCfg->getCommandByKeyEvent(aKey);
284 if (!sCommand.isEmpty())
285 return sCommand;
287 catch(const css::container::NoSuchElementException&)
292 if (xModuleCfg.is())
293 sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
294 if (!sCommand.isEmpty())
295 return sCommand;
297 catch(const css::container::NoSuchElementException&)
302 if (xGlobalCfg.is())
303 sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
304 if (!sCommand.isEmpty())
305 return sCommand;
307 catch(const css::container::NoSuchElementException&)
310 // fall back to functional key codes
311 if( aKey.Modifiers == 0 )
313 switch( aKey.KeyCode )
315 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
316 return u".uno:DelToStartOfLine"_ustr;
317 case css::awt::Key::DELETE_TO_END_OF_LINE:
318 return u".uno:DelToEndOfLine"_ustr;
319 case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
320 return u".uno:DelToStartOfPara"_ustr;
321 case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
322 return u".uno:DelToEndOfPara"_ustr;
323 case css::awt::Key::DELETE_WORD_BACKWARD:
324 return u".uno:DelToStartOfWord"_ustr;
325 case css::awt::Key::DELETE_WORD_FORWARD:
326 return u".uno:DelToEndOfWord"_ustr;
327 case css::awt::Key::INSERT_LINEBREAK:
328 return u".uno:InsertLinebreak"_ustr;
329 case css::awt::Key::INSERT_PARAGRAPH:
330 return u".uno:InsertPara"_ustr;
331 case css::awt::Key::MOVE_WORD_BACKWARD:
332 return u".uno:GoToPrevWord"_ustr;
333 case css::awt::Key::MOVE_WORD_FORWARD:
334 return u".uno:GoToNextWord"_ustr;
335 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
336 return u".uno:GoToStartOfLine"_ustr;
337 case css::awt::Key::MOVE_TO_END_OF_LINE:
338 return u".uno:GoToEndOfLine"_ustr;
339 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
340 return u".uno:GoToStartOfPara"_ustr;
341 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
342 return u".uno:GoToEndOfPara"_ustr;
343 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
344 return u".uno:GoToStartOfDoc"_ustr;
345 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
346 return u".uno:GoToEndOfDoc"_ustr;
347 case css::awt::Key::SELECT_BACKWARD:
348 return u".uno:CharLeftSel"_ustr;
349 case css::awt::Key::SELECT_FORWARD:
350 return u".uno:CharRightSel"_ustr;
351 case css::awt::Key::SELECT_WORD_BACKWARD:
352 return u".uno:WordLeftSel"_ustr;
353 case css::awt::Key::SELECT_WORD_FORWARD:
354 return u".uno:WordRightSel"_ustr;
355 case css::awt::Key::SELECT_WORD:
356 return u".uno:SelectWord"_ustr;
357 case css::awt::Key::SELECT_LINE:
358 return OUString();
359 case css::awt::Key::SELECT_PARAGRAPH:
360 return u".uno:SelectText"_ustr;
361 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
362 return u".uno:StartOfLineSel"_ustr;
363 case css::awt::Key::SELECT_TO_END_OF_LINE:
364 return u".uno:EndOfLineSel"_ustr;
365 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
366 return u".uno:StartOfParaSel"_ustr;
367 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
368 return u".uno:EndOfParaSel"_ustr;
369 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
370 return u".uno:StartOfDocumentSel"_ustr;
371 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
372 return u".uno:EndOfDocumentSel"_ustr;
373 case css::awt::Key::SELECT_ALL:
374 return u".uno:SelectAll"_ustr;
375 default:
376 break;
380 return OUString();
384 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openModuleConfig(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
385 const css::uno::Reference< css::frame::XFrame >& xFrame)
387 css::uno::Reference< css::frame::XModuleManager2 > xModuleDetection(
388 css::frame::ModuleManager::create(rxContext));
390 OUString sModule;
393 sModule = xModuleDetection->identify(xFrame);
395 catch(const css::uno::RuntimeException&)
396 { throw; }
397 catch(const css::uno::Exception&)
398 { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
400 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
401 css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext) );
403 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
406 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager(sModule);
407 xAccCfg = xUIManager->getShortCutManager();
409 catch(const css::container::NoSuchElementException&)
411 return xAccCfg;
414 css::uno::Reference<css::ui::XAcceleratorConfiguration> AcceleratorExecute::lok_createNewAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& rxContext, const OUString& sModule)
416 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext));
420 css::uno::Reference<css::ui::XUIConfigurationManager> xUIManager = xUISupplier->getUIConfigurationManager(sModule);
422 css::ui::XModuleUIConfigurationManager2* t = static_cast<css::ui::XModuleUIConfigurationManager2*>(xUIManager.get());
424 // Return new short cut manager in case current view's language is different from previous ones.
425 return t->createShortCutManager();
427 catch(const css::container::NoSuchElementException&)
430 return css::uno::Reference<css::ui::XAcceleratorConfiguration>();
433 void AcceleratorExecute::lok_setModuleConfig(const css::uno::Reference<css::ui::XAcceleratorConfiguration>& acceleratorConfig)
435 this->m_xModuleCfg = acceleratorConfig;
438 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
440 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
441 css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY);
442 if (xUISupplier.is())
444 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager();
445 xAccCfg = xUIManager->getShortCutManager();
447 return xAccCfg;
451 css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
453 // SAFE -> ----------------------------------
454 std::unique_lock aLock(m_aLock);
456 if (m_xURLParser.is())
457 return m_xURLParser;
458 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
460 aLock.unlock();
461 // <- SAFE ----------------------------------
463 css::uno::Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create( xContext );
465 // SAFE -> ----------------------------------
466 aLock.lock();
467 m_xURLParser = xParser;
468 aLock.unlock();
469 // <- SAFE ----------------------------------
471 return xParser;
474 AsyncAccelExec::AsyncAccelExec(css::uno::Reference<css::lang::XComponent> xFrame,
475 css::uno::Reference<css::frame::XDispatch> xDispatch,
476 css::util::URL aURL)
477 : m_xFrame(std::move(xFrame))
478 , m_xDispatch(std::move(xDispatch))
479 , m_aURL(std::move(aURL))
480 , m_aAsyncCallback(LINK(this, AsyncAccelExec, impl_ts_asyncCallback))
482 acquire();
485 rtl::Reference<AsyncAccelExec> AsyncAccelExec::createOneShotInstance(const css::uno::Reference<css::lang::XComponent> &xFrame,
486 const css::uno::Reference< css::frame::XDispatch >& xDispatch,
487 const css::util::URL& rURL)
489 rtl::Reference<AsyncAccelExec> pExec = new AsyncAccelExec(xFrame, xDispatch, rURL);
490 return pExec;
494 void AsyncAccelExec::execAsync()
496 if (m_xFrame.is())
497 m_xFrame->addEventListener(this);
498 m_aAsyncCallback.Post();
501 IMPL_LINK_NOARG(AsyncAccelExec, impl_ts_asyncCallback, LinkParamNone*, void)
503 if (m_xDispatch.is())
507 if (m_xFrame.is())
508 m_xFrame->removeEventListener(this);
509 m_xDispatch->dispatch(m_aURL, css::uno::Sequence< css::beans::PropertyValue >());
511 catch(const css::uno::Exception&)
515 release();
518 } // namespace svt
520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */