639ce451d2383315141354f09d2595213e1227b8
[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 = NULL;
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 void GHOST_System::dispatchEvents()
218 {
219 #ifdef WITH_INPUT_NDOF
220         // NDOF Motion event is sent only once per dispatch, so do it now:
221         if (m_ndofManager) {
222                 m_ndofManager->sendMotionEvent();
223         }
224 #endif
225
226         if (m_eventManager) {
227                 m_eventManager->dispatchEvents();
228         }
229
230         m_timerManager->fireTimers(getMilliSeconds());
231 }
232
233
234 GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer *consumer)
235 {
236         GHOST_TSuccess success;
237         if (m_eventManager) {
238                 success = m_eventManager->addConsumer(consumer);
239         }
240         else {
241                 success = GHOST_kFailure;
242         }
243         return success;
244 }
245
246 GHOST_TSuccess GHOST_System::removeEventConsumer(GHOST_IEventConsumer *consumer)
247 {
248         GHOST_TSuccess success;
249         if (m_eventManager) {
250                 success = m_eventManager->removeConsumer(consumer);
251         }
252         else {
253                 success = GHOST_kFailure;
254         }
255         return success;
256 }
257
258 GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent *event)
259 {
260         GHOST_TSuccess success;
261         if (m_eventManager) {
262                 success = m_eventManager->pushEvent(event);
263         }
264         else {
265                 success = GHOST_kFailure;
266         }
267         return success;
268 }
269
270 GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
271 {
272         GHOST_ModifierKeys keys;
273         // Get the state of all modifier keys 
274         GHOST_TSuccess success = getModifierKeys(keys);
275         if (success) {
276                 // Isolate the state of the key requested
277                 isDown = keys.get(mask);
278         }
279         return success;
280 }
281
282
283 GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const
284 {
285         GHOST_Buttons buttons;
286         // Get the state of all mouse buttons
287         GHOST_TSuccess success = getButtons(buttons);
288         if (success) {
289                 // Isolate the state of the mouse button requested
290                 isDown = buttons.get(mask);
291         }
292         return success;
293 }
294
295 void GHOST_System::setNDOFDeadZone(float deadzone)
296 {
297 #ifdef WITH_INPUT_NDOF
298         this->m_ndofManager->setDeadZone(deadzone);
299 #else
300         (void)deadzone;
301 #endif
302 }
303
304 GHOST_TSuccess GHOST_System::init()
305 {
306         m_timerManager = new GHOST_TimerManager();
307         m_windowManager = new GHOST_WindowManager();
308         m_eventManager = new GHOST_EventManager();
309         
310 #ifdef GHOST_DEBUG
311         if (m_eventManager) {
312                 m_eventPrinter = new GHOST_EventPrinter();
313                 m_eventManager->addConsumer(m_eventPrinter);
314         }
315 #endif // GHOST_DEBUG
316
317         if (m_timerManager && m_windowManager && m_eventManager) {
318                 return GHOST_kSuccess;
319         }
320         else {
321                 return GHOST_kFailure;
322         }
323 }
324
325
326 GHOST_TSuccess GHOST_System::exit()
327 {
328         if (getFullScreen()) {
329                 endFullScreen();
330         }
331
332         delete m_displayManager;
333         m_displayManager = NULL;
334
335         delete m_windowManager;
336         m_windowManager = NULL;
337
338         delete m_timerManager;
339         m_timerManager = NULL;
340
341         delete m_eventManager;
342         m_eventManager = NULL;
343
344 #ifdef WITH_INPUT_NDOF
345         delete m_ndofManager;
346         m_ndofManager = NULL;
347 #endif
348         return GHOST_kSuccess;
349 }
350
351 GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
352                                                     const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
353 {
354         GHOST_GLSettings glSettings = {0};
355
356         if (stereoVisual)
357                 glSettings.flags |= GHOST_glStereoVisual;
358         glSettings.numOfAASamples = numOfAASamples;
359
360         /* note: don't use getCurrentDisplaySetting() because on X11 we may
361          * be zoomed in and the desktop may be bigger then the viewport. */
362         GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
363         //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
364         *window = (GHOST_Window *)createWindow(
365             STR_String(""),
366             0, 0, settings.xPixels, settings.yPixels,
367             GHOST_kWindowStateNormal,
368             GHOST_kDrawingContextTypeOpenGL,
369             glSettings,
370             true  /* exclusive */);
371         return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
372 }
373
374
375 int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const
376 {
377         return 1;
378 }
379
380 bool GHOST_System::useNativePixel(void)
381 {
382         m_nativePixel = true;
383         return 1;
384 }
385