Add runtime platform selection

This adds compile-time support for multiple platforms and runtime
detection of them.  Window system related platform functions are now
called from shared code via the function pointer struct _GLFWplatform.

The timer, thread and module loading platform functions are still called
directly by name and the implementation chosen at link-time.  These
functions are the same for any backend on a given OS, including the Null
backend.

The platforms are now enabled via CMake dependent options following the
GLFW_BUILD_<platform> pattern instead of a mix of automagic and ad-hoc
option names.  There is no longer any option for the Null backend as it
is now always enabled.

Much of the struct stitching work in platform.h was based on an earlier
experimental branch for runtime platform selection by @ronchaine.

Every platform function related to windows, contexts, monitors, input,
event processing and Vulkan have been renamed so that multiple sets of
them can exist without colliding.  Calls to these are now routed through
the _glfw.platform struct member.  These changes makes up most of this
commit.

For Wayland and X11 the client library loading and display creation is
used to detect a running compositor/server.  The XDG_SESSION_TYPE
environment variable is ignored for now, as X11 is still by far the more
complete implementation.

Closes #1655
Closes #1958
This commit is contained in:
Camilla Löwy
2021-07-13 21:50:09 +02:00
parent ff9d9515f6
commit 56a4cb0a3a
56 changed files with 2698 additions and 1235 deletions
+94 -90
View File
@@ -53,10 +53,10 @@ static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
static void fitToMonitor(_GLFWwindow* window)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor,
&window->null.xpos,
&window->null.ypos);
_glfwGetVideoModeNull(window->monitor, &mode);
_glfwGetMonitorPosNull(window->monitor,
&window->null.xpos,
&window->null.ypos);
window->null.width = mode.width;
window->null.height = mode.height;
}
@@ -103,10 +103,10 @@ static int createNativeWindow(_GLFWwindow* window,
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
int _glfwCreateWindowNull(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE;
@@ -132,15 +132,15 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
_glfwShowWindowNull(window);
_glfwFocusWindowNull(window);
acquireMonitor(window);
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
void _glfwDestroyWindowNull(_GLFWwindow* window)
{
if (window->monitor)
releaseMonitor(window);
@@ -152,27 +152,26 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title)
{
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
const GLFWimage* images)
void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
void _glfwSetWindowMonitorNull(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (window->monitor == monitor)
{
if (!monitor)
{
_glfwPlatformSetWindowPos(window, xpos, ypos);
_glfwPlatformSetWindowSize(window, width, height);
_glfwSetWindowPosNull(window, xpos, ypos);
_glfwSetWindowSizeNull(window, width, height);
}
return;
@@ -191,12 +190,12 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
}
else
{
_glfwPlatformSetWindowPos(window, xpos, ypos);
_glfwPlatformSetWindowSize(window, width, height);
_glfwSetWindowPosNull(window, xpos, ypos);
_glfwSetWindowSizeNull(window, width, height);
}
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwGetWindowPosNull(_GLFWwindow* window, int* xpos, int* ypos)
{
if (xpos)
*xpos = window->null.xpos;
@@ -204,7 +203,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
*ypos = window->null.ypos;
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
void _glfwSetWindowPosNull(_GLFWwindow* window, int xpos, int ypos)
{
if (window->monitor)
return;
@@ -217,7 +216,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
}
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwGetWindowSizeNull(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->null.width;
@@ -225,7 +224,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
*height = window->null.height;
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
void _glfwSetWindowSizeNull(_GLFWwindow* window, int width, int height)
{
if (window->monitor)
return;
@@ -239,25 +238,25 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
}
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
void _glfwSetWindowSizeLimitsNull(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
int width = window->null.width;
int height = window->null.height;
applySizeLimits(window, &width, &height);
_glfwPlatformSetWindowSize(window, width, height);
_glfwSetWindowSizeNull(window, width, height);
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
void _glfwSetWindowAspectRatioNull(_GLFWwindow* window, int n, int d)
{
int width = window->null.width;
int height = window->null.height;
applySizeLimits(window, &width, &height);
_glfwPlatformSetWindowSize(window, width, height);
_glfwSetWindowSizeNull(window, width, height);
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
void _glfwGetFramebufferSizeNull(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->null.width;
@@ -265,9 +264,9 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->null.height;
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
void _glfwGetWindowFrameSizeNull(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
if (window->null.decorated && !window->monitor)
{
@@ -293,8 +292,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
}
}
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
float* xscale, float* yscale)
void _glfwGetWindowContentScaleNull(_GLFWwindow* window, float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.f;
@@ -302,7 +300,7 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = 1.f;
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
void _glfwIconifyWindowNull(_GLFWwindow* window)
{
if (_glfw.null.focusedWindow == window)
{
@@ -320,7 +318,7 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window)
}
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwRestoreWindowNull(_GLFWwindow* window)
{
if (window->null.iconified)
{
@@ -337,7 +335,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
}
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwMaximizeWindowNull(_GLFWwindow* window)
{
if (!window->null.maximized)
{
@@ -346,12 +344,12 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
}
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
int _glfwWindowMaximizedNull(_GLFWwindow* window)
{
return window->null.maximized;
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
int _glfwWindowHoveredNull(_GLFWwindow* window)
{
return _glfw.null.xcursor >= window->null.xpos &&
_glfw.null.ycursor >= window->null.ypos &&
@@ -359,59 +357,63 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
_glfw.null.ycursor <= window->null.ypos + window->null.height - 1;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
int _glfwFramebufferTransparentNull(_GLFWwindow* window)
{
return window->null.transparent;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled)
{
window->null.resizable = enabled;
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled)
{
window->null.decorated = enabled;
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled)
{
window->null.floating = enabled;
}
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
void _glfwSetWindowMousePassthroughNull(_GLFWwindow* window, GLFWbool enabled)
{
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
float _glfwGetWindowOpacityNull(_GLFWwindow* window)
{
return window->null.opacity;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity)
{
window->null.opacity = opacity;
}
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled)
{
}
GLFWbool _glfwPlatformRawMouseMotionSupported(void)
GLFWbool _glfwRawMouseMotionSupportedNull(void)
{
return GLFW_TRUE;
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
void _glfwShowWindowNull(_GLFWwindow* window)
{
window->null.visible = GLFW_TRUE;
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
void _glfwRequestWindowAttentionNull(_GLFWwindow* window)
{
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
void _glfwUnhideWindowNull(_GLFWwindow* window)
{
}
void _glfwHideWindowNull(_GLFWwindow* window)
{
if (_glfw.null.focusedWindow == window)
{
@@ -422,59 +424,61 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
window->null.visible = GLFW_FALSE;
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
void _glfwFocusWindowNull(_GLFWwindow* window)
{
_GLFWwindow* previous;
if (_glfw.null.focusedWindow == window)
return;
if (!window->null.visible)
return;
_GLFWwindow* previous = _glfw.null.focusedWindow;
previous = _glfw.null.focusedWindow;
_glfw.null.focusedWindow = window;
if (previous)
{
_glfwInputWindowFocus(previous, GLFW_FALSE);
if (previous->monitor && previous->autoIconify)
_glfwPlatformIconifyWindow(previous);
_glfwIconifyWindowNull(previous);
}
_glfwInputWindowFocus(window, GLFW_TRUE);
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
int _glfwWindowFocusedNull(_GLFWwindow* window)
{
return _glfw.null.focusedWindow == window;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
int _glfwWindowIconifiedNull(_GLFWwindow* window)
{
return window->null.iconified;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
int _glfwWindowVisibleNull(_GLFWwindow* window)
{
return window->null.visible;
}
void _glfwPlatformPollEvents(void)
void _glfwPollEventsNull(void)
{
}
void _glfwPlatformWaitEvents(void)
void _glfwWaitEventsNull(void)
{
}
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwWaitEventsTimeoutNull(double timeout)
{
}
void _glfwPlatformPostEmptyEvent(void)
void _glfwPostEmptyEventNull(void)
{
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos)
{
if (xpos)
*xpos = _glfw.null.xcursor - window->null.xpos;
@@ -482,64 +486,64 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
*ypos = _glfw.null.ycursor - window->null.ypos;
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y)
{
_glfw.null.xcursor = window->null.xpos + (int) x;
_glfw.null.ycursor = window->null.ypos + (int) y;
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
void _glfwSetCursorModeNull(_GLFWwindow* window, int mode)
{
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
int _glfwCreateCursorNull(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
return GLFW_TRUE;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
int _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape)
{
return GLFW_TRUE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwDestroyCursorNull(_GLFWcursor* cursor)
{
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor)
{
}
void _glfwPlatformSetClipboardString(const char* string)
void _glfwSetClipboardStringNull(const char* string)
{
char* copy = _glfw_strdup(string);
_glfw_free(_glfw.null.clipboardString);
_glfw.null.clipboardString = copy;
}
const char* _glfwPlatformGetClipboardString(void)
const char* _glfwGetClipboardStringNull(void)
{
return _glfw.null.clipboardString;
}
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs)
EGLenum _glfwGetEGLPlatformNull(EGLint** attribs)
{
return 0;
}
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void)
{
return 0;
}
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window)
EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window)
{
return 0;
}
const char* _glfwPlatformGetScancodeName(int scancode)
const char* _glfwGetScancodeNameNull(int scancode)
{
if (scancode < GLFW_KEY_SPACE || scancode > GLFW_KEY_LAST)
{
@@ -666,26 +670,26 @@ const char* _glfwPlatformGetScancodeName(int scancode)
return NULL;
}
int _glfwPlatformGetKeyScancode(int key)
int _glfwGetKeyScancodeNull(int key)
{
return key;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
void _glfwGetRequiredInstanceExtensionsNull(char** extensions)
{
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
int _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
return GLFW_FALSE;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
VkResult _glfwCreateWindowSurfaceNull(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
// This seems like the most appropriate error to return here
return VK_ERROR_EXTENSION_NOT_PRESENT;