GHOST should now be finally fixed
[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_nativePixelSize(1),
50         m_displayManager(0),
51         m_timerManager(0),
52         m_windowManager(0),
53         m_eventManager(0)
54 #ifdef WITH_INPUT_NDOF
55         , m_ndofManager(0)
56 #endif
57 {
58 }
59
60
61 GHOST_System::~GHOST_System()
62 {
63         exit();
64 }
65
66
67 GHOST_TUns64 GHOST_System::getMilliSeconds() const
68 {
69         GHOST_TUns64 millis = ::clock();
70         if (CLOCKS_PER_SEC != 1000) {
71                 millis *= 1000;
72                 millis /= CLOCKS_PER_SEC;
73         }
74         return millis;
75 }
76
77
78 GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay,
79                                              GHOST_TUns64 interval,
80                                              GHOST_TimerProcPtr timerProc,
81                                              GHOST_TUserDataPtr userData)
82 {
83         GHOST_TUns64 millis = getMilliSeconds();
84         GHOST_TimerTask *timer = new GHOST_TimerTask(millis + delay, interval, timerProc, userData);
85         if (timer) {
86                 if (m_timerManager->addTimer(timer) == GHOST_kSuccess) {
87                         // Check to see whether we need to fire the timer right away
88                         m_timerManager->fireTimers(millis);
89                 }
90                 else {
91                         delete timer;
92                         timer = 0;
93                 }
94         }
95         return timer;
96 }
97
98
99 GHOST_TSuccess GHOST_System::removeTimer(GHOST_ITimerTask *timerTask)
100 {
101         GHOST_TSuccess success = GHOST_kFailure;
102         if (timerTask) {
103                 success = m_timerManager->removeTimer((GHOST_TimerTask *)timerTask);
104         }
105         return success;
106 }
107
108
109 GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow *window)
110 {
111         GHOST_TSuccess success;
112
113         /*
114          * Remove all pending events for the window.
115          */ 
116         if (m_windowManager->getWindowFound(window)) {
117                 m_eventManager->removeWindowEvents(window);
118         }
119         if (window == m_windowManager->getFullScreenWindow()) {
120                 success = endFullScreen();
121         }
122         else {
123                 if (m_windowManager->getWindowFound(window)) {
124                         success = m_windowManager->removeWindow(window);
125                         if (success) {
126                                 delete window;
127                         }
128                 }
129                 else {
130                         success = GHOST_kFailure;
131                 }
132         }
133         return success;
134 }
135
136
137 bool GHOST_System::validWindow(GHOST_IWindow *window)
138 {
139         return m_windowManager->getWindowFound(window);
140 }
141
142
143 GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
144                                              const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
145 {
146         GHOST_TSuccess success = GHOST_kFailure;
147         GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager");
148         if (m_displayManager) {
149                 if (!m_windowManager->getFullScreen()) {
150                         m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
151
152                         //GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n");
153                         success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
154                         if (success == GHOST_kSuccess) {
155                                 //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
156                                 success = createFullScreenWindow((GHOST_Window **)window, stereoVisual, numOfAASamples);
157                                 if (success == GHOST_kSuccess) {
158                                         m_windowManager->beginFullScreen(*window, stereoVisual);
159                                 }
160                                 else {
161                                         m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
162                                 }
163                         }
164                 }
165         }
166         if (success == GHOST_kFailure) {
167                 GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n");
168         }
169         return success;
170 }
171
172
173 GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window)
174 {
175         GHOST_TSuccess success = GHOST_kFailure;
176         GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
177         if (m_displayManager) {
178                 if (m_windowManager->getFullScreen()) {
179                         success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
180                 }
181         }
182
183         return success;
184 }
185
186 GHOST_TSuccess GHOST_System::endFullScreen(void)
187 {
188         GHOST_TSuccess success = GHOST_kFailure;
189         GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager");
190         if (m_windowManager->getFullScreen()) {
191                 //GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
192                 //GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n");
193                 success = m_windowManager->endFullScreen();
194                 GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager");
195                 //GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n");
196                 success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
197         }
198         else {
199                 success = GHOST_kFailure;
200         }
201         return success;
202 }
203
204
205 bool GHOST_System::getFullScreen(void)
206 {
207         bool fullScreen;
208         if (m_windowManager) {
209                 fullScreen = m_windowManager->getFullScreen();
210         }
211         else {
212                 fullScreen = false;
213         }
214         return fullScreen;
215 }
216
217
218 bool GHOST_System::dispatchEvents()
219 {
220         bool handled = false;
221
222 #ifdef WITH_INPUT_NDOF
223         // NDOF Motion event is sent only once per dispatch, so do it now:
224         if (m_ndofManager) {
225                 handled |= m_ndofManager->sendMotionEvent();
226         }
227 #endif
228
229         if (m_eventManager) {
230                 handled |= m_eventManager->dispatchEvents();
231         }
232
233         m_timerManager->fireTimers(getMilliSeconds());
234         return handled;
235 }
236
237
238 GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer *consumer)
239 {
240         GHOST_TSuccess success;
241         if (m_eventManager) {
242                 success = m_eventManager->addConsumer(consumer);
243         }
244         else {
245                 success = GHOST_kFailure;
246         }
247         return success;
248 }
249
250 GHOST_TSuccess GHOST_System::removeEventConsumer(GHOST_IEventConsumer *consumer)
251 {
252         GHOST_TSuccess success;
253         if (m_eventManager) {
254                 success = m_eventManager->removeConsumer(consumer);
255         }
256         else {
257                 success = GHOST_kFailure;
258         }
259         return success;
260 }
261
262 GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent *event)
263 {
264         GHOST_TSuccess success;
265         if (m_eventManager) {
266                 success = m_eventManager->pushEvent(event);
267         }
268         else {
269                 success = GHOST_kFailure;
270         }
271         return success;
272 }
273
274 GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
275 {
276         GHOST_ModifierKeys keys;
277         // Get the state of all modifier keys 
278         GHOST_TSuccess success = getModifierKeys(keys);
279         if (success) {
280                 // Isolate the state of the key requested
281                 isDown = keys.get(mask);
282         }
283         return success;
284 }
285
286
287 GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const
288 {
289         GHOST_Buttons buttons;
290         // Get the state of all mouse buttons
291         GHOST_TSuccess success = getButtons(buttons);
292         if (success) {
293                 // Isolate the state of the mouse button requested
294                 isDown = buttons.get(mask);
295         }
296         return success;
297 }
298
299 GHOST_TSuccess GHOST_System::init()
300 {
301         m_timerManager = new GHOST_TimerManager();
302         m_windowManager = new GHOST_WindowManager();
303         m_eventManager = new GHOST_EventManager();
304         
305 #ifdef GHOST_DEBUG
306         if (m_eventManager) {
307                 m_eventPrinter = new GHOST_EventPrinter();
308                 m_eventManager->addConsumer(m_eventPrinter);
309         }
310 #endif // GHOST_DEBUG
311
312         if (m_timerManager && m_windowManager && m_eventManager) {
313                 return GHOST_kSuccess;
314         }
315         else {
316                 return GHOST_kFailure;
317         }
318 }
319
320
321 GHOST_TSuccess GHOST_System::exit()
322 {
323         if (getFullScreen()) {
324                 endFullScreen();
325         }
326         if (m_displayManager) {
327                 delete m_displayManager;
328                 m_displayManager = 0;
329         }
330         if (m_windowManager) {
331                 delete m_windowManager;
332                 m_windowManager = 0;
333         }
334         if (m_timerManager) {
335                 delete m_timerManager;
336                 m_timerManager = 0;
337         }
338         if (m_eventManager) {
339                 delete m_eventManager;
340                 m_eventManager = 0;
341         }
342 #ifdef WITH_INPUT_NDOF
343         if (m_ndofManager) {
344                 delete m_ndofManager;
345                 m_ndofManager = 0;
346         }
347 #endif
348         return GHOST_kSuccess;
349 }
350
351
352 GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
353 {
354         GHOST_TSuccess success;
355         GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
356         GHOST_DisplaySetting settings;
357
358         success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings);
359         if (success) {
360                 //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
361                 *window = (GHOST_Window *)createWindow(
362                     STR_String(""),
363                     0, 0, settings.xPixels, settings.yPixels,
364                     GHOST_kWindowStateFullScreen,
365                     GHOST_kDrawingContextTypeOpenGL,
366                     stereoVisual,
367                     numOfAASamples);
368                 success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
369         }
370         return success;
371 }
372
373
374 int GHOST_System::confirmQuit(GHOST_IWindow *window) const
375 {
376         return 1;
377 }
378
379 bool GHOST_System::useNativePixel(void)
380 {
381         m_nativePixel = true;
382         return 1;
383 }
384
385 float GHOST_System::getNativePixelSize(void)
386 {
387         if (m_nativePixel)
388                 return m_nativePixelSize;
389         return 1.0f;
390 }