1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SoEvent SoEvent.h Inventor/events/SoEvent.h
35   \brief The SoEvent class is the base class for all Coin events.
36 
37   \ingroup events
38 
39   Coin contains its own set of event classes, independent of the underlying
40   window system.
41 
42   Upon system specific events, a translation is done by the window
43   specific device classes into one of the Coin event object classes
44   listed below. The event is then typically sent by the render area
45   to an SoSceneManager which will apply it to the scenegraph through
46   an SoHandleEventAction.
47 
48   Events may be caught by the user by attaching an SoEventCallback
49   node to the scenegraph, or it can automatically be handled by a
50   dragger or manipulator in the graph.
51 
52   \sa SoButtonEvent, SoKeyboardEvent, SoLocation2Event, SoMotion3Event
53   \sa SoMouseButtonEvent, SoSpaceballButtonEvent
54   \sa SoEventCallback, SoHandleEventAction */
55 
56 #include <Inventor/events/SoEvent.h>
57 
58 #include <cassert>
59 
60 #include <Inventor/events/SoMouseButtonEvent.h>
61 #include <Inventor/events/SoKeyboardEvent.h>
62 #include <Inventor/events/SoSpaceballButtonEvent.h>
63 #include <Inventor/events/SoLocation2Event.h>
64 #include <Inventor/events/SoMotion3Event.h>
65 #include <Inventor/SbViewportRegion.h>
66 #include <Inventor/SbName.h>
67 
68 #include "tidbitsp.h"
69 
70 SO_EVENT_ABSTRACT_SOURCE(SoEvent);
71 
72 /*!
73   \fn SoType SoEvent::getClassTypeId(void)
74 
75   This static method returns the SoType object associated with objects
76   of this class.
77  */
78 
79 
80 // FIXME: grab better version of getTypeId() doc from SoBase, SoAction
81 // and / or SoDetail. 20010913 mortene.
82 /*!
83   \fn SoType SoEvent::getTypeId(void) const
84 
85   Returns the actual type id of an instantiated object.
86 */
87 
88 
89 /*!
90   Initialize SoEvent and all it's known subclasses (i.e. all subclasses
91   which are part of the standard classes in the Coin library).
92 
93   This method is called from SoDB::init(), so it's very unlikely that
94   you will have to call it explicitly.
95  */
96 void
initClass(void)97 SoEvent::initClass(void)
98 {
99   // Make sure we only initialize once.
100   assert(SoEvent::classTypeId == SoType::badType());
101 
102   SoEvent::classTypeId = SoType::createType(SoType::badType(), "SoEvent");
103   coin_atexit(reinterpret_cast<coin_atexit_f *>(cleanupClass), CC_ATEXIT_NORMAL);
104 
105   SoEvent::initEvents();
106 }
107 
108 /*!
109   \COININTERNAL
110 
111   Initialize all known subclasses.
112  */
113 void
initEvents(void)114 SoEvent::initEvents(void)
115 {
116   SoButtonEvent::initClass();
117     SoMouseButtonEvent::initClass();
118     SoKeyboardEvent::initClass();
119     SoSpaceballButtonEvent::initClass();
120   SoLocation2Event::initClass();
121   SoMotion3Event::initClass();
122 }
123 
124 /*!
125   Constructor, will set all modifiers to "off" state.
126 */
SoEvent(void)127 SoEvent::SoEvent(void)
128 {
129   this->modifiers.shiftdown = 0;
130   this->modifiers.ctrldown = 0;
131   this->modifiers.altdown = 0;
132 }
133 
134 /*!
135   Destructor.
136  */
~SoEvent()137 SoEvent::~SoEvent()
138 {
139 }
140 
141 /*!
142   Returns TRUE if this object either has the same type as the given
143   \c type parameter, or if \c type belongs to a superclass of ourselves.
144 */
145 SbBool
isOfType(SoType type) const146 SoEvent::isOfType(SoType type) const
147 {
148   const SoType myType = this->getTypeId();
149   if (myType == type) return TRUE;
150   if (myType.isDerivedFrom(type)) return TRUE;
151   return FALSE;
152 }
153 
154 /*!
155   From a system specific device object, set the time the event occurred.
156 
157   \sa getTime()
158  */
159 void
setTime(const SbTime t)160 SoEvent::setTime(const SbTime t)
161 {
162   this->timeofevent = t;
163 }
164 
165 /*!
166   Returns the time the event occurred.
167 
168   \sa getPosition(), wasShiftDown(), wasCtrlDown(), wasAltDown()
169  */
170 SbTime
getTime(void) const171 SoEvent::getTime(void) const
172 {
173   return this->timeofevent;
174 }
175 
176 /*!
177   From a system specific device object, set the mouse pointer position
178   when the event occurred.
179 
180   \sa getPosition(), getNormalizedPosition()
181  */
182 void
setPosition(const SbVec2s & p)183 SoEvent::setPosition(const SbVec2s & p)
184 {
185   this->positionofevent = p;
186 }
187 
188 // FIXME: "window" below is ambiguous, replace with something less
189 // generic, like e.g. "the rendering canvas" or some such. Should also
190 // scan API docs for other references to "window" (and "widget"?) and
191 // do likewise. 20040728 mortene.
192 /*!
193   Returns the mouse pointer position when the event occurred. The
194   coordinates are given relative to the window coordinates.
195 
196   \sa getNormalizedPosition(), getTime(), wasShiftDown(), wasCtrlDown(),
197   \sa wasAltDown()
198  */
199 const SbVec2s &
getPosition(void) const200 SoEvent::getPosition(void) const
201 {
202   return this->positionofevent;
203 }
204 
205 /*!
206   Returns the mouse pointer position when the event occurred. The
207   coordinates are given relative to the viewport coordinates.
208 
209   \sa getNormalizedPosition(), getTime(), wasShiftDown(), wasCtrlDown(),
210   \sa wasAltDown()
211  */
212 const SbVec2s &
getPosition(const SbViewportRegion & vpRgn) const213 SoEvent::getPosition(const SbViewportRegion & vpRgn) const
214 {
215   positionVP = SbVec2s(this->positionofevent - vpRgn.getViewportOriginPixels());
216 
217   return positionVP;
218 }
219 
220 /*!
221   Returns the mouse pointer position when the event occurred. The
222   coordinates are given relative to the viewport coordinates,
223   normalized according to the size of the viewport.
224 
225   \sa getPosition(), getTime(), wasShiftDown(), wasCtrlDown(), wasAltDown()
226  */
227 const SbVec2f &
getNormalizedPosition(const SbViewportRegion & vpRgn) const228 SoEvent::getNormalizedPosition(const SbViewportRegion & vpRgn) const
229 {
230   SbVec2s p = this->positionofevent - vpRgn.getViewportOriginPixels();
231   SbVec2s s = vpRgn.getViewportSizePixels();
232 
233   positionVPNorm = SbVec2f(
234                            static_cast<float>(p[0])/static_cast<float>(s[0]),
235                            static_cast<float>(p[1])/static_cast<float>(s[1])
236                            );
237 
238   return positionVPNorm;
239 }
240 
241 /*!
242   From a system specific device object, set the state of the Shift key(s)
243   when the event occurred.
244 
245   \sa wasShiftDown(), setCtrlDown(), setAltDown()
246  */
247 void
setShiftDown(SbBool isDown)248 SoEvent::setShiftDown(SbBool isDown)
249 {
250   this->modifiers.shiftdown = isDown ? TRUE : FALSE;
251 }
252 
253 /*!
254   Returns state of Shift key(s) when the event occurred.
255 
256   \sa wasCtrlDown(), wasAltDown(), getPosition(), getTime()
257  */
258 SbBool
wasShiftDown(void) const259 SoEvent::wasShiftDown(void) const
260 {
261   return this->modifiers.shiftdown;
262 }
263 
264 /*!
265   From a system specific device object, set the state of the Ctrl key(s)
266   when the event occurred.
267 
268   \sa wasCtrlDown(), setShiftDown(), setAltDown()
269  */
270 void
setCtrlDown(SbBool isDown)271 SoEvent::setCtrlDown(SbBool isDown)
272 {
273   this->modifiers.ctrldown = isDown ? TRUE : FALSE;
274 }
275 
276 /*!
277   Returns state of Ctrl key(s) when the event occurred.
278 
279   \sa wasShiftDown(), wasAltDown(), getPosition(), getTime()
280  */
281 SbBool
wasCtrlDown(void) const282 SoEvent::wasCtrlDown(void) const
283 {
284   return this->modifiers.ctrldown;
285 }
286 
287 /*!
288   From a system specific device object, set the state of the Alt key(s)
289   when the event occurred.
290 
291   \sa wasAltDown(), setCtrlDown(), setShiftDown()
292  */
293 void
setAltDown(SbBool isDown)294 SoEvent::setAltDown(SbBool isDown)
295 {
296   this->modifiers.altdown = isDown ? TRUE : FALSE;
297 }
298 
299 /*!
300   Returns state of Alt key(s) when the event occurred.
301 
302   \sa wasShiftDown(), wasCtrlDown(), getPosition(), getTime()
303  */
304 SbBool
wasAltDown(void) const305 SoEvent::wasAltDown(void) const
306 {
307   return this->modifiers.altdown;
308 }
309