Blender V4.3
GHOST_System.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "GHOST_System.hh"
10
11#include <chrono>
12#include <cstdio> /* Just for #printf. */
13
15#include "GHOST_EventManager.hh"
16#include "GHOST_TimerManager.hh"
17#include "GHOST_TimerTask.hh"
19
20#ifdef WITH_INPUT_NDOF
21# include "GHOST_NDOFManager.hh"
22#endif
23
25 : m_nativePixel(false),
26 m_windowFocus(true),
27 m_autoFocus(true),
28 m_displayManager(nullptr),
29 m_timerManager(nullptr),
30 m_windowManager(nullptr),
31 m_eventManager(nullptr),
32#ifdef WITH_INPUT_NDOF
33 m_ndofManager(nullptr),
34#endif
35 m_preFullScreenSetting{0},
36 m_multitouchGestures(true),
37 m_tabletAPI(GHOST_kTabletAutomatic),
38 m_is_debug_enabled(false)
39{
40}
41
46
51
52uint *GHOST_System::getClipboardImage(int * /*r_width*/, int * /*r_height*/) const
53{
54 return nullptr;
55}
56
58 int /*width*/,
59 int /*height*/) const
60{
61 return GHOST_kFailure;
62}
63
65 uint64_t interval,
66 GHOST_TimerProcPtr timerProc,
67 GHOST_TUserDataPtr userData)
68{
69 uint64_t millis = getMilliSeconds();
70 GHOST_TimerTask *timer = new GHOST_TimerTask(millis + delay, interval, timerProc, userData);
71 if (timer) {
73 /* Check to see whether we need to fire the timer right away. */
75 }
76 else {
77 delete timer;
78 timer = nullptr;
79 }
80 }
81 return timer;
82}
83
85{
87 if (timerTask) {
88 success = m_timerManager->removeTimer((GHOST_TimerTask *)timerTask);
89 }
90 return success;
91}
92
94{
95 GHOST_TSuccess success;
96
97 /*
98 * Remove all pending events for the window.
99 */
100 if (m_windowManager->getWindowFound(window)) {
102 }
103 if (window == m_windowManager->getFullScreenWindow()) {
104 success = endFullScreen();
105 }
106 else {
107 if (m_windowManager->getWindowFound(window)) {
108 success = m_windowManager->removeWindow(window);
109 if (success) {
110 delete window;
111 }
112 }
113 else {
114 success = GHOST_kFailure;
115 }
116 }
117 return success;
118}
119
121{
122 return m_windowManager->getWindowFound(window);
123}
124
126 GHOST_IWindow **window,
127 const bool stereoVisual)
128{
130 GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager");
131 if (m_displayManager) {
135
136 // GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n");
138 setting);
139 if (success == GHOST_kSuccess) {
140 // GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
141 success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual);
142 if (success == GHOST_kSuccess) {
143 m_windowManager->beginFullScreen(*window, stereoVisual);
144 }
145 else {
148 }
149 }
150 }
151 }
152 if (success == GHOST_kFailure) {
153 GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n");
154 }
155 return success;
156}
157
159 GHOST_IWindow ** /*window*/)
160{
162 GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
163 if (m_displayManager) {
166 setting);
167 }
168 }
169
170 return success;
171}
172
174{
176 GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager");
178 // GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
179 // GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n");
181 GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager");
182 // GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n");
185 }
186 }
187 return success;
188}
189
191{
192 bool fullScreen;
193 if (m_windowManager) {
194 fullScreen = m_windowManager->getFullScreen();
195 }
196 else {
197 fullScreen = false;
198 }
199 return fullScreen;
200}
201
203{
204 /* TODO: This solution should follow the order of the activated windows (Z-order).
205 * It is imperfect but usable in most cases. Ideally each platform should provide
206 * a custom version of this function that properly considers z-order. */
207
208 std::vector<GHOST_IWindow *> windows = m_windowManager->getWindows();
209 std::vector<GHOST_IWindow *>::reverse_iterator iwindow_iter;
210
211 /* Search through the windows in reverse order because in most cases
212 * the window that is on top was created after those that are below it. */
213
214 for (iwindow_iter = windows.rbegin(); iwindow_iter != windows.rend(); ++iwindow_iter) {
215
216 GHOST_IWindow *win = *iwindow_iter;
217
219 continue;
220 }
221
224 if (bounds.isInside(x, y)) {
225 return win;
226 }
227 }
228
229 return nullptr;
230}
231
233{
234#ifdef WITH_INPUT_NDOF
235 /* NDOF Motion event is sent only once per dispatch, so do it now: */
236 if (m_ndofManager) {
237 m_ndofManager->sendMotionEvent();
238 }
239#endif
240
241 if (m_eventManager) {
243 }
244
246}
247
249{
250 GHOST_TSuccess success;
251 if (m_eventManager) {
252 success = m_eventManager->addConsumer(consumer);
253 }
254 else {
255 success = GHOST_kFailure;
256 }
257 return success;
258}
259
261{
262 GHOST_TSuccess success;
263 if (m_eventManager) {
264 success = m_eventManager->removeConsumer(consumer);
265 }
266 else {
267 success = GHOST_kFailure;
268 }
269 return success;
270}
271
273{
274 GHOST_TSuccess success;
275 if (m_eventManager) {
276 success = m_eventManager->pushEvent(event);
277 }
278 else {
279 success = GHOST_kFailure;
280 }
281 return success;
282}
283
285 int32_t &x,
286 int32_t &y) const
287{
288 /* Sub-classes that can implement this directly should do so. */
289 int32_t screen_x, screen_y;
290 GHOST_TSuccess success = getCursorPosition(screen_x, screen_y);
291 if (success == GHOST_kSuccess) {
292 window->screenToClient(screen_x, screen_y, x, y);
293 }
294 return success;
295}
296
298 int32_t x,
299 int32_t y)
300{
301 /* Sub-classes that can implement this directly should do so. */
302 int32_t screen_x, screen_y;
303 window->clientToScreen(x, y, screen_x, screen_y);
304 return setCursorPosition(screen_x, screen_y);
305}
306
308{
310 /* Get the state of all modifier keys. */
311 GHOST_TSuccess success = getModifierKeys(keys);
312 if (success) {
313 /* Isolate the state of the key requested. */
314 isDown = keys.get(mask);
315 }
316 return success;
317}
318
320{
321 GHOST_Buttons buttons;
322 /* Get the state of all mouse buttons. */
323 GHOST_TSuccess success = getButtons(buttons);
324 if (success) {
325 /* Isolate the state of the mouse button requested. */
326 isDown = buttons.get(mask);
327 }
328 return success;
329}
330
332{
334}
335
340
345
347{
348 return GHOST_kFailure;
349}
350
351#ifdef WITH_INPUT_NDOF
352void GHOST_System::setNDOFDeadZone(float deadzone)
353{
354 if (this->m_ndofManager) {
355 this->m_ndofManager->setDeadZone(deadzone);
356 }
357}
358#endif
359
361{
365
366#ifdef WITH_GHOST_DEBUG
367 if (m_eventManager) {
368 m_eventPrinter = new GHOST_EventPrinter();
369 m_eventManager->addConsumer(m_eventPrinter);
370 }
371#endif /* WITH_GHOST_DEBUG */
372
374 return GHOST_kSuccess;
375 }
376 return GHOST_kFailure;
377}
378
380{
381 if (getFullScreen()) {
383 }
384
385 delete m_displayManager;
386 m_displayManager = nullptr;
387
388 delete m_windowManager;
389 m_windowManager = nullptr;
390
391 delete m_timerManager;
392 m_timerManager = nullptr;
393
394 delete m_eventManager;
395 m_eventManager = nullptr;
396
397#ifdef WITH_INPUT_NDOF
398 delete m_ndofManager;
399 m_ndofManager = nullptr;
400#endif
401
402 return GHOST_kSuccess;
403}
404
406 const GHOST_DisplaySetting &settings,
407 const bool stereoVisual)
408{
409 GHOST_GPUSettings gpuSettings = {0};
410
411 if (stereoVisual) {
412 gpuSettings.flags |= GHOST_gpuStereoVisual;
413 }
414#if defined(WITH_OPENGL_BACKEND)
415 gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
416#elif defined(WITH_METAL_BACKEND)
417 gpuSettings.context_type = GHOST_kDrawingContextTypeMetal;
418#elif defined(WITH_VULKAN_BACKEND)
419 gpuSettings.context_type = GHOST_kDrawingContextTypeVulkan;
420#else
421# error
422#endif
423 /* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
424 * be zoomed in and the desktop may be bigger than the viewport. */
426 "GHOST_System::createFullScreenWindow(): invalid display manager");
427 // GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
428 *window = (GHOST_Window *)createWindow("",
429 0,
430 0,
431 settings.xPixels,
432 settings.yPixels,
434 gpuSettings,
435 true /*exclusive*/);
436 return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
437}
438
440{
441 m_nativePixel = true;
442 return true;
443}
444
445void GHOST_System::useWindowFocus(const bool use_focus)
446{
447 m_windowFocus = use_focus;
448}
449
450void GHOST_System::setAutoFocus(const bool auto_focus)
451{
452 m_autoFocus = auto_focus;
453}
454
459
unsigned int uint
#define GHOST_ASSERT(x, info)
#define GHOST_PRINT(x)
@ GHOST_kWindowStateMinimized
@ GHOST_kWindowStateNormal
void * GHOST_TUserDataPtr
Definition GHOST_Types.h:85
@ GHOST_kDebugDefault
void(* GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, uint64_t time)
GHOST_TModifierKey
GHOST_TSuccess
Definition GHOST_Types.h:87
@ GHOST_kFailure
Definition GHOST_Types.h:87
@ GHOST_kSuccess
Definition GHOST_Types.h:87
@ GHOST_gpuStereoVisual
Definition GHOST_Types.h:76
GHOST_TButton
GHOST_TTabletAPI
@ GHOST_kTabletAutomatic
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
virtual GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting)
virtual GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const
GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer)
GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer)
GHOST_TSuccess pushEvent(const GHOST_IEvent *event)
void removeWindowEvents(const GHOST_IWindow *window)
virtual GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const =0
virtual GHOST_IWindow * createWindow(const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_GPUSettings gpuSettings, const bool exclusive=false, const bool is_dialog=false, const GHOST_IWindow *parentWindow=nullptr)=0
virtual uint64_t getMilliSeconds() const =0
virtual GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)=0
virtual void getClientBounds(GHOST_Rect &bounds) const =0
virtual void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const =0
virtual void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const =0
virtual GHOST_TWindowState getState() const =0
virtual GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const =0
GHOST_TTabletAPI getTabletAPI()
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const
GHOST_DisplaySetting m_preFullScreenSetting
GHOST_TSuccess hasClipboardImage() const
void setAutoFocus(const bool auto_focus)
void useWindowFocus(const bool use_focus)
GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window, const bool stereoVisual)
GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask)
virtual bool isDebugEnabled()
virtual ~GHOST_System()
virtual GHOST_TSuccess exit()
bool getFullScreen()
uint * getClipboardImage(int *r_width, int *r_height) const
GHOST_TSuccess getPixelAtCursor(float r_color[3]) const
GHOST_TSuccess pushEvent(const GHOST_IEvent *event)
bool m_multitouchGestures
virtual GHOST_TSuccess init()
virtual void setTabletAPI(GHOST_TTabletAPI api)
bool useNativePixel()
GHOST_TSuccess getButtonState(GHOST_TButton mask, bool &isDown) const
GHOST_TSuccess getModifierKeyState(GHOST_TModifierKey mask, bool &isDown) const
GHOST_TSuccess disposeWindow(GHOST_IWindow *window)
GHOST_IWindow * getWindowUnderCursor(int32_t x, int32_t y)
void setMultitouchGestures(const bool use)
GHOST_TSuccess endFullScreen()
GHOST_WindowManager * m_windowManager
virtual void initDebug(GHOST_Debug debug)
GHOST_TSuccess getCursorPositionClientRelative(const GHOST_IWindow *window, int32_t &x, int32_t &y) const
void dispatchEvents()
bool validWindow(GHOST_IWindow *window)
GHOST_TimerManager * m_timerManager
GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer)
GHOST_TSuccess setCursorPositionClientRelative(GHOST_IWindow *window, int32_t x, int32_t y)
GHOST_DisplayManager * m_displayManager
GHOST_TTabletAPI m_tabletAPI
bool m_is_debug_enabled
GHOST_EventManager * m_eventManager
virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const =0
GHOST_ITimerTask * installTimer(uint64_t delay, uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData=nullptr)
GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings, const bool stereoVisual)
GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window)
GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer)
bool fireTimers(uint64_t time)
GHOST_TSuccess removeTimer(GHOST_TimerTask *timer)
GHOST_TSuccess addTimer(GHOST_TimerTask *timer)
GHOST_TSuccess endFullScreen()
GHOST_TSuccess removeWindow(const GHOST_IWindow *window)
const std::vector< GHOST_IWindow * > & getWindows() const
GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual)
GHOST_IWindow * getFullScreenWindow() const
bool getWindowFound(const GHOST_IWindow *window) const
signed int int32_t
Definition stdint.h:77
unsigned __int64 uint64_t
Definition stdint.h:90
bool get(GHOST_TButton mask) const
GHOST_TDrawingContextType context_type
bool get(GHOST_TModifierKey mask) const
wmTimer * timer