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 21 #include <sfx2/userinputinterception.hxx> 22 23 #include <com/sun/star/awt/MouseButton.hpp> 24 #include <com/sun/star/awt/MouseEvent.hpp> 25 #include <com/sun/star/awt/InputEvent.hpp> 26 #include <com/sun/star/awt/KeyEvent.hpp> 27 #include <com/sun/star/awt/KeyModifier.hpp> 28 #include <com/sun/star/awt/XKeyHandler.hpp> 29 #include <com/sun/star/awt/XMouseClickHandler.hpp> 30 #include <com/sun/star/awt/XWindowPeer.hpp> 31 #include <com/sun/star/uno/XInterface.hpp> 32 33 #include <comphelper/interfacecontainer2.hxx> 34 #include <cppuhelper/weak.hxx> 35 #include <vcl/event.hxx> 36 #include <vcl/window.hxx> 37 #include <osl/diagnose.h> 38 39 namespace sfx2 40 { 41 42 43 using ::com::sun::star::uno::Reference; 44 using ::com::sun::star::uno::XInterface; 45 using ::com::sun::star::uno::Exception; 46 using ::com::sun::star::uno::RuntimeException; 47 using ::com::sun::star::awt::MouseEvent; 48 using ::com::sun::star::awt::KeyEvent; 49 using ::com::sun::star::awt::InputEvent; 50 using ::com::sun::star::awt::XKeyHandler; 51 using ::com::sun::star::awt::XMouseClickHandler; 52 using ::com::sun::star::lang::DisposedException; 53 54 namespace MouseButton = ::com::sun::star::awt::MouseButton; 55 namespace KeyModifier = ::com::sun::star::awt::KeyModifier; 56 57 struct UserInputInterception_Data 58 { 59 public: 60 ::cppu::OWeakObject& m_rControllerImpl; 61 ::comphelper::OInterfaceContainerHelper2 m_aKeyHandlers; 62 ::comphelper::OInterfaceContainerHelper2 m_aMouseClickHandlers; 63 64 public: UserInputInterception_Datasfx2::UserInputInterception_Data65 UserInputInterception_Data( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) 66 :m_rControllerImpl( _rControllerImpl ) 67 ,m_aKeyHandlers( _rMutex ) 68 ,m_aMouseClickHandlers( _rMutex ) 69 { 70 } 71 }; 72 73 namespace 74 { 75 template< class VCLEVENT > lcl_initModifiers(InputEvent & _rEvent,const VCLEVENT & _rVclEvent)76 void lcl_initModifiers( InputEvent& _rEvent, const VCLEVENT& _rVclEvent ) 77 { 78 _rEvent.Modifiers = 0; 79 80 if ( _rVclEvent.IsShift() ) 81 _rEvent.Modifiers |= KeyModifier::SHIFT; 82 if ( _rVclEvent.IsMod1() ) 83 _rEvent.Modifiers |= KeyModifier::MOD1; 84 if ( _rVclEvent.IsMod2() ) 85 _rEvent.Modifiers |= KeyModifier::MOD2; 86 if ( _rVclEvent.IsMod3() ) 87 _rEvent.Modifiers |= KeyModifier::MOD3; 88 } 89 lcl_initKeyEvent(KeyEvent & rEvent,const::KeyEvent & rEvt)90 void lcl_initKeyEvent( KeyEvent& rEvent, const ::KeyEvent& rEvt ) 91 { 92 lcl_initModifiers( rEvent, rEvt.GetKeyCode() ); 93 94 rEvent.KeyCode = rEvt.GetKeyCode().GetCode(); 95 rEvent.KeyChar = rEvt.GetCharCode(); 96 rEvent.KeyFunc = sal::static_int_cast< sal_Int16 >( rEvt.GetKeyCode().GetFunction()); 97 } 98 lcl_initMouseEvent(MouseEvent & rEvent,const::MouseEvent & rEvt)99 void lcl_initMouseEvent( MouseEvent& rEvent, const ::MouseEvent& rEvt ) 100 { 101 lcl_initModifiers( rEvent, rEvt ); 102 103 rEvent.Buttons = 0; 104 if ( rEvt.IsLeft() ) 105 rEvent.Buttons |= MouseButton::LEFT; 106 if ( rEvt.IsRight() ) 107 rEvent.Buttons |= MouseButton::RIGHT; 108 if ( rEvt.IsMiddle() ) 109 rEvent.Buttons |= MouseButton::MIDDLE; 110 111 rEvent.X = rEvt.GetPosPixel().X(); 112 rEvent.Y = rEvt.GetPosPixel().Y(); 113 rEvent.ClickCount = rEvt.GetClicks(); 114 rEvent.PopupTrigger = false; 115 } 116 117 } 118 119 120 //= UserInputInterception 121 122 UserInputInterception(::cppu::OWeakObject & _rControllerImpl,::osl::Mutex & _rMutex)123 UserInputInterception::UserInputInterception( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) 124 :m_pData( new UserInputInterception_Data( _rControllerImpl, _rMutex ) ) 125 { 126 } 127 128 ~UserInputInterception()129 UserInputInterception::~UserInputInterception() 130 { 131 } 132 133 addKeyHandler(const Reference<XKeyHandler> & _rxHandler)134 void UserInputInterception::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) 135 { 136 if ( _rxHandler.is() ) 137 m_pData->m_aKeyHandlers.addInterface( _rxHandler ); 138 } 139 140 removeKeyHandler(const Reference<XKeyHandler> & _rxHandler)141 void UserInputInterception::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) 142 { 143 m_pData->m_aKeyHandlers.removeInterface( _rxHandler ); 144 } 145 146 addMouseClickHandler(const Reference<XMouseClickHandler> & _rxHandler)147 void UserInputInterception::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) 148 { 149 if ( _rxHandler.is() ) 150 m_pData->m_aMouseClickHandlers.addInterface( _rxHandler ); 151 } 152 153 removeMouseClickHandler(const Reference<XMouseClickHandler> & _rxHandler)154 void UserInputInterception::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) 155 { 156 m_pData->m_aMouseClickHandlers.removeInterface( _rxHandler ); 157 } 158 159 hasKeyHandlers() const160 bool UserInputInterception::hasKeyHandlers() const 161 { 162 return m_pData->m_aKeyHandlers.getLength() > 0; 163 } 164 165 hasMouseClickListeners() const166 bool UserInputInterception::hasMouseClickListeners() const 167 { 168 return m_pData->m_aMouseClickHandlers.getLength() > 0; 169 } 170 171 handleNotifyEvent(const NotifyEvent & _rEvent)172 bool UserInputInterception::handleNotifyEvent( const NotifyEvent& _rEvent ) 173 { 174 Reference < XInterface > xHoldAlive( m_pData->m_rControllerImpl ); 175 176 MouseNotifyEvent nType = _rEvent.GetType(); 177 bool bHandled = false; 178 179 switch ( nType ) 180 { 181 case MouseNotifyEvent::KEYINPUT: 182 case MouseNotifyEvent::KEYUP: 183 { 184 KeyEvent aEvent; 185 lcl_initKeyEvent( aEvent, *_rEvent.GetKeyEvent() ); 186 if ( _rEvent.GetWindow() ) 187 aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); 188 189 ::comphelper::OInterfaceIteratorHelper2 aIterator( m_pData->m_aKeyHandlers ); 190 while ( aIterator.hasMoreElements() ) 191 { 192 Reference< XKeyHandler > xHandler( static_cast< XKeyHandler* >( aIterator.next() ) ); 193 if ( !xHandler.is() ) 194 continue; 195 196 try 197 { 198 if ( nType == MouseNotifyEvent::KEYINPUT ) 199 bHandled = xHandler->keyPressed( aEvent ); 200 else 201 bHandled = xHandler->keyReleased( aEvent ); 202 } 203 catch( const DisposedException& e ) 204 { 205 if ( e.Context == xHandler ) 206 aIterator.remove(); 207 } 208 catch( const RuntimeException& ) 209 { 210 throw; 211 } 212 catch( const Exception& ) 213 { 214 } 215 } 216 } 217 break; 218 219 case MouseNotifyEvent::MOUSEBUTTONDOWN: 220 case MouseNotifyEvent::MOUSEBUTTONUP: 221 { 222 MouseEvent aEvent; 223 lcl_initMouseEvent( aEvent, *_rEvent.GetMouseEvent() ); 224 if ( _rEvent.GetWindow() ) 225 aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); 226 227 ::comphelper::OInterfaceIteratorHelper2 aIterator( m_pData->m_aMouseClickHandlers ); 228 while ( aIterator.hasMoreElements() ) 229 { 230 Reference< XMouseClickHandler > xHandler( static_cast< XMouseClickHandler* >( aIterator.next() ) ); 231 if ( !xHandler.is() ) 232 continue; 233 234 try 235 { 236 if ( nType == MouseNotifyEvent::MOUSEBUTTONDOWN ) 237 bHandled = xHandler->mousePressed( aEvent ); 238 else 239 bHandled = xHandler->mouseReleased( aEvent ); 240 } 241 catch( const DisposedException& e ) 242 { 243 if ( e.Context == xHandler ) 244 aIterator.remove(); 245 } 246 catch( const RuntimeException& ) 247 { 248 throw; 249 } 250 catch( const Exception& ) 251 { 252 } 253 } 254 } 255 break; 256 257 default: 258 OSL_FAIL( "UserInputInterception::handleNotifyEvent: illegal event type!" ); 259 break; 260 } 261 262 return bHandled; 263 } 264 265 266 } // namespace sfx2 267 268 269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 270