Merged changes in the trunk up to revision 55357.
[blender.git] / intern / ghost / intern / GHOST_System.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_System.cpp
29  *  \ingroup GHOST
30  *  \author     Maarten Gribnau
31  *  \date       May 7, 2001
32  */
33
34 #include "GHOST_System.h"
35
36 #include <time.h>
37 #include <stdio.h> /* just for printf */
38
39 #include "GHOST_DisplayManager.h"
40 #include "GHOST_EventManager.h"
41 #include "GHOST_NDOFManager.h"
42 #include "GHOST_TimerTask.h"
43 #include "GHOST_TimerManager.h"
44 #include "GHOST_WindowManager.h"
45
46
47 GHOST_System::GHOST_System()
48         : m_nativePixel(false),
49         m_displayManager(NULL),
50         m_timerManager(NULL),
51         m_windowManager(NULL),
52         m_eventManager(NULL)
53 #ifdef WITH_INPUT_NDOF
54         , m_ndofManager(0)
55 #endif
56 {
57 }
58
59
60 GHOST_System::~GHOST_System()
61 {
62         exit();
63 }
64
65
66 GHOST_TUns64 GHOST_System::getMilliSeconds() const
67 {
68         GHOST_TUns64 millis = ::clock();
69         if (CLOCKS_PER_SEC != 1000) {
70                 millis *= 1000;
71                 millis /= CLOCKS_PER_SEC;
72         }
73         return millis;
74 }
75
76
77 GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay,
78                                              GHOST_TUns64 interval,
79                                              GHOST_TimerProcPtr timerProc,
80                                              GHOST_TUserDataPtr userData)
81 {
82         GHOST_TUns64 millis = getMilliSeconds();
83         GHOST_TimerTask *timer = new GHOST_TimerTask(millis + delay, interval, timerProc, userData);
84         if (timer) {
85                 if (m_timerManager->addTimer(timer) == GHOST_kSuccess) {
86                         // Check to see whether we need to fire the timer right away
87                         m_timerManager->fireTimers(millis);
88                 }
89                 else {
90                         delete timer;
91                         timer = 0;
92                 }
93         }
94         return timer;
95 }
96
97
98 GHOST_TSuccess GHOST_System::removeTimer(GHOST_ITimerTask *timerTask)
99 {
100         GHOST_TSuccess success = GHOST_kFailure;
101         if (timerTask) {
102                 success = m_timerManager->removeTimer((GHOST_TimerTask *)timerTask);
103         }
104         return success;
105 }
106
107
108 GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow *window)
109 {
110         GHOST_TSuccess success;
111
112         /*
113          * Remove all pending events for the window.
114          */ 
115         if (m_windowManager->getWindowFound(window)) {
116                 m_eventManager->removeWindowEvents(window);
117         }
118         if (window == m_windowManager->getFullScreenWindow()) {
119                 success = endFullScreen();
120         }
121         else {
122                 if (m_windowManager->getWindowFound(window)) {
123                         success = m_windowManager->removeWindow(window);
124                         if (success) {
125                                 delete window;
126                         }
127                 }
128                 else {
129                         success = GHOST_kFailure;
130                 }
131         }
132         return success;
133 }
134
135
136 bool GHOST_System::validWindow(GHOST_IWindow *window)
137 {
138         return m_windowManager->getWindowFound(window);
139 }
140
141
142 GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
143                                              const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
144 {
145         GHOST_TSuccess success = GHOST_kFailure;
146         GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager");
147         if (m_displayManager) {
148                 if (!m_windowManager->getFullScreen()) {
149                         m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
150
151                         //GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n");
152                         success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
153                         if (success == GHOST_kSuccess) {
154                                 //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
155                                 success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual, numOfAASamples);
156                                 if (success == GHOST_kSuccess) {
157                                         m_windowManager->beginFullScreen(*window, stereoVisual);
158                                 }
159                                 else {
160                                         m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
161                                 }
162                         }
163                 }
164         }
165         if (success == GHOST_kFailure) {
166                 GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n");
167         }
168         return success;
169 }
170
171
172 GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window)
173 {
174         GHOST_TSuccess success = GHOST_kFailure;
175         GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
176         if (m_displayManager) {
177                 if (m_windowManager->getFullScreen()) {
178                         success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
179                 }
180         }
181
182         return success;
183 }
184
185 GHOST_TSuccess GHOST_System::endFullScreen(void)
186 {
187         GHOST_TSuccess success = GHOST_kFailure;
188         GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager");
189         if (m_windowManager->getFullScreen()) {
190                 //GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
191                 //GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n");
192                 success = m_windowManager->endFullScreen();
193                 GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager");
194                 //GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n");
195                 success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
196         }
197         else {
198                 success = GHOST_kFailure;
199         }
200         return success;
201 }
202
203
204 bool GHOST_System::getFullScreen(void)
205 {
206         bool fullScreen;
207         if (m_windowManager) {
208                 fullScreen = m_windowManager->getFullScreen();
209         }
210         else {
211                 fullScreen = false;
212         }
213         return fullScreen;
214 }
215
216
217 bool GHOST_System::dispatchEvents()
218 {
219         bool handled = false;
220
221 #ifdef WITH_INPUT_NDOF
222         // NDOF Motion event is sent only once per dispatch, so do it now:
223         if (m_ndofManager) {
224                 handled |= m_ndofManager->sendMotionEvent();
225         }
226 #endif
227
228         if (m_eventManager) {
229                 handled |= m_eventManager->dispatchEvents();
230         }
231
232         m_timerManager->fireTimers(getMilliSeconds());
233         return handled;
234 }
235
236
237 GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer *consumer)
238 {
239         GHOST_TSuccess success;
240         if (m_eventManager) {
241                 success = m_eventManager->addConsumer(consumer);
242         }
243         else {
244                 success = GHOST_kFailure;
245         }
246         return success;
247 }
248
249 GHOST_TSuccess GHOST_System::removeEventConsumer(GHOST_IEventConsumer *consumer)
250 {
251         GHOST_TSuccess success;
252         if (m_eventManager) {
253                 success = m_eventManager->removeConsumer(consumer);
254         }
255         else {
256                 success = GHOST_kFailure;
257         }
258         return success;
259 }
260
261 GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent *event)
262 {
263         GHOST_TSuccess success;
264         if (m_eventManager) {
265                 success = m_eventManager->pushEvent(event);
266         }
267         else {
268                 success = GHOST_kFailure;
269         }
270         return success;
271 }
272
273 GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
274 {
275         GHOST_ModifierKeys keys;
276         // Get the state of all modifier keys 
277         GHOST_TSuccess success = getModifierKeys(keys);
278         if (success) {
279                 // Isolate the state of the key requested
280                 isDown = keys.get(mask);
281         }
282         return success;
283 }
284
285
286 GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const
287 {
288         GHOST_Buttons buttons;
289         // Get the state of all mouse buttons
290         GHOST_TSuccess success = getButtons(buttons);
291         if (success) {
292                 // Isolate the state of the mouse button requested
293                 isDown = buttons.get(mask);
294         }
295         return success;
296 }
297
298 GHOST_TSuccess GHOST_System::init()
299 {
300         m_timerManager = new GHOST_TimerManager();
301         m_windowManager = new GHOST_WindowManager();
302         m_eventManager = new GHOST_EventManager();
303         
304 #ifdef GHOST_DEBUG
305         if (m_eventManager) {
306                 m_eventPrinter = new GHOST_EventPrinter();
307                 m_eventManager->addConsumer(m_eventPrinter);
308         }
309 #endif // GHOST_DEBUG
310
311         if (m_timerManager && m_windowManager && m_eventManager) {
312                 return GHOST_kSuccess;
313         }
314         else {
315                 return GHOST_kFailure;
316         }
317 }
318
319
320 GHOST_TSuccess GHOST_System::exit()
321 {
322         if (getFullScreen()) {
323                 endFullScreen();
324         }
325         if (m_displayManager) {
326                 delete m_displayManager;
327                 m_displayManager = NULL;
328         }
329         if (m_windowManager) {
330                 delete m_windowManager;
331                 m_windowManager = NULL;
332         }
333         if (m_timerManager) {
334                 delete m_timerManager;
335                 m_timerManager = NULL;
336         }
337         if (m_eventManager) {
338                 delete m_eventManager;
339                 m_eventManager = NULL;
340         }
341 #ifdef WITH_INPUT_NDOF
342         if (m_ndofManager) {
343                 delete m_ndofManager;
344                 m_ndofManager = 0;
345         }
346 #endif
347         return GHOST_kSuccess;
348 }
349
350 GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
351                                                     const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
352 {
353         /* note: don't use getCurrentDisplaySetting() because on X11 we may
354          * be zoomed in and the desktop may be bigger then the viewport. */
355         GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
356         //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
357         *window = (GHOST_Window *)createWindow(
358             STR_String(""),
359             0, 0, settings.xPixels, settings.yPixels,
360             GHOST_kWindowStateNormal,
361             GHOST_kDrawingContextTypeOpenGL,
362             stereoVisual,
363             true,  /* exclusive */
364             numOfAASamples);
365         return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
366 }
367
368
369 int GHOST_System::confirmQuit(GHOST_IWindow *window) const
370 {
371         return 1;
372 }
373
374 bool GHOST_System::useNativePixel(void)
375 {
376         m_nativePixel = true;
377         return 1;
378 }
379