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