Skip to content

Instantly share code, notes, and snippets.

@Kielan
Last active November 16, 2022 12:12
Show Gist options
  • Save Kielan/589804d743d5bbe9c37d7230d7406d84 to your computer and use it in GitHub Desktop.
Save Kielan/589804d743d5bbe9c37d7230d7406d84 to your computer and use it in GitHub Desktop.
GHOST api for OpenGL to window manager api system. Currently in cpp prepping for migration
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
}

GHOSTPage GHOST

\section intro Introduction

GHOST is yet another acronym. It stands for "Generic Handy Operating System Toolkit". It has been created to replace the OpenGL utility tool kit GLUT. GLUT was used in Blender until the point that Blender needed to be ported to Apple's Mac OSX. Blender needed a number of modifications in GLUT to work but the GLUT sources for OSX were unavailable at the time. The decision was made to build our own replacement for GLUT. In those days, NaN Technologies BV was the company that developed Blender.

Enough history. What does GHOST have to offer?
In short: everything that Blender needed from GLUT to run on all its supported operating systems and some extra's. This includes :

  • Time(r) management.
  • Display/window management (windows are only created on the main display).
  • Event management.
  • Cursor shape management (no custom cursors for now).
  • Access to the state of the mouse buttons and the keyboard.
  • Menus for windows with events generated when they are accessed (this is work in progress).
  • Video mode switching.
  • Copy/Paste buffers.
  • System paths.

Font management has been moved to a separate library.

\section platforms Platforms

GHOST supports the following platforms:

  • OSX Cocoa.
  • Windows.
  • X11.
  • SDL2 (experimental).
  • NULL (headless mode).

\section Building GHOST

GHOST is not build standalone however there are tests in intern/ghost/test

\section interface Interface GHOST has two programming interfaces:

  • The C-API. For programs written in C.
  • The C++-API. For programs written in C++.

GHOST itself is written in C++ and the C-API is a wrapper around the C++ API.

\subsection cplusplus_api The C++ API consists of the following files:

  • GHOST_IEvent.h
  • GHOST_IEventConsumer.h
  • GHOST_ISystem.h
  • GHOST_ITimerTask.h
  • GHOST_IWindow.h
  • GHOST_Rect.h
  • GHOST_Types.h

For an example of using the C++-API, have a look at the GHOST_C-Test.cpp program in the ?/ghost/test/gears/ directory.

\subsection c_api The C-API To use GHOST in programs written in C, include the file GHOST_C-API.h in your program. This file includes the GHOST_Types.h file for all GHOST types and defines functions that give you access to the same functionality present in the C++ API.
For an example of using the C-API, have a look at the GHOST_C-Test.c program in the ?/ghost/test/gears/ directory.

\section work Work in progress \todo write WIP section

\interface GHOST_ISystem Interface for classes that provide access to the operating system. There should be only one system class in an application. Therefore, the routines to create and dispose the system are static. Provides: -# Time(r) management. -# Display/window management (windows are only created on the main display). -# Event management. -# Cursor shape management (no custom cursors for now). -# Access to the state of the mouse buttons and the keyboard. -# Menus for windows with events generated when they are accessed (this is work in progress).

/*
* Macro's used in GHOST debug target.
*/
#pragma once
#ifdef _MSC_VER
# ifdef DEBUG
/* Suppress STL-MSVC debug info warning. */
# pragma warning(disable : 4786)
# endif
#endif
#include <iostream>
#include <stdio.h> /* For `printf()`. */
#if defined(WITH_GHOST_DEBUG)
# define GHOST_PRINT(x) \
{ \
std::cout << x; \
} \
((void)0)
# define GHOST_PRINTF(x, ...) \
{ \
printf(x, __VA_ARGS__); \
} \
((void)0)
#else
/* Expand even when `WITH_GHOST_DEBUG` is disabled to prevent expressions
* becoming invalid even when the option is disable. */
# define GHOST_PRINT(x) \
{ \
if (false) { \
std::cout << x; \
} \
} \
((void)0)
# define GHOST_PRINTF(x, ...) \
{ \
if (false) { \
printf(x, __VA_ARGS__); \
} \
} \
((void)0)
#endif /* `!defined(WITH_GHOST_DEBUG)` */
#ifdef WITH_ASSERT_ABORT
# include <stdlib.h> //for abort()
# define GHOST_ASSERT(x, info) \
{ \
if (!(x)) { \
fprintf(stderr, "GHOST_ASSERT failed: "); \
fprintf(stderr, info); \
fprintf(stderr, "\n"); \
abort(); \
} \
} \
((void)0)
/* Assert in non-release builds too. */
#elif defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))
# define GHOST_ASSERT(x, info) \
{ \
if (!(x)) { \
GHOST_PRINT("GHOST_ASSERT failed: "); \
GHOST_PRINT(info); \
GHOST_PRINT("\n"); \
} \
} \
((void)0)
#else /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */
# define GHOST_ASSERT(x, info) ((void)0)
#endif /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */
/*
* Declaration of GHOST_IContext interface class.
*/
#pragma once
#include "GHOST_Types.h"
/**
* Interface for GHOST context.
*
* You can create a off-screen context (windowless) with the system's
* #GHOST_ISystem::createOffscreenContext method.
* \see GHOST_ISystem#createOffscreenContext
*/
class GHOST_IContext {
public:
/**
* Destructor.
*/
virtual ~GHOST_IContext()
{
}
/**
* Activates the drawing context.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess activateDrawingContext() = 0;
/**
* Release the drawing context of the calling thread.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess releaseDrawingContext() = 0;
virtual unsigned int getDefaultFramebuffer() = 0;
virtual GHOST_TSuccess swapBuffers() = 0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
#endif
};
#include <stdexcept>
#include "GHOST_ISystem.h"
#include "GHOST_SystemHeadless.h"
#if defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
# include "GHOST_SystemWayland.h"
# include "GHOST_SystemX11.h"
#elif defined(WITH_GHOST_X11)
# include "GHOST_SystemX11.h"
#elif defined(WITH_GHOST_WAYLAND)
# include "GHOST_SystemWayland.h"
#elif defined(WITH_GHOST_SDL)
# include "GHOST_SystemSDL.h"
#elif defined(WIN32)
# include "GHOST_SystemWin32.h"
#elif defined(__APPLE__)
# include "GHOST_SystemCocoa.h"
#endif
GHOST_ISystem *GHOST_ISystem::m_system = nullptr;
const char *GHOST_ISystem::m_system_backend_id = nullptr;
GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr;
GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose, [[maybe_unused]] bool background)
{
/* When GHOST fails to start, report the back-ends that were attempted.
* A Verbose argument could be supported in printing isn't always desired. */
const char *backends_attempted[8] = {nullptr};
int backends_attempted_num = 0;
GHOST_TSuccess success;
if (!m_system) {
#if defined(WITH_HEADLESS)
/* Pass. */
#elif defined(WITH_GHOST_WAYLAND)
# if defined(WITH_GHOST_WAYLAND_DYNLOAD)
const bool has_wayland_libraries = ghost_wl_dynload_libraries_init();
# else
const bool has_wayland_libraries = true;
# endif
#endif
#if defined(WITH_HEADLESS)
/* Pass. */
#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
/* Special case, try Wayland, fall back to X11. */
if (has_wayland_libraries) {
backends_attempted[backends_attempted_num++] = "WAYLAND";
try {
m_system = new GHOST_SystemWayland(background);
}
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
ghost_wl_dynload_libraries_exit();
# endif
}
}
else {
m_system = nullptr;
}
if (!m_system) {
/* Try to fallback to X11. */
backends_attempted[backends_attempted_num++] = "X11";
try {
m_system = new GHOST_SystemX11();
}
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
}
}
#elif defined(WITH_GHOST_X11)
backends_attempted[backends_attempted_num++] = "X11";
try {
m_system = new GHOST_SystemX11();
}
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
}
#elif defined(WITH_GHOST_WAYLAND)
if (has_wayland_libraries) {
backends_attempted[backends_attempted_num++] = "WAYLAND";
try {
m_system = new GHOST_SystemWayland(background);
}
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
ghost_wl_dynload_libraries_exit();
# endif
}
}
else {
m_system = nullptr;
}
#elif defined(WITH_GHOST_SDL)
backends_attempted[backends_attempted_num++] = "SDL";
try {
m_system = new GHOST_SystemSDL();
}
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
}
#elif defined(WIN32)
backends_attempted[backends_attempted_num++] = "WIN32";
m_system = new GHOST_SystemWin32();
#elif defined(__APPLE__)
backends_attempted[backends_attempted_num++] = "COCOA";
m_system = new GHOST_SystemCocoa();
#endif
if (m_system) {
m_system_backend_id = backends_attempted[backends_attempted_num - 1];
}
else if (verbose) {
fprintf(stderr, "GHOST: failed to initialize display for back-end(s): [");
for (int i = 0; i < backends_attempted_num; i++) {
if (i != 0) {
fprintf(stderr, ", ");
}
fprintf(stderr, "'%s'", backends_attempted[i]);
}
fprintf(stderr, "]\n");
}
success = m_system != nullptr ? GHOST_kSuccess : GHOST_kFailure;
}
else {
success = GHOST_kFailure;
}
if (success) {
success = m_system->init();
}
return success;
}
GHOST_TSuccess GHOST_ISystem::createSystemBackground()
{
GHOST_TSuccess success;
if (!m_system) {
#if !defined(WITH_HEADLESS)
/* Try to create a off-screen render surface with the graphical systems. */
success = createSystem(false, true);
if (success) {
return success;
}
/* Try to fallback to headless mode if all else fails. */
#endif
m_system = new GHOST_SystemHeadless();
success = m_system != nullptr ? GHOST_kSuccess : GHOST_kFailure;
}
else {
success = GHOST_kFailure;
}
if (success) {
success = m_system->init();
}
return success;
}
GHOST_TSuccess GHOST_ISystem::disposeSystem()
{
GHOST_TSuccess success = GHOST_kSuccess;
if (m_system) {
delete m_system;
m_system = nullptr;
}
else {
success = GHOST_kFailure;
}
return success;
}
GHOST_ISystem *GHOST_ISystem::getSystem()
{
return m_system;
}
const char *GHOST_ISystem::getSystemBackend()
{
return m_system_backend_id;
}
GHOST_TBacktraceFn GHOST_ISystem::getBacktraceFn()
{
return GHOST_ISystem::m_backtrace_fn;
}
void GHOST_ISystem::setBacktraceFn(GHOST_TBacktraceFn backtrace_fn)
{
GHOST_ISystem::m_backtrace_fn = backtrace_fn;
}
#pragma once
#include <stdlib.h>
#include "GHOST_IContext.h"
#include "GHOST_ITimerTask.h"
#include "GHOST_IWindow.h"
#include "GHOST_Types.h"
class GHOST_IEventConsumer;
class GHOST_ISystem {
public:
/**
* Creates the one and only system.
* \param verbose: report back-ends that were attempted no back-end could be loaded.
* \param background: loading the system for background rendering (no visible windows).
* \return An indication of success.
*/
static GHOST_TSuccess createSystem(bool verbose, bool background);
static GHOST_TSuccess createSystemBackground();
/**
* Disposes the one and only system.
* \return An indication of success.
*/
static GHOST_TSuccess disposeSystem();
/**
* Returns a pointer to the one and only system (nil if it hasn't been created).
* \return A pointer to the system.
*/
static GHOST_ISystem *getSystem();
/**
* Return an identifier for the one and only system.
* \warning while it may be tempting this should never be used to check for supported features,
* in that case, the GHOST API should be extended to query capabilities.
* This is needed for X11/WAYLAND on Unix, without this - there is no convenient way for users to
* check if WAYLAND or XWAYLAND are in use since they are dynamically selected at startup.
* When dynamically switching between X11/WAYLAND is removed, this function can go too.
*/
static const char *getSystemBackend();
static GHOST_TBacktraceFn getBacktraceFn();
static void setBacktraceFn(GHOST_TBacktraceFn backtrace_fn);
protected:
/**
* Constructor.
* Protected default constructor to force use of static createSystem member.
*/
GHOST_ISystem()
{
}
/**
* Destructor.
* Protected default constructor to force use of static dispose member.
*/
virtual ~GHOST_ISystem()
{
}
public:
/***************************************************************************************
* Time(r) functionality
***************************************************************************************/
/**
* Returns the system time.
* Returns the number of milliseconds since the start of the system process.
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
virtual uint64_t getMilliSeconds() const = 0;
/**
* Installs a timer.
* Note that, on most operating systems, messages need to be processed in order
* for the timer callbacks to be invoked.
* \param delay: The time to wait for the first call to the timerProc (in milliseconds).
* \param interval: The interval between calls to the timerProc (in milliseconds).
* \param timerProc: The callback invoked when the interval expires.
* \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
virtual GHOST_ITimerTask *installTimer(uint64_t delay,
uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL) = 0;
/**
* Removes a timer.
* \param timerTask: Timer task to be removed.
* \return Indication of success.
*/
virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask) = 0;
/***************************************************************************************
* Display/window management functionality
***************************************************************************************/
/**
* Returns the number of displays on this system.
* \return The number of displays.
*/
virtual uint8_t getNumDisplays() const = 0;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
virtual void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const = 0;
/**
* Returns the combine dimensions of all monitors.
* \return The dimension of the workspace.
*/
virtual void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const = 0;
/**
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
* \param title: The name of the window
* (displayed in the title bar of the window if the OS supports it).
* \param left: The coordinate of the left edge of the window.
* \param top: The coordinate of the top edge of the window.
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param parentWindow: Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
virtual GHOST_IWindow *createWindow(const char *title,
int32_t left,
int32_t top,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL) = 0;
/**
* Dispose a window.
* \param window: Pointer to the window to be disposed.
* \return Indication of success.
*/
virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0;
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
/**
* Dispose of a context.
* \param context: Pointer to the context to be disposed.
* \return Indication of success.
*/
virtual GHOST_TSuccess disposeContext(GHOST_IContext *context) = 0;
/**
* Returns whether a window is valid.
* \param window: Pointer to the window to be checked.
* \return Indication of validity.
*/
virtual bool validWindow(GHOST_IWindow *window) = 0;
/**
* Begins full screen mode.
* \param setting: The new setting of the display.
* \param window: Window displayed in full screen.
* This window is invalid after full screen has been ended.
* \return Indication of success.
*/
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window,
const bool stereoVisual) = 0;
/**
* Updates the resolution while in full-screen mode.
* \param setting: The new setting of the display.
* \param window: Window displayed in full screen.
*
* \return Indication of success.
*/
virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window) = 0;
/**
* Ends full screen mode.
* \return Indication of success.
*/
virtual GHOST_TSuccess endFullScreen(void) = 0;
/**
* Returns current full screen mode status.
* \return The current status.
*/
virtual bool getFullScreen(void) = 0;
/**
* Native pixel size support (MacBook 'retina').
*/
virtual bool useNativePixel(void) = 0;
/**
* Return true when warping the cursor is supported.
*/
virtual bool supportsCursorWarp() = 0;
/**
* Return true getting/setting the window position is supported.
*/
virtual bool supportsWindowPosition() = 0;
/**
* Focus window after opening, or put them in the background.
*/
virtual void useWindowFocus(const bool use_focus) = 0;
/**
* Get the Window under the cursor.
* \param x: The x-coordinate of the cursor.
* \param y: The y-coordinate of the cursor.
* \return The window under the cursor or nullptr if none.
*/
virtual GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y) = 0;
/***************************************************************************************
* Event management functionality
***************************************************************************************/
/**
* Retrieves events from the system and stores them in the queue.
* \param waitForEvent: Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
virtual bool processEvents(bool waitForEvent) = 0;
/**
* Retrieves events from the queue and send them to the event consumers.
*/
virtual void dispatchEvents() = 0;
/**
* Adds the given event consumer to our list.
* \param consumer: The event consumer to add.
* \return Indication of success.
*/
virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer) = 0;
/**
* Removes the given event consumer to our list.
* \param consumer: The event consumer to remove.
* \return Indication of success.
*/
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer) = 0;
/***************************************************************************************
* Cursor management functionality
***************************************************************************************/
/**
* Returns the current location of the cursor (location in window coordinates)
* \param x: The x-coordinate of the cursor.
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
virtual GHOST_TSuccess getCursorPositionClientRelative(const GHOST_IWindow *window,
int32_t &x,
int32_t &y) const = 0;
/**
* Updates the location of the cursor (location in window coordinates).
* \param x: The x-coordinate of the cursor.
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
virtual GHOST_TSuccess setCursorPositionClientRelative(GHOST_IWindow *window,
int32_t x,
int32_t y) = 0;
/**
* Returns the current location of the cursor (location in screen coordinates)
* \param x: The x-coordinate of the cursor.
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
virtual GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const = 0;
/**
* Updates the location of the cursor (location in screen coordinates).
* Not all operating systems allow the cursor to be moved (without the input device being moved).
* \param x: The x-coordinate of the cursor.
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
virtual GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) = 0;
/***************************************************************************************
* Access to mouse button and keyboard states.
***************************************************************************************/
/**
* Returns the state of a modifier key (outside the message queue).
* \param mask: The modifier key state to retrieve.
* \param isDown: The state of a modifier key (true == pressed).
* \return Indication of success.
*/
virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKey mask, bool &isDown) const = 0;
/**
* Returns the state of a mouse button (outside the message queue).
* \param mask: The button state to retrieve.
* \param isDown: Button state.
* \return Indication of success.
*/
virtual GHOST_TSuccess getButtonState(GHOST_TButton mask, bool &isDown) const = 0;
/**
* Enable multi-touch gestures if supported.
* \param use: Enable or disable.
*/
virtual void setMultitouchGestures(const bool use) = 0;
/**
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
* \param api: Enum indicating which API to use.
*/
virtual void setTabletAPI(GHOST_TTabletAPI api) = 0;
#ifdef WITH_INPUT_NDOF
/**
* Sets 3D mouse deadzone
* \param deadzone: Dead-zone of the 3D mouse (both for rotation and pan) relative to full range
*/
virtual void setNDOFDeadZone(float deadzone) = 0;
#endif
/**
* Set the Console State
* \param action: console state
* \return current status (true: visible, 0: hidden)
*/
virtual bool setConsoleWindowState(GHOST_TConsoleWindowState action) = 0;
/***************************************************************************************
* Access to clipboard.
***************************************************************************************/
/**
* Returns the selection buffer
* \return "unsigned char" from X11 XA_CUT_BUFFER0 buffer
*
*/
virtual char *getClipboard(bool selection) const = 0;
/**
* Put data to the Clipboard
*/
virtual void putClipboard(const char *buffer, bool selection) const = 0;
/***************************************************************************************
* System Message Box.
***************************************************************************************/
/**
* Show a system message box
*
* \param title: The title of the message box.
* \param message: The message to display.
* \param help_label: Help button label.
* \param continue_label: Continue button label.
* \param link: An optional hyperlink.
* \param dialog_options: Options how to display the message.
*/
virtual GHOST_TSuccess showMessageBox(const char * /*title*/,
const char * /*message*/,
const char * /*help_label*/,
const char * /*continue_label*/,
const char * /*link*/,
GHOST_DialogOptions /*dialog_options*/) const = 0;
/***************************************************************************************
* Debugging
***************************************************************************************/
/**
* Specify whether debug messages are to be shown.
* \param debug: Flag for systems to debug.
*/
virtual void initDebug(GHOST_Debug debug) = 0;
/**
* Check whether debug messages are to be shown.
*/
virtual bool isDebugEnabled() = 0;
protected:
/**
* Initialize the system.
* \return Indication of success.
*/
virtual GHOST_TSuccess init() = 0;
/**
* Shut the system down.
* return Indication of success.
*/
virtual GHOST_TSuccess exit() = 0;
/** The one and only system */
static GHOST_ISystem *m_system;
static const char *m_system_backend_id;
/** Function to call that sets the back-trace. */
static GHOST_TBacktraceFn m_backtrace_fn;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystem")
#endif
};
#include "GHOST_ISystemPaths.h"
#ifdef WIN32
# include "GHOST_SystemPathsWin32.h"
#else
# ifdef __APPLE__
# include "GHOST_SystemPathsCocoa.h"
# else
# include "GHOST_SystemPathsUnix.h"
# endif
#endif
GHOST_ISystemPaths *GHOST_ISystemPaths::m_systemPaths = nullptr;
GHOST_TSuccess GHOST_ISystemPaths::create()
{
GHOST_TSuccess success;
if (!m_systemPaths) {
#ifdef WIN32
m_systemPaths = new GHOST_SystemPathsWin32();
#else
# ifdef __APPLE__
m_systemPaths = new GHOST_SystemPathsCocoa();
# else
m_systemPaths = new GHOST_SystemPathsUnix();
# endif
#endif
success = m_systemPaths != nullptr ? GHOST_kSuccess : GHOST_kFailure;
}
else {
success = GHOST_kFailure;
}
return success;
}
GHOST_TSuccess GHOST_ISystemPaths::dispose()
{
GHOST_TSuccess success = GHOST_kSuccess;
if (m_systemPaths) {
delete m_systemPaths;
m_systemPaths = nullptr;
}
else {
success = GHOST_kFailure;
}
return success;
}
GHOST_ISystemPaths *GHOST_ISystemPaths::get()
{
if (!m_systemPaths) {
create();
}
return m_systemPaths;
}
#pragma once
#include "GHOST_Types.h"
class GHOST_ISystemPaths {
public:
/**
* Creates the one and only system.
* \return An indication of success.
*/
static GHOST_TSuccess create();
/**
* Disposes the one and only system.
* \return An indication of success.
*/
static GHOST_TSuccess dispose();
/**
* Returns a pointer to the one and only system (nil if it hasn't been created).
* \return A pointer to the system.
*/
static GHOST_ISystemPaths *get();
protected:
/**
* Constructor.
* Protected default constructor to force use of static createSystem member.
*/
GHOST_ISystemPaths()
{
}
/**
* Destructor.
* Protected default constructor to force use of static dispose member.
*/
virtual ~GHOST_ISystemPaths()
{
}
public:
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
virtual const char *getSystemDir(int version, const char *versionstr) const = 0;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
virtual const char *getUserDir(int version, const char *versionstr) const = 0;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
virtual const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
virtual const char *getBinaryDir() const = 0;
/**
* Add the file to the operating system most recently used files
*/
virtual void addToSystemRecentFiles(const char *filename) const = 0;
private:
/** The one and only system paths. */
static GHOST_ISystemPaths *m_systemPaths;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystemPaths")
#endif
};
/* dust/intern/ghost/intern/GHOST_Path-api.cpp */
#include <cstdio>
#include "GHOST_ISystemPaths.h"
#include "GHOST_Path-api.h"
#include "GHOST_Types.h"
#include "intern/GHOST_Debug.h"
GHOST_TSuccess GHOST_CreateSystemPaths(void)
{
return GHOST_ISystemPaths::create();
}
#pragma once
#include "GHOST_Types.h"
#ifdef __cplusplus
extern "C" {
#endif
GHOST_DECLARE_HANDLE(GHOST_SystemPathsHandle);
/**
* Creates the one and only instance of the system path access.
* \return An indication of success.
*/
extern GHOST_TSuccess GHOST_CreateSystemPaths(void);
/**
* Disposes the one and only system.
* \return An indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeSystemPaths(void);
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg `/usr/share/blender/`).
*
* \note typically: `BKE_appdir_resource_path_id(BLENDER_RESOURCE_PATH_SYSTEM, false)` should be
* used instead of this function directly as it ensures environment variable overrides are used.
*/
extern const char *GHOST_getSystemDir(int version, const char *versionstr);
/**
* Determine the base dir in which user configuration is stored, including versioning.
* \return Unsigned char string pointing to user dir (eg ~).
*
* \note typically: `BKE_appdir_resource_path_id(BLENDER_RESOURCE_PATH_USER, false)` should be
* used instead of this function directly as it ensures environment variable overrides are used.
*/
extern const char *GHOST_getUserDir(int version, const char *versionstr);
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
extern const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type);
/**
* Determine the dir in which the binary file is found.
* \return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/).
*/
extern const char *GHOST_getBinaryDir(void);
/**
* Add the file to the operating system most recently used files
*/
extern void GHOST_addToSystemRecentFiles(const char *filename);
#ifdef __cplusplus
}
#endif
#include <sstream>
#include "GHOST_SystemPathsUnix.h"
#include "GHOST_Debug.h"
/* For timing. */
#include <sys/time.h>
#include <unistd.h>
#include <pwd.h> /* For get home without use `getenv()`. */
#include <string>
using std::string;
#ifdef PREFIX
static const char *static_path = PREFIX "/share";
#else
static const char *static_path = nullptr;
#endif
GHOST_SystemPathsUnix::GHOST_SystemPathsUnix()
{
}
GHOST_SystemPathsUnix::~GHOST_SystemPathsUnix()
{
}
const char *GHOST_SystemPathsUnix::getSystemDir(int /*version*/, const char *versionstr) const
{
/* no prefix assumes a portable build which only uses bundled scripts */
if (static_path) {
static string system_path = string(static_path) + "/blender/" + versionstr;
return system_path.c_str();
}
return nullptr;
}
const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const
{
static string user_path = "";
static int last_version = 0;
/* in blender 2.64, we migrate to XDG. to ensure the copy previous settings
* operator works we give a different path depending on the requested version */
if (version < 264) {
if (user_path.empty() || last_version != version) {
const char *home = getenv("HOME");
last_version = version;
if (home) {
user_path = string(home) + "/.blender/" + versionstr;
}
else {
return nullptr;
}
}
return user_path.c_str();
}
if (user_path.empty() || last_version != version) {
const char *home = getenv("XDG_CONFIG_HOME");
last_version = version;
if (home) {
user_path = string(home) + "/blender/" + versionstr;
}
else {
home = getenv("HOME");
if (home == nullptr) {
home = getpwuid(getuid())->pw_dir;
}
user_path = string(home) + "/.config/blender/" + versionstr;
}
}
return user_path.c_str();
}
const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
{
const char *type_str;
std::string add_path = "";
switch (type) {
case GHOST_kUserSpecialDirDesktop:
type_str = "DESKTOP";
break;
case GHOST_kUserSpecialDirDocuments:
type_str = "DOCUMENTS";
break;
case GHOST_kUserSpecialDirDownloads:
type_str = "DOWNLOAD";
break;
case GHOST_kUserSpecialDirMusic:
type_str = "MUSIC";
break;
case GHOST_kUserSpecialDirPictures:
type_str = "PICTURES";
break;
case GHOST_kUserSpecialDirVideos:
type_str = "VIDEOS";
break;
case GHOST_kUserSpecialDirCaches: {
const char *cache_dir = getenv("XDG_CACHE_HOME");
if (cache_dir) {
return cache_dir;
}
/* Fallback to ~home/.cache/.
* When invoking `xdg-user-dir` without parameters the user folder
* will be read. `.cache` will be appended. */
type_str = "";
add_path = ".cache";
break;
}
default:
GHOST_ASSERT(
false,
"GHOST_SystemPathsUnix::getUserSpecialDir(): Invalid enum value for type parameter");
return nullptr;
}
static string path = "";
/* Pipe `stderr` to `/dev/null` to avoid error prints. We will fail gracefully still. */
string command = string("xdg-user-dir ") + type_str + " 2> /dev/null";
FILE *fstream = popen(command.c_str(), "r");
if (fstream == nullptr) {
return nullptr;
}
std::stringstream path_stream;
while (!feof(fstream)) {
char c = fgetc(fstream);
/* `xdg-user-dir` ends the path with '\n'. */
if (c == '\n') {
break;
}
path_stream << c;
}
if (pclose(fstream) == -1) {
perror("GHOST_SystemPathsUnix::getUserSpecialDir failed at pclose()");
return nullptr;
}
if (!add_path.empty()) {
path_stream << '/' << add_path;
}
path = path_stream.str();
return path[0] ? path.c_str() : nullptr;
}
const char *GHOST_SystemPathsUnix::getBinaryDir() const
{
return nullptr;
}
void GHOST_SystemPathsUnix::addToSystemRecentFiles(const char * /*filename*/) const
{
/* TODO: implement for X11 */
}
#pragma once
#include "../GHOST_Types.h"
#include "GHOST_SystemPaths.h"
class GHOST_SystemPathsUnix : public GHOST_SystemPaths {
public:
/**
* Constructor
* this class should only be instantiated by GHOST_ISystem.
*/
GHOST_SystemPathsUnix();
/**
* Destructor.
*/
~GHOST_SystemPathsUnix();
/**
* Determine the base dir in which shared resources are located. It will first try to use
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg `/usr/share/blender/`).
*/
const char *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg `~/.config/.blender/`).
*/
const char *getUserDir(int version, const char *versionstr) const;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
const char *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
*/
void addToSystemRecentFiles(const char *filename) const;
};
typedef struct {
int flags;
} GHOST_GLSettings;
#pragma once
#include <stdint.h>
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#else
/* Convenience unsigned abbreviations (#WITH_CXX_GUARDEDALLOC defines these). */
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef unsigned char uchar;
#endif
#if defined(WITH_CXX_GUARDEDALLOC) && defined(__cplusplus)
# define GHOST_DECLARE_HANDLE(name) \
typedef struct name##__ { \
int unused; \
MEM_CXX_CLASS_ALLOC_FUNCS(#name) \
} * name
#else
# define GHOST_DECLARE_HANDLE(name) \
typedef struct name##__ { \
int unused; \
} * name
#endif
/**
* Creates a "handle" for a C++ GHOST object.
* A handle is just an opaque pointer to an empty struct.
* In the API the pointer is cast to the actual C++ class.
* The 'name' argument to the macro is the name of the handle to create.
*/
GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
GHOST_DECLARE_HANDLE(GHOST_EventHandle);
GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
typedef void (*GHOST_TBacktraceFn)(void *file_handle);
/**
* A reference to cursor bitmap data.
*/
typedef struct {
/** `RGBA` bytes. */
const uint8_t *data;
int data_size[2];
int hot_spot[2];
} GHOST_CursorBitmapRef;
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
} GHOST_GLFlags;
typedef enum GHOST_DialogOptions {
GHOST_DialogWarning = (1 << 0),
GHOST_DialogError = (1 << 1),
} GHOST_DialogOptions;
typedef void *GHOST_TUserDataPtr;
typedef enum { GHOST_kFailure = 0, GHOST_kSuccess } GHOST_TSuccess;
/* Xtilt and Ytilt represent how much the pen is tilted away from
* vertically upright in either the X or Y direction, with X and Y the
* axes of the tablet surface.
* In other words, Xtilt and Ytilt are components of a vector created by projecting
* the pen's angle in 3D space vertically downwards on to the XY plane
* --Matt
*/
typedef enum {
GHOST_kTabletModeNone = 0,
GHOST_kTabletModeStylus,
GHOST_kTabletModeEraser
} GHOST_TTabletMode;
typedef enum {
GHOST_kTabletAutomatic = 0,
/* Show as Windows Ink to users to match "Use Windows Ink" in tablet utilities,
* but we use the dependent Windows Pointer API. */
GHOST_kTabletWinPointer,
GHOST_kTabletWintab,
} GHOST_TTabletAPI;
typedef struct GHOST_TabletData {
GHOST_TTabletMode Active; /* 0=None, 1=Stylus, 2=Eraser */
float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */
float Xtilt; /* range 0.0 (upright) to 1.0 (tilted fully against the tablet surface) */
float Ytilt; /* as above */
} GHOST_TabletData;
static const GHOST_TabletData GHOST_TABLET_DATA_NONE = {
GHOST_kTabletModeNone, /* No cursor in range */
1.0f, /* Pressure */
0.0f, /* Xtilt */
0.0f}; /* Ytilt */
typedef enum {
GHOST_kNotVisible = 0,
GHOST_kPartiallyVisible,
GHOST_kFullyVisible
} GHOST_TVisibility;
typedef enum { GHOST_kFireTimeNever = 0xFFFFFFFF } GHOST_TFireTimeConstant;
typedef enum {
GHOST_kModifierKeyLeftShift = 0,
GHOST_kModifierKeyRightShift,
GHOST_kModifierKeyLeftAlt,
GHOST_kModifierKeyRightAlt,
GHOST_kModifierKeyLeftControl,
GHOST_kModifierKeyRightControl,
GHOST_kModifierKeyLeftOS,
GHOST_kModifierKeyRightOS,
GHOST_kModifierKeyNum
} GHOST_TModifierKey;
typedef enum {
GHOST_kWindowStateNormal = 0,
GHOST_kWindowStateMaximized,
GHOST_kWindowStateMinimized,
GHOST_kWindowStateFullScreen,
GHOST_kWindowStateEmbedded,
// GHOST_kWindowStateModified,
// GHOST_kWindowStateUnModified,
} GHOST_TWindowState;
typedef enum {
GHOST_kConsoleWindowStateHide = 0,
GHOST_kConsoleWindowStateShow,
GHOST_kConsoleWindowStateToggle,
GHOST_kConsoleWindowStateHideForNonConsoleLaunch
} GHOST_TConsoleWindowState;
typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWindowOrder;
typedef enum {
GHOST_kDrawingContextTypeNone = 0,
GHOST_kDrawingContextTypeOpenGL,
#ifdef WIN32
GHOST_kDrawingContextTypeD3D,
#endif
#ifdef __APPLE__
GHOST_kDrawingContextTypeMetal,
#endif
} GHOST_TDrawingContextType;
typedef enum {
GHOST_kButtonMaskNone,
GHOST_kButtonMaskLeft,
GHOST_kButtonMaskMiddle,
GHOST_kButtonMaskRight,
GHOST_kButtonMaskButton4,
GHOST_kButtonMaskButton5,
/* Trackballs and programmable buttons. */
GHOST_kButtonMaskButton6,
GHOST_kButtonMaskButton7,
GHOST_kButtonNum
} GHOST_TButton;
typedef enum {
GHOST_kEventUnknown = 0,
GHOST_kEventCursorMove, /* Mouse move event. */
GHOST_kEventButtonDown, /* Mouse button event. */
GHOST_kEventButtonUp, /* Mouse button event. */
GHOST_kEventWheel, /* Mouse wheel event. */
GHOST_kEventTrackpad, /* Trackpad event. */
#ifdef WITH_INPUT_NDOF
GHOST_kEventNDOFMotion, /* N degree of freedom device motion event. */
GHOST_kEventNDOFButton, /* N degree of freedom device button event. */
#endif
GHOST_kEventKeyDown,
GHOST_kEventKeyUp,
// GHOST_kEventKeyAuto,
GHOST_kEventQuitRequest,
GHOST_kEventWindowClose,
GHOST_kEventWindowActivate,
GHOST_kEventWindowDeactivate,
GHOST_kEventWindowUpdate,
GHOST_kEventWindowSize,
GHOST_kEventWindowMove,
GHOST_kEventWindowDPIHintChanged,
GHOST_kEventDraggingEntered,
GHOST_kEventDraggingUpdated,
GHOST_kEventDraggingExited,
GHOST_kEventDraggingDropDone,
GHOST_kEventOpenMainFile, /* Needed for Cocoa to open double-clicked .blend file at startup. */
GHOST_kEventNativeResolutionChange, /* Needed for Cocoa when window moves to other display. */
GHOST_kEventTimer,
GHOST_kEventImeCompositionStart,
GHOST_kEventImeComposition,
GHOST_kEventImeCompositionEnd,
GHOST_kNumEventTypes
} GHOST_TEventType;
typedef enum {
GHOST_kStandardCursorFirstCursor = 0,
GHOST_kStandardCursorDefault = 0,
GHOST_kStandardCursorRightArrow,
GHOST_kStandardCursorLeftArrow,
GHOST_kStandardCursorInfo,
GHOST_kStandardCursorDestroy,
GHOST_kStandardCursorHelp,
GHOST_kStandardCursorWait,
GHOST_kStandardCursorText,
GHOST_kStandardCursorCrosshair,
GHOST_kStandardCursorCrosshairA,
GHOST_kStandardCursorCrosshairB,
GHOST_kStandardCursorCrosshairC,
GHOST_kStandardCursorPencil,
GHOST_kStandardCursorUpArrow,
GHOST_kStandardCursorDownArrow,
GHOST_kStandardCursorVerticalSplit,
GHOST_kStandardCursorHorizontalSplit,
GHOST_kStandardCursorEraser,
GHOST_kStandardCursorKnife,
GHOST_kStandardCursorEyedropper,
GHOST_kStandardCursorZoomIn,
GHOST_kStandardCursorZoomOut,
GHOST_kStandardCursorMove,
GHOST_kStandardCursorNSEWScroll,
GHOST_kStandardCursorNSScroll,
GHOST_kStandardCursorEWScroll,
GHOST_kStandardCursorStop,
GHOST_kStandardCursorUpDown,
GHOST_kStandardCursorLeftRight,
GHOST_kStandardCursorTopSide,
GHOST_kStandardCursorBottomSide,
GHOST_kStandardCursorLeftSide,
GHOST_kStandardCursorRightSide,
GHOST_kStandardCursorTopLeftCorner,
GHOST_kStandardCursorTopRightCorner,
GHOST_kStandardCursorBottomRightCorner,
GHOST_kStandardCursorBottomLeftCorner,
GHOST_kStandardCursorCopy,
GHOST_kStandardCursorCustom,
GHOST_kStandardCursorNumCursors
} GHOST_TStandardCursor;
typedef enum {
GHOST_kKeyUnknown = -1,
GHOST_kKeyBackSpace,
GHOST_kKeyTab,
GHOST_kKeyLinefeed,
GHOST_kKeyClear,
GHOST_kKeyEnter = 0x0D,
GHOST_kKeyEsc = 0x1B,
GHOST_kKeySpace = ' ',
GHOST_kKeyQuote = 0x27,
GHOST_kKeyComma = ',',
GHOST_kKeyMinus = '-',
GHOST_kKeyPlus = '+',
GHOST_kKeyPeriod = '.',
GHOST_kKeySlash = '/',
/* Number keys. */
GHOST_kKey0 = '0',
GHOST_kKey1,
GHOST_kKey2,
GHOST_kKey3,
GHOST_kKey4,
GHOST_kKey5,
GHOST_kKey6,
GHOST_kKey7,
GHOST_kKey8,
GHOST_kKey9,
GHOST_kKeySemicolon = ';',
GHOST_kKeyEqual = '=',
/* Character keys. */
GHOST_kKeyA = 'A',
GHOST_kKeyB,
GHOST_kKeyC,
GHOST_kKeyD,
GHOST_kKeyE,
GHOST_kKeyF,
GHOST_kKeyG,
GHOST_kKeyH,
GHOST_kKeyI,
GHOST_kKeyJ,
GHOST_kKeyK,
GHOST_kKeyL,
GHOST_kKeyM,
GHOST_kKeyN,
GHOST_kKeyO,
GHOST_kKeyP,
GHOST_kKeyQ,
GHOST_kKeyR,
GHOST_kKeyS,
GHOST_kKeyT,
GHOST_kKeyU,
GHOST_kKeyV,
GHOST_kKeyW,
GHOST_kKeyX,
GHOST_kKeyY,
GHOST_kKeyZ,
GHOST_kKeyLeftBracket = '[',
GHOST_kKeyRightBracket = ']',
GHOST_kKeyBackslash = 0x5C,
GHOST_kKeyAccentGrave = '`',
#define _GHOST_KEY_MODIFIER_MIN GHOST_kKeyLeftShift
/* Modifiers: See #GHOST_KEY_MODIFIER_CHECK. */
GHOST_kKeyLeftShift = 0x100,
GHOST_kKeyRightShift,
GHOST_kKeyLeftControl,
GHOST_kKeyRightControl,
GHOST_kKeyLeftAlt,
GHOST_kKeyRightAlt,
GHOST_kKeyLeftOS, /* Command key on Apple, Windows key(s) on Windows. */
GHOST_kKeyRightOS,
#define _GHOST_KEY_MODIFIER_MAX GHOST_kKeyRightOS
GHOST_kKeyGrLess, /* German PC only! */
GHOST_kKeyApp, /* Also known as menu key. */
GHOST_kKeyCapsLock,
GHOST_kKeyNumLock,
GHOST_kKeyScrollLock,
GHOST_kKeyLeftArrow,
GHOST_kKeyRightArrow,
GHOST_kKeyUpArrow,
GHOST_kKeyDownArrow,
GHOST_kKeyPrintScreen,
GHOST_kKeyPause,
GHOST_kKeyInsert,
GHOST_kKeyDelete,
GHOST_kKeyHome,
GHOST_kKeyEnd,
GHOST_kKeyUpPage,
GHOST_kKeyDownPage,
/* Numpad keys. */
GHOST_kKeyNumpad0,
GHOST_kKeyNumpad1,
GHOST_kKeyNumpad2,
GHOST_kKeyNumpad3,
GHOST_kKeyNumpad4,
GHOST_kKeyNumpad5,
GHOST_kKeyNumpad6,
GHOST_kKeyNumpad7,
GHOST_kKeyNumpad8,
GHOST_kKeyNumpad9,
GHOST_kKeyNumpadPeriod,
GHOST_kKeyNumpadEnter,
GHOST_kKeyNumpadPlus,
GHOST_kKeyNumpadMinus,
GHOST_kKeyNumpadAsterisk,
GHOST_kKeyNumpadSlash,
/* Function keys. */
GHOST_kKeyF1,
GHOST_kKeyF2,
GHOST_kKeyF3,
GHOST_kKeyF4,
GHOST_kKeyF5,
GHOST_kKeyF6,
GHOST_kKeyF7,
GHOST_kKeyF8,
GHOST_kKeyF9,
GHOST_kKeyF10,
GHOST_kKeyF11,
GHOST_kKeyF12,
GHOST_kKeyF13,
GHOST_kKeyF14,
GHOST_kKeyF15,
GHOST_kKeyF16,
GHOST_kKeyF17,
GHOST_kKeyF18,
GHOST_kKeyF19,
GHOST_kKeyF20,
GHOST_kKeyF21,
GHOST_kKeyF22,
GHOST_kKeyF23,
GHOST_kKeyF24,
/* Multimedia keypad buttons. */
GHOST_kKeyMediaPlay,
GHOST_kKeyMediaStop,
GHOST_kKeyMediaFirst,
GHOST_kKeyMediaLast
} GHOST_TKey;
#define GHOST_KEY_MODIFIER_NUM ((_GHOST_KEY_MODIFIER_MAX - _GHOST_KEY_MODIFIER_MIN) + 1)
#define GHOST_KEY_MODIFIER_TO_INDEX(key) ((unsigned int)(key)-_GHOST_KEY_MODIFIER_MIN)
#define GHOST_KEY_MODIFIER_FROM_INDEX(key) \
(GHOST_TKey)(((unsigned int)(key) + _GHOST_KEY_MODIFIER_MIN))
#define GHOST_KEY_MODIFIER_CHECK(key) (GHOST_KEY_MODIFIER_TO_INDEX(key) < GHOST_KEY_MODIFIER_NUM)
typedef enum {
/** Grab not set. */
GHOST_kGrabDisable = 0,
/** No cursor adjustments. */
GHOST_kGrabNormal,
/** Wrap the mouse location to prevent limiting screen bounds. */
GHOST_kGrabWrap,
/**
* Hide the mouse while grabbing and restore the original location on release
* (used for number buttons and some other draggable UI elements).
*/
GHOST_kGrabHide,
} GHOST_TGrabCursorMode;
#define GHOST_GRAB_NEEDS_SOFTWARE_CURSOR_FOR_WARP(grab) ((grab) == GHOST_kGrabWrap)
typedef enum {
/** Axis that cursor grab will wrap. */
GHOST_kAxisNone = 0,
GHOST_kAxisX = (1 << 0),
GHOST_kAxisY = (1 << 1),
} GHOST_TAxisFlag;
typedef void *GHOST_TEventDataPtr;
typedef struct {
/** The x-coordinate of the cursor position. */
int32_t x;
/** The y-coordinate of the cursor position. */
int32_t y;
/** Associated tablet data. */
GHOST_TabletData tablet;
} GHOST_TEventCursorData;
typedef struct {
/** The mask of the mouse button. */
GHOST_TButton button;
/** Associated tablet data. */
GHOST_TabletData tablet;
} GHOST_TEventButtonData;
typedef struct {
/** Displacement of a mouse wheel. */
int32_t z;
} GHOST_TEventWheelData;
typedef enum {
GHOST_kTrackpadEventUnknown = 0,
GHOST_kTrackpadEventScroll,
GHOST_kTrackpadEventRotate,
GHOST_kTrackpadEventSwipe, /* Reserved, not used for now */
GHOST_kTrackpadEventMagnify,
GHOST_kTrackpadEventSmartMagnify
} GHOST_TTrackpadEventSubTypes;
typedef struct {
/** The event subtype */
GHOST_TTrackpadEventSubTypes subtype;
/** The x-location of the trackpad event */
int32_t x;
/** The y-location of the trackpad event */
int32_t y;
/** The x-delta or value of the trackpad event */
int32_t deltaX;
/** The y-delta (currently only for scroll subtype) of the trackpad event */
int32_t deltaY;
/** The delta is inverted from the device due to system preferences. */
char isDirectionInverted;
} GHOST_TEventTrackpadData;
typedef enum {
GHOST_kDragnDropTypeUnknown = 0,
GHOST_kDragnDropTypeFilenames, /* Array of strings representing file names (full path). */
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string. */
GHOST_kDragnDropTypeBitmap /* Bitmap image data. */
} GHOST_TDragnDropTypes;
typedef struct {
/** The x-coordinate of the cursor position. */
int32_t x;
/** The y-coordinate of the cursor position. */
int32_t y;
/** The dropped item type */
GHOST_TDragnDropTypes dataType;
/** The "dropped content" */
GHOST_TEventDataPtr data;
} GHOST_TEventDragnDropData;
/** similar to wmImeData */
typedef struct {
/** size_t */
GHOST_TUserDataPtr result_len, composite_len;
/** char * utf8 encoding */
GHOST_TUserDataPtr result, composite;
/** Cursor position in the IME composition. */
int cursor_position;
/** Represents the position of the beginning of the selection */
int target_start;
/** Represents the position of the end of the selection */
int target_end;
} GHOST_TEventImeData;
typedef struct {
int count;
uint8_t **strings;
} GHOST_TStringArray;
typedef enum {
GHOST_kNotStarted = 0,
GHOST_kStarting,
GHOST_kInProgress,
GHOST_kFinishing,
GHOST_kFinished
} GHOST_TProgress;
#ifdef WITH_INPUT_NDOF
typedef struct {
/** N-degree of freedom device data v3 [GSoC 2010] */
/* Each component normally ranges from -1 to +1, but can exceed that.
* These use blender standard view coordinates,
* with positive rotations being CCW about the axis. */
/* translation: */
float tx, ty, tz;
/* rotation:
* - `axis = (rx,ry,rz).normalized`
* - `amount = (rx,ry,rz).magnitude` [in revolutions, 1.0 = 360 deg]. */
float rx, ry, rz;
/** Time since previous NDOF Motion event */
float dt;
/** Starting, #GHOST_kInProgress or #GHOST_kFinishing (for modal handlers) */
GHOST_TProgress progress;
} GHOST_TEventNDOFMotionData;
typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
/* Good for mouse or other buttons too? */
typedef struct {
GHOST_TButtonAction action;
short button;
} GHOST_TEventNDOFButtonData;
#endif // WITH_INPUT_NDOF
typedef struct {
/** The key code. */
GHOST_TKey key;
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set. */
char utf8_buf[6];
/**
* Enabled when the key is held (auto-repeat).
* In this case press events are sent without a corresponding release/up event.
*
* All back-ends must set this variable for correct behavior regarding repeatable keys.
*/
char is_repeat;
} GHOST_TEventKeyData;
typedef enum {
GHOST_kUserSpecialDirDesktop,
GHOST_kUserSpecialDirDocuments,
GHOST_kUserSpecialDirDownloads,
GHOST_kUserSpecialDirMusic,
GHOST_kUserSpecialDirPictures,
GHOST_kUserSpecialDirVideos,
GHOST_kUserSpecialDirCaches,
/* Can be extended as needed. */
} GHOST_TUserSpecialDirTypes;
typedef struct {
/** Number of pixels on a line. */
uint32_t xPixels;
/** Number of lines. */
uint32_t yPixels;
/** Number of bits per pixel. */
uint32_t bpp;
/** Refresh rate (in Hertz). */
uint32_t frequency;
} GHOST_DisplaySetting;
typedef struct {
int flags;
GHOST_TDrawingContextType context_type;
} GHOST_GLSettings;
typedef enum {
/** Axis that cursor grab will wrap. */
GHOST_kDebugDefault = (1 << 1),
GHOST_kDebugWintab = (1 << 2),
} GHOST_TDebugFlags;
typedef struct {
int flags;
} GHOST_Debug;
#ifdef _WIN32
typedef void *GHOST_TEmbedderWindowID;
#endif // _WIN32
#ifndef _WIN32
/* I can't use "Window" from `X11/Xlib.h`
* because it conflicts with Window defined in `winlay.h`. */
typedef int GHOST_TEmbedderWindowID;
#endif // _WIN32
/**
* A timer task callback routine.
* \param task: The timer task object.
* \param time: Time since this timer started (in milliseconds).
*/
#ifdef __cplusplus
class GHOST_ITimerTask;
typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask *task, uint64_t time);
#else
struct GHOST_TimerTaskHandle__;
typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, uint64_t time);
#endif
#ifdef WITH_XR_OPENXR
struct GHOST_XrDrawViewInfo;
struct GHOST_XrError;
/**
* The XR view (i.e. the OpenXR runtime) may require a different graphics library than OpenGL.
* An off-screen texture of the viewport will then be drawn into using OpenGL,
* but the final texture draw call will happen through another library (say DirectX).
*
* This enum defines the possible graphics bindings to attempt to enable.
*/
typedef enum GHOST_TXrGraphicsBinding {
GHOST_kXrGraphicsUnknown = 0,
GHOST_kXrGraphicsOpenGL,
# ifdef WIN32
GHOST_kXrGraphicsD3D11,
# endif
/* For later */
// GHOST_kXrGraphicsVulkan,
} GHOST_TXrGraphicsBinding;
typedef void (*GHOST_XrErrorHandlerFn)(const struct GHOST_XrError *);
typedef void (*GHOST_XrSessionCreateFn)(void);
typedef void (*GHOST_XrSessionExitFn)(void *customdata);
typedef void (*GHOST_XrCustomdataFreeFn)(void *customdata);
typedef void *(*GHOST_XrGraphicsContextBindFn)(void);
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_ContextHandle graphics_context);
typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view, void *customdata);
/**
* An array of #GHOST_TXrGraphicsBinding items defining the candidate bindings to use.
* The first available candidate will be chosen, so order defines priority.
*/
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
typedef struct {
float position[3];
/* Blender convention (w, x, y, z) */
float orientation_quat[4];
} GHOST_XrPose;
enum {
GHOST_kXrContextDebug = (1 << 0),
GHOST_kXrContextDebugTime = (1 << 1),
# ifdef WIN32
/* Needed to avoid issues with the SteamVR OpenGL graphics binding
* (use DirectX fallback instead). */
GHOST_kXrContextGpuNVIDIA = (1 << 2),
# endif
};
typedef struct {
const GHOST_XrGraphicsBindingCandidates gpu_binding_candidates;
unsigned int gpu_binding_candidates_count;
unsigned int context_flag;
} GHOST_XrContextCreateInfo;
typedef struct {
GHOST_XrPose base_pose;
GHOST_XrSessionCreateFn create_fn;
GHOST_XrSessionExitFn exit_fn;
void *exit_customdata;
} GHOST_XrSessionBeginInfo;
/** Texture format for XR swapchain. */
typedef enum GHOST_TXrSwapchainFormat {
GHOST_kXrSwapchainFormatRGBA8,
GHOST_kXrSwapchainFormatRGBA16,
GHOST_kXrSwapchainFormatRGBA16F,
GHOST_kXrSwapchainFormatRGB10_A2,
} GHOST_TXrSwapchainFormat;
typedef struct GHOST_XrDrawViewInfo {
int ofsx, ofsy;
int width, height;
GHOST_XrPose eye_pose;
GHOST_XrPose local_pose;
struct {
float angle_left, angle_right;
float angle_up, angle_down;
} fov;
GHOST_TXrSwapchainFormat swapchain_format;
/** Set if the buffer should be submitted with a SRGB transfer applied. */
char expects_srgb_buffer;
/** The view that this info represents. Not necessarily the "eye index" (e.g. for quad view
* systems, etc). */
char view_idx;
} GHOST_XrDrawViewInfo;
typedef struct GHOST_XrError {
const char *user_message;
void *customdata;
} GHOST_XrError;
typedef struct GHOST_XrActionSetInfo {
const char *name;
GHOST_XrCustomdataFreeFn customdata_free_fn;
void *customdata; /* wmXrActionSet */
} GHOST_XrActionSetInfo;
/** XR action type. Enum values match those in OpenXR's
* XrActionType enum for consistency. */
typedef enum GHOST_XrActionType {
GHOST_kXrActionTypeBooleanInput = 1,
GHOST_kXrActionTypeFloatInput = 2,
GHOST_kXrActionTypeVector2fInput = 3,
GHOST_kXrActionTypePoseInput = 4,
GHOST_kXrActionTypeVibrationOutput = 100,
} GHOST_XrActionType;
typedef struct GHOST_XrActionInfo {
const char *name;
GHOST_XrActionType type;
uint32_t count_subaction_paths;
const char **subaction_paths;
/** States for each subaction path. */
void *states;
/** Input thresholds/regions for each subaction path. */
float *float_thresholds;
int16_t *axis_flags;
GHOST_XrCustomdataFreeFn customdata_free_fn;
void *customdata; /* wmXrAction */
} GHOST_XrActionInfo;
typedef struct GHOST_XrActionBindingInfo {
const char *component_path;
float float_threshold;
int16_t axis_flag;
GHOST_XrPose pose;
} GHOST_XrActionBindingInfo;
typedef struct GHOST_XrActionProfileInfo {
const char *action_name;
const char *profile_path;
uint32_t count_subaction_paths;
const char **subaction_paths;
/** Bindings for each subaction path. */
const GHOST_XrActionBindingInfo *bindings;
} GHOST_XrActionProfileInfo;
typedef struct GHOST_XrControllerModelVertex {
float position[3];
float normal[3];
} GHOST_XrControllerModelVertex;
typedef struct GHOST_XrControllerModelComponent {
/** World space transform. */
float transform[4][4];
uint32_t vertex_offset;
uint32_t vertex_count;
uint32_t index_offset;
uint32_t index_count;
} GHOST_XrControllerModelComponent;
typedef struct GHOST_XrControllerModelData {
uint32_t count_vertices;
const GHOST_XrControllerModelVertex *vertices;
uint32_t count_indices;
const uint32_t *indices;
uint32_t count_components;
const GHOST_XrControllerModelComponent *components;
} GHOST_XrControllerModelData;
#endif /* WITH_XR_OPENXR */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment