Line data Source code
1 :
2 : /* Copyright (c) 2013, Daniel Nachbaur <daniel.nachbaur@epfl.ch>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "eventHandler.h"
19 : #include "proxy.h"
20 :
21 : #include "../messagePump.h"
22 : #include "../channel.h"
23 : #include "../config.h"
24 : #include "../pipe.h"
25 : #include "../window.h"
26 : #include "../configEvent.h"
27 :
28 : #include <lunchbox/perThread.h>
29 : #include <deflect/Stream.h>
30 :
31 : namespace eq
32 : {
33 : namespace deflect
34 : {
35 : namespace
36 : {
37 : typedef std::vector< EventHandler* > EventHandlers;
38 14 : static lunchbox::PerThread< EventHandlers > _eventHandlers;
39 :
40 : const float wheelFactor = 1.f / 40.f;
41 :
42 : // Values come from QtCore/qnamespace.h, but don't want to depend on Qt just for that
43 0 : uint32_t _getKey( const int key )
44 : {
45 0 : switch( key )
46 : {
47 0 : case 0x01000000: return KC_ESCAPE;
48 0 : case 0x01000001: return KC_TAB;
49 0 : case 0x01000003: return KC_BACKSPACE;
50 0 : case 0x01000004: return KC_RETURN;
51 0 : case 0x01000010: return KC_HOME;
52 0 : case 0x01000011: return KC_END;
53 0 : case 0x01000012: return KC_LEFT;
54 0 : case 0x01000013: return KC_UP;
55 0 : case 0x01000014: return KC_RIGHT;
56 0 : case 0x01000015: return KC_DOWN;
57 0 : case 0x01000016: return KC_PAGE_UP;
58 0 : case 0x01000017: return KC_PAGE_DOWN;
59 0 : case 0x01000020: return KC_SHIFT_L;
60 0 : case 0x01000021: return KC_CONTROL_L;
61 0 : case 0x01000023: return KC_ALT_L;
62 0 : case 0x01000030: return KC_F1;
63 0 : case 0x01000031: return KC_F2;
64 0 : case 0x01000032: return KC_F3;
65 0 : case 0x01000033: return KC_F4;
66 0 : case 0x01000034: return KC_F5;
67 0 : case 0x01000035: return KC_F6;
68 0 : case 0x01000036: return KC_F7;
69 0 : case 0x01000037: return KC_F8;
70 0 : case 0x01000038: return KC_F9;
71 0 : case 0x01000039: return KC_F10;
72 0 : case 0x0100003a: return KC_F11;
73 0 : case 0x0100003b: return KC_F12;
74 0 : case 0x0100003c: return KC_F13;
75 0 : case 0x0100003d: return KC_F14;
76 0 : case 0x0100003e: return KC_F15;
77 0 : case 0x0100003f: return KC_F16;
78 0 : case 0x01000040: return KC_F17;
79 0 : case 0x01000041: return KC_F18;
80 0 : case 0x01000042: return KC_F19;
81 0 : case 0x01000043: return KC_F20;
82 0 : case 0x01000044: return KC_F21;
83 0 : case 0x01000045: return KC_F22;
84 0 : case 0x01000046: return KC_F23;
85 0 : case 0x01000047: return KC_F24;
86 0 : case 0x01001103: return KC_ALT_R;
87 0 : case 0x01ffffff: return KC_VOID;
88 0 : case 0x20: return key; // space
89 0 : default: return key+32;
90 : }
91 : }
92 :
93 0 : uint32_t _getButtons( const ::deflect::Event& deflectEvent )
94 : {
95 0 : uint32_t buttons = 0;
96 0 : if( deflectEvent.mouseLeft )
97 0 : buttons |= PTR_BUTTON1;
98 0 : if( deflectEvent.mouseMiddle )
99 0 : buttons |= PTR_BUTTON2;
100 0 : if( deflectEvent.mouseRight )
101 0 : buttons |= PTR_BUTTON3;
102 0 : return buttons;
103 : }
104 : }
105 :
106 0 : EventHandler::EventHandler( Proxy* proxy )
107 0 : : _proxy( proxy )
108 : {
109 0 : LBASSERT( proxy );
110 :
111 0 : if( !_eventHandlers )
112 0 : _eventHandlers = new EventHandlers;
113 0 : _eventHandlers->push_back( this );
114 :
115 0 : Pipe* pipe = proxy->getChannel().getPipe();
116 0 : MessagePump* messagePump = pipe->isThreaded() ? pipe->getMessagePump() :
117 0 : pipe->getConfig()->getMessagePump();
118 0 : if( messagePump )
119 0 : messagePump->register_( proxy );
120 : else
121 0 : LBINFO << "Using deflect::EventHandler without MessagePump, "
122 0 : << "external event dispatch assumed" << std::endl;
123 0 : }
124 :
125 0 : EventHandler::~EventHandler()
126 : {
127 0 : Pipe* pipe = _proxy->getChannel().getPipe();
128 : MessagePump* messagePump =
129 0 : dynamic_cast<MessagePump*>( pipe->isThreaded() ?
130 : pipe->getMessagePump() :
131 0 : pipe->getConfig()->getMessagePump( ));
132 0 : if( messagePump )
133 0 : messagePump->deregister( _proxy );
134 :
135 0 : EventHandlers::iterator i = lunchbox::find( *_eventHandlers, this );
136 0 : LBASSERT( i != _eventHandlers->end( ));
137 0 : _eventHandlers->erase( i );
138 0 : if( _eventHandlers->empty( ))
139 : {
140 0 : delete _eventHandlers.get();
141 0 : _eventHandlers = 0;
142 : }
143 0 : }
144 :
145 19 : void EventHandler::processEvents( const Proxy* proxy )
146 : {
147 19 : if( !_eventHandlers )
148 38 : return;
149 :
150 0 : for( EventHandlers::const_iterator i = _eventHandlers->begin();
151 0 : i != _eventHandlers->end(); ++i )
152 : {
153 0 : (*i)->_processEvents( proxy );
154 : }
155 : }
156 :
157 0 : void EventHandler::_processEvents( const Proxy* proxy )
158 : {
159 0 : LB_TS_THREAD( _thread );
160 0 : if( !_proxy || (proxy && _proxy != proxy ))
161 0 : return;
162 :
163 0 : Channel& channel = _proxy->getChannel();
164 0 : const PixelViewport& pvp = channel.getPixelViewport();
165 0 : Window* window = channel.getWindow();
166 :
167 0 : while( _proxy->hasNewEvent( ))
168 : {
169 0 : ::deflect::Event deflectEvent = _proxy->getEvent();
170 :
171 0 : if( deflectEvent.type == ::deflect::Event::EVT_CLOSE )
172 : {
173 0 : _proxy->stopRunning();
174 0 : ConfigEvent configEvent;
175 0 : configEvent.data.type = Event::EXIT;
176 0 : window->getConfig()->sendEvent( configEvent );
177 0 : break;
178 : }
179 :
180 0 : Event event;
181 0 : event.originator = channel.getID();
182 0 : event.serial = channel.getSerial();
183 0 : event.type = Event::UNKNOWN;
184 :
185 0 : const float x = deflectEvent.mouseX * pvp.w;
186 0 : const float y = deflectEvent.mouseY * pvp.h;
187 :
188 0 : switch( deflectEvent.type )
189 : {
190 : case ::deflect::Event::EVT_KEY_PRESS:
191 : case ::deflect::Event::EVT_KEY_RELEASE:
192 0 : event.type = deflectEvent.type == ::deflect::Event::EVT_KEY_PRESS ?
193 0 : Event::KEY_PRESS : Event::KEY_RELEASE;
194 0 : event.keyPress.key = _getKey( deflectEvent.key );
195 0 : break;
196 : case ::deflect::Event::EVT_PRESS:
197 : case ::deflect::Event::EVT_RELEASE:
198 0 : event.type = deflectEvent.type == ::deflect::Event::EVT_PRESS ?
199 : Event::CHANNEL_POINTER_BUTTON_PRESS :
200 0 : Event::CHANNEL_POINTER_BUTTON_RELEASE;
201 0 : event.pointerButtonPress.x = x;
202 0 : event.pointerButtonPress.y = y;
203 0 : event.pointerButtonPress.buttons = _getButtons( deflectEvent );
204 0 : event.pointerButtonPress.button = event.pointerButtonPress.buttons;
205 0 : _computePointerDelta( event );
206 0 : break;
207 : case ::deflect::Event::EVT_DOUBLECLICK:
208 0 : break;
209 : case ::deflect::Event::EVT_MOVE:
210 : case ::deflect::Event::EVT_PAN:
211 0 : event.type = Event::CHANNEL_POINTER_MOTION;
212 0 : event.pointerMotion.x = x;
213 0 : event.pointerMotion.y = y;
214 :
215 0 : if( deflectEvent.type == ::deflect::Event::EVT_PAN )
216 0 : event.pointerButtonPress.buttons = PTR_BUTTON3;
217 : else
218 0 : event.pointerButtonPress.buttons = _getButtons( deflectEvent );
219 0 : event.pointerMotion.button = event.pointerMotion.buttons;
220 :
221 0 : event.pointerMotion.dx = deflectEvent.dx * pvp.w;
222 0 : event.pointerMotion.dy = deflectEvent.dy * pvp.h;
223 0 : break;
224 : case ::deflect::Event::EVT_WHEEL:
225 0 : event.type = Event::CHANNEL_POINTER_WHEEL;
226 0 : event.pointerWheel.x = x;
227 0 : event.pointerWheel.y = pvp.h - y;
228 0 : event.pointerWheel.buttons = PTR_BUTTON_NONE;
229 0 : event.pointerWheel.xAxis = deflectEvent.dx * wheelFactor;
230 0 : event.pointerWheel.yAxis = deflectEvent.dy * wheelFactor;
231 0 : event.pointerMotion.dx = -deflectEvent.dx;
232 0 : event.pointerMotion.dy = -deflectEvent.dy;
233 0 : break;
234 : case ::deflect::Event::EVT_PINCH:
235 : {
236 0 : event.type = Event::CHANNEL_POINTER_WHEEL;
237 0 : event.pointerWheel.x = x;
238 0 : event.pointerWheel.y = pvp.h - y;
239 0 : event.pointerWheel.buttons = PTR_BUTTON_NONE;
240 0 : const auto dx = deflectEvent.dx * pvp.w;
241 0 : const auto dy = deflectEvent.dy * pvp.h;
242 0 : const auto sign = dx + dy;
243 0 : const auto zoom = std::copysign( std::sqrt( dx*dx + dy*dy ), sign );
244 0 : event.pointerWheel.xAxis = 0.f;
245 0 : event.pointerWheel.yAxis = zoom * wheelFactor;
246 0 : break;
247 : }
248 : case ::deflect::Event::EVT_NONE:
249 : default:
250 0 : break;
251 : }
252 :
253 0 : if( event.type != Event::UNKNOWN )
254 : {
255 : // TODO: compute and use window x,y coordinates
256 0 : if( !window->getRenderContext( x, y, event.context ))
257 0 : LBVERB << "No rendering context for pointer event at " << x
258 0 : << ", " << y << std::endl;
259 0 : channel.processEvent( event );
260 : }
261 0 : }
262 : }
263 :
264 : }
265 42 : }
|