merge with/from trunk at r35190
[blender.git] / intern / ghost / intern / GHOST_EventManager.cpp
1 /*
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file ghost/intern/GHOST_EventManager.cpp
30  *  \ingroup GHOST
31  */
32
33
34 /**
35
36  * $Id$
37  * Copyright (C) 2001 NaN Technologies B.V.
38  * @author      Maarten Gribnau
39  * @date        May 14, 2001
40  */
41
42 #include "GHOST_EventManager.h"
43 #include <algorithm>
44 #include "GHOST_Debug.h"
45
46 #include "GHOST_System.h"
47 #include "GHOST_IWindow.h"
48 #include "GHOST_WindowManager.h"
49 #include "GHOST_Event.h"
50 #include "GHOST_EventButton.h"
51 #include "GHOST_EventCursor.h"
52 #include "GHOST_EventKey.h"
53 #include "GHOST_EventWheel.h"
54 #include "GHOST_EventTrackpad.h"
55
56 GHOST_EventManager::GHOST_EventManager()
57 {
58         m_playfile = m_recfile = NULL;
59         m_lasttime = 0;
60 }
61
62
63 GHOST_EventManager::~GHOST_EventManager()
64 {
65         disposeEvents();
66
67         TConsumerVector::iterator iter= m_consumers.begin();
68         while (iter != m_consumers.end())
69         {
70                 GHOST_IEventConsumer* consumer = *iter;
71                 delete consumer;
72                 m_consumers.erase(iter);
73                 iter = m_consumers.begin();
74         }
75 }
76
77
78 GHOST_TUns32 GHOST_EventManager::getNumEvents()
79 {
80         return (GHOST_TUns32) m_events.size();
81 }
82
83
84 GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
85 {
86         GHOST_TUns32 numEvents = 0;
87         TEventStack::iterator p;
88         for (p = m_events.begin(); p != m_events.end(); p++) {
89                 if ((*p)->getType() == type) {
90                         numEvents++;
91                 }
92         }
93         return numEvents;
94 }
95
96
97 GHOST_IEvent* GHOST_EventManager::peekEvent()
98 {
99         GHOST_IEvent* event = 0;
100         if (m_events.size() > 0) {
101                 event = m_events.back();
102         }
103         return event;
104 }
105
106         
107 GHOST_TSuccess GHOST_EventManager::beginRecord(FILE *file)
108 {
109         if (m_playfile || !file)
110                 return GHOST_kFailure;
111                 
112         m_recfile = file;
113         return GHOST_kSuccess;
114 }
115
116 GHOST_TSuccess GHOST_EventManager::endRecord()
117 {
118         if (!m_recfile)
119                 return GHOST_kFailure;
120                 
121         m_recfile = NULL;
122         return GHOST_kSuccess;
123 }
124
125 GHOST_TSuccess GHOST_EventManager::playbackEvents(FILE *file)
126 {
127         if (m_recfile || !file)
128                 return GHOST_kFailure;
129                 
130         m_playfile = file;
131         return GHOST_kSuccess;
132 }
133
134 GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event)
135 {
136         GHOST_TSuccess success;
137         GHOST_ASSERT(event, "invalid event");
138         if (m_events.size() < m_events.max_size()) {
139                 m_events.push_front(event);
140                 success = GHOST_kSuccess;
141                 if (m_recfile) {
142                         GHOST_System *sys;
143                         GHOST_ModifierKeys keys;
144                         GHOST_TInt32 x, y;
145                         char buf[256];
146
147                         sys = reinterpret_cast<GHOST_System*>(GHOST_ISystem::getSystem());
148                         
149                         /*write event parent class data*/
150                         event->writeheader(buf);
151                         fprintf(m_recfile, "%s\n", buf);
152                         
153                         /*write child class data*/
154                         event->serialize(buf);
155                         fprintf(m_recfile, "%s\n", buf);
156                         
157                         /*write modifier key states*/
158                         sys->getModifierKeys(keys);
159                         fprintf(m_recfile, "lshift: %d rshift: %d lalt: %d ralt: %d lctrl: %d rctrl: %d command: %d\n", 
160                                 (int)keys.get(GHOST_kModifierKeyLeftShift),
161                                 (int)keys.get(GHOST_kModifierKeyRightShift), 
162                                 (int)keys.get(GHOST_kModifierKeyLeftAlt), 
163                                 (int)keys.get(GHOST_kModifierKeyRightAlt), 
164                                 (int)keys.get(GHOST_kModifierKeyLeftControl), 
165                                 (int)keys.get(GHOST_kModifierKeyRightControl));
166                         fflush(m_recfile);
167                         
168                         sys->getCursorPosition(x, y);
169
170                         /*write mouse cursor state*/
171                         fprintf(m_recfile, "mcursorstate: %d %d\n", x, y);
172                 }
173         }
174         else {
175                 success = GHOST_kFailure;
176         }
177         return success;
178 }
179
180
181 bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event)
182 {
183         bool handled;
184         if (event) {
185                 handled = true;
186                 TConsumerVector::iterator iter;
187                 for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) {
188                         if ((*iter)->processEvent(event)) {
189                                 handled = false;
190                         }
191                 }
192         }
193         else {
194                 handled = false;
195         }
196         return handled;
197 }
198
199 bool GHOST_EventManager::playingEvents(bool *hasevent) {
200         if (hasevent && m_events.size()) {
201                 GHOST_IEvent *event = m_events[m_events.size()-1];
202                 GHOST_System *sys;
203
204                 sys = reinterpret_cast<GHOST_System*>(GHOST_ISystem::getSystem());
205                 *hasevent = event->getType()==0 || sys->getMilliSeconds()-m_lasttime > event->getTime();
206                 
207                 if (event->getType()==0)
208                         popEvent();
209         } else if (hasevent) 
210                 *hasevent = true;
211         
212         return m_playfile != NULL;
213 }
214
215 bool GHOST_EventManager::dispatchEvent()
216 {
217         GHOST_IEvent* event = popEvent(); 
218         bool handled = false;
219         if (event) {
220                 handled = dispatchEvent(event);
221                 delete event;
222         }
223         return handled;
224 }
225
226
227 bool GHOST_EventManager::dispatchEvents()
228 {
229         bool handled = false;
230         
231         if (m_recfile && getNumEvents()) {
232                 fprintf(m_recfile, "break\n");
233         }
234         
235         if (m_playfile) {
236                 GHOST_IEvent *event = NULL;
237                 GHOST_System *sys;
238                 GHOST_WindowManager *wm;
239                 GHOST_TInt32 x, y;
240                 GHOST_ModifierKeys modkeys;
241                 std::vector<GHOST_IWindow *> windows;
242                 double lasttime = -1.0;
243                 char buf[256], *str;
244                                 
245                 sys = reinterpret_cast<GHOST_System*>(GHOST_ISystem::getSystem());
246                 wm = sys->getWindowManager();
247                 windows = wm->getWindows();
248
249                 while (str = fgets(buf, 256, m_playfile)) {
250                         GHOST_IWindow *iwin = NULL;
251                         GHOST_TEventType type;
252                         double time;
253                         int winid, i;
254                         int ctype;
255                         
256                         event = NULL;
257                         
258                         if (strcmp(str, "break\n")==0) {
259                                 event = new GHOST_Event(0, GHOST_kEventUnknown, NULL);
260                                 pushEvent(event);
261                                 continue;
262                         }
263                         
264                         sscanf(str, "%lf %d %d", &time, &ctype, &winid);
265                         type = (GHOST_TEventType)(ctype);
266                         
267                         if (lasttime > 0.0) {
268                                 double t = time;
269                                 
270                                 time -= lasttime;
271                                 lasttime = t;
272                         } else lasttime = time;
273                         
274                         for (i=0; i<windows.size(); i++) {
275                                 if (windows[i]->getID() == winid)
276                                         break;
277                         }
278                         
279                         if (i == windows.size()) {
280                                 printf("Eek! Could not find window %d!\n", winid);
281                                 str = fgets(buf, 256, m_playfile);
282                                 continue;
283                         }
284                         
285                         iwin = windows[i];
286                         
287                         str = fgets(buf, 256, m_playfile);
288                         if (!str)
289                                 break;
290                                 
291                         switch (type) {
292                                 case GHOST_kEventCursorMove:
293                                         event = new GHOST_EventCursor(time*1000, type, iwin, str);
294                                         break;
295                                 case GHOST_kEventButtonDown:
296                                         event = new GHOST_EventButton(time*1000, type, iwin, str);
297                                         break;
298                                 case GHOST_kEventButtonUp:
299                                         event = new GHOST_EventButton(time*1000, type, iwin, str);
300                                         break;
301                                 case GHOST_kEventWheel:
302                                         event = new GHOST_EventWheel(time*1000, type, iwin, str);
303                                         break;
304                                 case GHOST_kEventTrackpad:
305                                         event = new GHOST_EventTrackpad(time*1000, type, iwin, str);
306                                         break;
307                         
308                                 case GHOST_kEventNDOFMotion:
309                                         break;
310                                 case GHOST_kEventNDOFButton:
311                                         break;
312                         
313                                 case GHOST_kEventKeyDown:
314                                         event = new GHOST_EventKey(time*1000, type, iwin, str);
315                                         break;
316                                 case GHOST_kEventKeyUp:
317                                         event = new GHOST_EventKey(time*1000, type, iwin, str);
318                                         break;
319                         //      case GHOST_kEventKeyAuto:
320                         
321                                 case GHOST_kEventQuit:
322                                         break;
323                         
324                                 case GHOST_kEventWindowClose:
325                                         break;
326                                 case GHOST_kEventWindowActivate:
327                                         break;
328                                 case GHOST_kEventWindowDeactivate:
329                                         break;
330                                 case GHOST_kEventWindowUpdate:
331                                         break;
332                                 case GHOST_kEventWindowSize:
333                                         break;
334                                 case GHOST_kEventWindowMove:
335                                         break;
336                                 
337                                 case GHOST_kEventDraggingEntered:
338                                         break;
339                                 case GHOST_kEventDraggingUpdated:
340                                         break;
341                                 case GHOST_kEventDraggingExited:
342                                         break;
343                                 case GHOST_kEventDraggingDropDone:
344                                         break;
345                                 
346                                 case GHOST_kEventOpenMainFile:
347                                         break;
348                         
349                                 case GHOST_kEventTimer:
350                                         break;                          
351                         }
352                         
353                         str = fgets(buf, 256, m_playfile);
354                         if (str) {
355                                 int lshift, rshift, lalt, ralt, lctrl, rctrl, command;
356                                 sscanf(str, "lshift: %d rshift: %d lalt: %d ralt: %d lctrl: %d rctrl: %d command: %d",
357                                             &lshift, &rshift, &lalt, &ralt, &lctrl, &rctrl, &command);
358                                 modkeys.set(GHOST_kModifierKeyLeftShift, lshift);
359                                 modkeys.set(GHOST_kModifierKeyRightShift, rshift);
360                                 modkeys.set(GHOST_kModifierKeyLeftAlt, lalt);
361                                 modkeys.set(GHOST_kModifierKeyRightAlt, ralt);
362                                 modkeys.set(GHOST_kModifierKeyLeftControl, lctrl);
363                                 modkeys.set(GHOST_kModifierKeyRightControl, rctrl);
364                         }           
365                         
366                         str = fgets(buf, 256, m_playfile);
367                         if (str) {
368                                 /*read mouse cursor state*/
369                                 sscanf(str, "mcursorstate: %d %d", &x, &y);
370                         }
371                         
372                         if (event) {
373                                 event->setPlaybackCursor(x, y);
374                                 event->setPlaybackModifierKeys(modkeys);
375                                 pushEvent(event);
376                         }
377                 }
378                 
379                 if (getNumEvents()) {
380                         handled = true;
381                         while (getNumEvents()) {
382                                 event = m_events[m_events.size()-1];
383                                 //event->geTime() stores delay between last event and this one
384                                 if (event->getType() == 0 || sys->getMilliSeconds()-m_lasttime < event->getTime()) {
385                                         handled = false;
386                                         
387                                         if (event->getType() == 0) 
388                                                 popEvent();             
389                                         break;
390                                 }
391                                 
392                                 //change event->time from delay-since-last-event to 
393                                 //current system timevoid
394                                 m_lasttime = sys->getMilliSeconds();
395                                 event->setTime(m_lasttime);
396                                 
397                                 event->getPlaybackModifierKeys(m_playmods);
398                                 event->getPlaybackCursor(m_x, m_y);
399                                 
400                                 if (!dispatchEvent()) {
401                                         handled = false;
402                                 }
403                         }
404                 } else {
405                         handled = false;
406                         m_playfile = NULL;
407                 }
408         } else {        
409                 if (getNumEvents()) {
410                         handled = true;
411                         while (getNumEvents()) {
412                                 if (!dispatchEvent()) {
413                                         handled = false;
414                                 }
415                         }
416                 }
417                 else {
418                         handled = false;
419                 }
420         }
421         
422         return handled;
423 }
424
425
426 GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer)
427 {
428         GHOST_TSuccess success;
429         GHOST_ASSERT(consumer, "invalid consumer");
430         
431         // Check to see whether the consumer is already in our list
432         TConsumerVector::const_iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
433
434         if (iter == m_consumers.end()) {
435                 // Add the consumer
436                 m_consumers.push_back(consumer);
437                 success = GHOST_kSuccess;
438         }
439         else {
440                 success = GHOST_kFailure;
441         }
442         return success;
443 }
444
445
446 GHOST_TSuccess GHOST_EventManager::removeConsumer(GHOST_IEventConsumer* consumer)
447 {
448         GHOST_TSuccess success;
449         GHOST_ASSERT(consumer, "invalid consumer");
450
451         // Check to see whether the consumer is in our list
452         TConsumerVector::iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
453
454         if (iter != m_consumers.end()) {
455                 // Remove the consumer
456                 m_consumers.erase(iter);
457                 success = GHOST_kSuccess;
458         }
459         else {
460                 success = GHOST_kFailure;
461         }
462         return success;
463 }
464
465
466 void GHOST_EventManager::removeWindowEvents(GHOST_IWindow* window)
467 {
468         TEventStack::iterator iter;
469         iter = m_events.begin();
470         while (iter != m_events.end())
471         {
472                 GHOST_IEvent* event = *iter;
473                 if (event->getWindow() == window)
474                 {
475             GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n");
476                         /*
477                          * Found an event for this window, remove it.
478                          * The iterator will become invalid.
479                          */
480                         delete event;
481                         m_events.erase(iter);
482                         iter = m_events.begin();
483                 }
484                 else
485                 {
486                         iter++;
487                 }
488         }
489 }
490
491 void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* window)
492 {
493         TEventStack::iterator iter;
494         iter = m_events.begin();
495         while (iter != m_events.end())
496         {
497                 GHOST_IEvent* event = *iter;
498                 if ((event->getType() == type) && (!window || (event->getWindow() == window)))
499                 {
500             GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n");
501                         /*
502                          * Found an event of this type for the window, remove it.
503                          * The iterator will become invalid.
504                          */
505                         delete event;
506                         m_events.erase(iter);
507                         iter = m_events.begin();
508                 }
509                 else
510                 {
511                         iter++;
512                 }
513         }
514 }
515
516
517 GHOST_IEvent* GHOST_EventManager::popEvent()
518 {
519         GHOST_IEvent* event = peekEvent();
520         if (event) {
521                 m_events.pop_back();
522         }
523         return event;
524 }
525
526
527 void GHOST_EventManager::disposeEvents()
528 {
529         while (m_events.size() > 0) {
530                 GHOST_ASSERT(m_events[0], "invalid event");
531                 delete m_events[0];
532                 m_events.pop_front();
533         }
534 }