LibreOffice Module svtools (master) 1
acceleratorexecute.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
22
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>
36
37#include <utility>
38#include <vcl/evntpost.hxx>
39#include <sal/log.hxx>
40#include <vcl/lok.hxx>
41#include <rtl/ref.hxx>
42
43#include <comphelper/lok.hxx>
44
45namespace svt
46{
47
48namespace {
49
50class AsyncAccelExec : public cppu::WeakImplHelper<css::lang::XEventListener>
51{
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:
58
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);
68
69 void execAsync();
70 private:
71
72 virtual void SAL_CALL disposing(const css::lang::EventObject&) override
73 {
74 m_xFrame->removeEventListener(this);
75 m_xFrame.clear();
76 m_xDispatch.clear();
77 }
78
82 AsyncAccelExec(css::uno::Reference<css::lang::XComponent> xFrame,
83 css::uno::Reference< css::frame::XDispatch > xDispatch,
84 css::util::URL aURL);
85
86 DECL_LINK(impl_ts_asyncCallback, LinkParamNone*, void);
87};
88
89}
90
92{
93}
94
96{
97 // does nothing real
98}
99
100
101std::unique_ptr<AcceleratorExecute> AcceleratorExecute::createAcceleratorHelper()
102{
103 return std::unique_ptr<AcceleratorExecute>(new AcceleratorExecute);
104}
105
106
107void AcceleratorExecute::init(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
108 const css::uno::Reference< css::frame::XFrame >& xEnv )
109{
110 // SAFE -> ----------------------------------
111 std::unique_lock aLock(m_aLock);
112
113 // take over the uno service manager
114 m_xContext = rxContext;
115
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())
121 {
122 aLock.unlock();
123 // <- SAFE ------------------------------
124
125 css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(css::frame::Desktop::create(rxContext), css::uno::UNO_QUERY_THROW);
126
127 // SAFE -> ------------------------------
128 aLock.lock();
129
130 m_xDispatcher = xDispatcher;
131 bDesktopIsUsed = true;
132 }
133
134 aLock.unlock();
135 // <- SAFE ----------------------------------
136
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 ;
141
142 // global cfg
143 xGlobalCfg = css::ui::GlobalAcceleratorConfiguration::create(rxContext);
144 if (!bDesktopIsUsed)
145 {
146 // module cfg
147 xModuleCfg = AcceleratorExecute::st_openModuleConfig(rxContext, xEnv);
148
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())
157 }
158
159 // SAFE -> ------------------------------
160 aLock.lock();
161
162 m_xGlobalCfg = xGlobalCfg;
163 m_xModuleCfg = xModuleCfg;
164 m_xDocCfg = xDocCfg ;
165
166 aLock.unlock();
167 // <- SAFE ----------------------------------
168}
169
170
172{
173 css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
174 return execute(aAWTKey);
175}
176
177
178bool AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
179{
180 OUString sCommand = impl_ts_findCommand(aAWTKey);
181
182 // No Command found? Do nothing! User is not interested on any error handling .-)
183 // or for some reason m_xContext is NULL (which would crash impl_ts_getURLParser()
184 if (sCommand.isEmpty() || !m_xContext.is())
185 {
186 return false;
187 }
188
189 // SAFE -> ----------------------------------
190 std::unique_lock aLock(m_aLock);
191
192 css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
193
194 aLock.unlock();
195 // <- SAFE ----------------------------------
196
197 // convert command in URL structure
198 css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
199 css::util::URL aURL;
200 aURL.Complete = sCommand;
201 xParser->parseStrict(aURL);
202
203 // ask for dispatch object
204 css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, OUString(), 0);
205 bool bRet = xDispatch.is();
206 if ( bRet )
207 {
208 // Note: Such instance can be used one times only and destroy itself afterwards .-)
209 css::uno::Reference<css::lang::XComponent> xFrame(xProvider, css::uno::UNO_QUERY);
211 { // tdf#130382 - all synchronous really.
212 try {
213 xDispatch->dispatch (aURL, css::uno::Sequence< css::beans::PropertyValue >());
214 }
215 catch(const css::uno::Exception&ev)
216 {
217 SAL_INFO("svtools", "exception on key emission: " << ev.Message);
218 }
219 }
220 else
221 {
222 rtl::Reference<AsyncAccelExec> pExec = AsyncAccelExec::createOneShotInstance(xFrame, xDispatch, aURL);
223 pExec->execAsync();
224 }
225 }
226
227 return bRet;
228}
229
230
231css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const vcl::KeyCode& aVCLKey)
232{
233 css::awt::KeyEvent aAWTKey;
234 aAWTKey.Modifiers = 0;
235 aAWTKey.KeyCode = static_cast<sal_Int16>(aVCLKey.GetCode());
236
237 if (aVCLKey.IsShift())
238 aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
239 if (aVCLKey.IsMod1())
240 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
241 if (aVCLKey.IsMod2())
242 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
243 if (aVCLKey.IsMod3())
244 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
245 return aAWTKey;
246}
247
248
249vcl::KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
250{
251 bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
252 bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
253 bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
254 bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
255 sal_uInt16 nKey = static_cast<sal_uInt16>(aAWTKey.KeyCode);
256
257 return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
258}
259
260OUString AcceleratorExecute::findCommand(const css::awt::KeyEvent& aKey)
261{
262 return impl_ts_findCommand(aKey);
263}
264
265OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
266{
267 // SAFE -> ----------------------------------
268 std::unique_lock aLock(m_aLock);
269
270 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
271 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
272 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg = m_xDocCfg ;
273
274 aLock.unlock();
275 // <- SAFE ----------------------------------
276
277 OUString sCommand;
278
279 try
280 {
281 if (xDocCfg.is())
282 sCommand = xDocCfg->getCommandByKeyEvent(aKey);
283 if (!sCommand.isEmpty())
284 return sCommand;
285 }
286 catch(const css::container::NoSuchElementException&)
287 {}
288
289 try
290 {
291 if (xModuleCfg.is())
292 sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
293 if (!sCommand.isEmpty())
294 return sCommand;
295 }
296 catch(const css::container::NoSuchElementException&)
297 {}
298
299 try
300 {
301 if (xGlobalCfg.is())
302 sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
303 if (!sCommand.isEmpty())
304 return sCommand;
305 }
306 catch(const css::container::NoSuchElementException&)
307 {}
308
309 // fall back to functional key codes
310 if( aKey.Modifiers == 0 )
311 {
312 switch( aKey.KeyCode )
313 {
314 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
315 return ".uno:DelToStartOfLine";
316 case css::awt::Key::DELETE_TO_END_OF_LINE:
317 return ".uno:DelToEndOfLine";
318 case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
319 return ".uno:DelToStartOfPara";
320 case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
321 return ".uno:DelToEndOfPara";
322 case css::awt::Key::DELETE_WORD_BACKWARD:
323 return ".uno:DelToStartOfWord";
324 case css::awt::Key::DELETE_WORD_FORWARD:
325 return ".uno:DelToEndOfWord";
326 case css::awt::Key::INSERT_LINEBREAK:
327 return ".uno:InsertLinebreak";
328 case css::awt::Key::INSERT_PARAGRAPH:
329 return ".uno:InsertPara";
330 case css::awt::Key::MOVE_WORD_BACKWARD:
331 return ".uno:GoToPrevWord";
332 case css::awt::Key::MOVE_WORD_FORWARD:
333 return ".uno:GoToNextWord";
334 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
335 return ".uno:GoToStartOfLine";
336 case css::awt::Key::MOVE_TO_END_OF_LINE:
337 return ".uno:GoToEndOfLine";
338 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
339 return ".uno:GoToStartOfPara";
340 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
341 return ".uno:GoToEndOfPara";
342 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
343 return ".uno:GoToStartOfDoc";
344 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
345 return ".uno:GoToEndOfDoc";
346 case css::awt::Key::SELECT_BACKWARD:
347 return ".uno:CharLeftSel";
348 case css::awt::Key::SELECT_FORWARD:
349 return ".uno:CharRightSel";
350 case css::awt::Key::SELECT_WORD_BACKWARD:
351 return ".uno:WordLeftSel";
352 case css::awt::Key::SELECT_WORD_FORWARD:
353 return ".uno:WordRightSel";
354 case css::awt::Key::SELECT_WORD:
355 return ".uno:SelectWord";
356 case css::awt::Key::SELECT_LINE:
357 return OUString();
358 case css::awt::Key::SELECT_PARAGRAPH:
359 return ".uno:SelectText";
360 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
361 return ".uno:StartOfLineSel";
362 case css::awt::Key::SELECT_TO_END_OF_LINE:
363 return ".uno:EndOfLineSel";
364 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
365 return ".uno:StartOfParaSel";
366 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
367 return ".uno:EndOfParaSel";
368 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
369 return ".uno:StartOfDocumentSel";
370 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
371 return ".uno:EndOfDocumentSel";
372 case css::awt::Key::SELECT_ALL:
373 return ".uno:SelectAll";
374 default:
375 break;
376 }
377 }
378
379 return OUString();
380}
381
382
383css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openModuleConfig(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
384 const css::uno::Reference< css::frame::XFrame >& xFrame)
385{
386 css::uno::Reference< css::frame::XModuleManager2 > xModuleDetection(
387 css::frame::ModuleManager::create(rxContext));
388
389 OUString sModule;
390 try
391 {
392 sModule = xModuleDetection->identify(xFrame);
393 }
394 catch(const css::uno::RuntimeException&)
395 { throw; }
396 catch(const css::uno::Exception&)
397 { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
398
399 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
400 css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext) );
401
402 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
403 try
404 {
405 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager(sModule);
406 xAccCfg = xUIManager->getShortCutManager();
407 }
408 catch(const css::container::NoSuchElementException&)
409 {}
410 return xAccCfg;
411}
412
413css::uno::Reference<css::ui::XAcceleratorConfiguration> AcceleratorExecute::lok_createNewAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& rxContext, OUString sModule)
414{
415 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext));
416
417 try
418 {
419 css::uno::Reference<css::ui::XUIConfigurationManager> xUIManager = xUISupplier->getUIConfigurationManager(sModule);
420
421 css::ui::XModuleUIConfigurationManager2* t = static_cast<css::ui::XModuleUIConfigurationManager2*>(xUIManager.get());
422
423 // Return new short cut manager in case current view's language is different from previous ones.
424 return t->createShortCutManager();
425 }
426 catch(const css::container::NoSuchElementException&)
427 {}
428
429 return css::uno::Reference<css::ui::XAcceleratorConfiguration>();
430}
431
432void AcceleratorExecute::lok_setModuleConfig(css::uno::Reference<css::ui::XAcceleratorConfiguration> acceleratorConfig)
433{
434 this->m_xModuleCfg = acceleratorConfig;
435}
436
437css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
438{
439 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
440 css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY);
441 if (xUISupplier.is())
442 {
443 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager();
444 xAccCfg = xUIManager->getShortCutManager();
445 }
446 return xAccCfg;
447}
448
449
450css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
451{
452 // SAFE -> ----------------------------------
453 std::unique_lock aLock(m_aLock);
454
455 if (m_xURLParser.is())
456 return m_xURLParser;
457 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
458
459 aLock.unlock();
460 // <- SAFE ----------------------------------
461
462 css::uno::Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create( xContext );
463
464 // SAFE -> ----------------------------------
465 aLock.lock();
466 m_xURLParser = xParser;
467 aLock.unlock();
468 // <- SAFE ----------------------------------
469
470 return xParser;
471}
472
473AsyncAccelExec::AsyncAccelExec(css::uno::Reference<css::lang::XComponent> xFrame,
474 css::uno::Reference<css::frame::XDispatch> xDispatch,
475 css::util::URL aURL)
476 : m_xFrame(std::move(xFrame))
477 , m_xDispatch(std::move(xDispatch))
478 , m_aURL(std::move(aURL))
479 , m_aAsyncCallback(LINK(this, AsyncAccelExec, impl_ts_asyncCallback))
480{
481 acquire();
482}
483
484rtl::Reference<AsyncAccelExec> AsyncAccelExec::createOneShotInstance(const css::uno::Reference<css::lang::XComponent> &xFrame,
485 const css::uno::Reference< css::frame::XDispatch >& xDispatch,
486 const css::util::URL& rURL)
487{
488 rtl::Reference<AsyncAccelExec> pExec = new AsyncAccelExec(xFrame, xDispatch, rURL);
489 return pExec;
490}
491
492
493void AsyncAccelExec::execAsync()
494{
495 if (m_xFrame.is())
496 m_xFrame->addEventListener(this);
497 m_aAsyncCallback.Post();
498}
499
500IMPL_LINK_NOARG(AsyncAccelExec, impl_ts_asyncCallback, LinkParamNone*, void)
501{
502 if (m_xDispatch.is())
503 {
504 try
505 {
506 if (m_xFrame.is())
507 m_xFrame->removeEventListener(this);
508 m_xDispatch->dispatch(m_aURL, css::uno::Sequence< css::beans::PropertyValue >());
509 }
510 catch(const css::uno::Exception&)
511 {
512 }
513 }
514 release();
515}
516
517} // namespace svt
518
519/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
css::uno::Reference< css::lang::XComponent > m_xFrame
vcl::EventPoster m_aAsyncCallback
css::uno::Reference< css::frame::XDispatch > m_xDispatch
css::util::URL m_aURL
@descr implements a helper, which can be used to convert vcl key codes into awt key codes ....
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xDocCfg
static css::uno::Reference< css::ui::XAcceleratorConfiguration > st_openDocConfig(const css::uno::Reference< css::frame::XModel > &xModel)
TODO document me.
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xGlobalCfg
TODO document me.
~AcceleratorExecute()
fight against inlining ...
OUString findCommand(const css::awt::KeyEvent &aKey)
search the command for the given key event.
css::uno::Reference< css::frame::XDispatchProvider > m_xDispatcher
TODO document me.
static vcl::KeyCode st_AWTKey2VCLKey(const css::awt::KeyEvent &aKey)
css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xModuleCfg
static css::awt::KeyEvent st_VCLKey2AWTKey(const vcl::KeyCode &aKey)
TODO document me.
void init(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XFrame > &xEnv)
init this instance.
css::uno::Reference< css::uno::XComponentContext > m_xContext
TODO document me.
static std::unique_ptr< AcceleratorExecute > createAcceleratorHelper()
factory method to create new accelerator helper instance.
static css::uno::Reference< css::ui::XAcceleratorConfiguration > st_openModuleConfig(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XFrame > &xFrame)
TODO document me.
void lok_setModuleConfig(css::uno::Reference< css::ui::XAcceleratorConfiguration > acceleratorConfig)
SVT_DLLPRIVATE css::uno::Reference< css::util::XURLTransformer > impl_ts_getURLParser()
TODO document me.
css::uno::Reference< css::util::XURLTransformer > m_xURLParser
TODO document me.
SVT_DLLPRIVATE OUString impl_ts_findCommand(const css::awt::KeyEvent &aKey)
TODO document me.
static css::uno::Reference< css::ui::XAcceleratorConfiguration > lok_createNewAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext > &rxContext, OUString sModule)
SVT_DLLPRIVATE AcceleratorExecute()
allow creation of instances of this class by using our factory only!
bool execute(const vcl::KeyCode &aKey)
trigger this accelerator.
bool IsMod1() const
sal_uInt16 GetCode() const
bool IsShift() const
bool IsMod2() const
bool IsMod3() const
Reference< XDispatch > xDispatch
URL aURL
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
#define SAL_INFO(area, stream)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
IMPL_LINK_NOARG(OCommonPicker, OnCancelPicker, void *, void)
bool isUnipoll()
Reference< XController > xController
Reference< XFrame > xFrame
Reference< XModel > xModel