Preliminary support for draw-only

This commit is contained in:
Matthew King 2023-06-20 21:22:38 +01:00
parent 7482de6071
commit e406c2d755
6 changed files with 157 additions and 18 deletions

View File

@ -1031,6 +1031,14 @@ extern "C" {
* [window hint](@ref GLFW_X11_CLASS_NAME_hint).
*/
#define GLFW_X11_INSTANCE_NAME 0x00024002
/*! @brief X11 specific
* [window hint](@ref GLFW_HANDLE_DND_hint).
*/
#define GLFW_HANDLE_DND 0x00024003
/*! @brief X11 specific but probably/possibly shouldn't be
* [window hint](@ref GLFW_HANDLE_KEYBOARD_hint).
*/
#define GLFW_HANDLE_KEYBOARD 0x00024004
/*! @} */
#define GLFW_NO_API 0
@ -1641,6 +1649,26 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor* monitor, int event);
*/
typedef void (* GLFWjoystickfun)(int jid, int event);
/*! @brief The function pointer type for unhandled event callbacks.
*
* This is the function pointer type for callbacks when GLFW has
* not handled an input event.
* unhandled event callback function has the following signature:
* @code
* void function_name(GLFWwindow* window, void *event)
* @endcode
*
* @param[in] window The window that received the event.
* @param[in] event The event. What it means is platform-dependent.
*
* @sa @ref glfwSetUnhandledCallback
*
* @since Added in version 3.9.
*
* @ingroup input
*/
typedef void (* GLFWunhandledfun)(GLFWwindow* window, void* event);
/*! @brief Video mode type.
*
* This describes a single video mode.
@ -4840,6 +4868,36 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun ca
*/
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback);
/*! @brief Sets the unhandled event callback.
*
* This function sets the unhandled event callback of the specified
* window, which is called when an event is received from the windowing system
* which GLFW does not handle itself.
*
* @param[in] window The window whose callback to set.
* @param[in] callback The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @callback_signature
* @code
* void function_name(GLFWwindow* window, void *event)
* @endcode
* The meaning of the event variable is platform-dependent.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref cursor_enter
*
* @since Added in version 3.0.
*
* @ingroup input
*/
GLFWAPI GLFWunhandledfun glfwSetUnhandledCallback(GLFWwindow* window, GLFWunhandledfun callback);
/*! @brief Returns whether the specified joystick is present.
*
* This function returns whether the specified joystick is present.

View File

@ -313,6 +313,22 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
*/
GLFWAPI Display* glfwGetX11Display(void);
/*! @brief Returns the `Screen` used by GLFW.
*
* @return The `Screen` used by GLFW, or `-1` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.8.9.
*
* @ingroup native
*/
GLFWAPI int glfwGetX11Screen(void);
/*! @brief Returns the `RRCrtc` of the specified monitor.
*
* @return The `RRCrtc` of the specified monitor, or `None` if an

View File

@ -245,6 +245,14 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code of an event that was not handled by GLFW
//
void _glfwInputUnhandledEvent(_GLFWwindow* window, void *event)
{
if (window->callbacks.unhandled)
window->callbacks.unhandled((GLFWwindow*) window, event);
}
// Notifies shared code of a physical key event
//
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
@ -849,6 +857,16 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
_glfwPlatformSetCursor(window, cursor);
}
GLFWAPI GLFWunhandledfun glfwSetUnhandledCallback(GLFWwindow* handle, GLFWunhandledfun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.unhandled, cbfun);
return cbfun;
}
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;

View File

@ -267,6 +267,8 @@ struct _GLFWwndconfig
GLFWbool centerCursor;
GLFWbool focusOnShow;
GLFWbool scaleToMonitor;
GLFWbool handleDND;
GLFWbool handleKeyboard;
struct {
GLFWbool retina;
char frameName[256];
@ -393,6 +395,8 @@ struct _GLFWwindow
// Virtual cursor position when cursor is disabled
double virtualCursorPosX, virtualCursorPosY;
GLFWbool rawMouseMotion;
GLFWbool handleDND;
GLFWbool handleKeyboard;
_GLFWcontext context;
@ -414,6 +418,7 @@ struct _GLFWwindow
GLFWcharfun character;
GLFWcharmodsfun charmods;
GLFWdropfun drop;
GLFWunhandledfun unhandled;
} callbacks;
// This is defined in the window API's platform.h
@ -716,6 +721,7 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
void _glfwInputUnhandledEvent(_GLFWwindow* window, void* event);
void _glfwInputKey(_GLFWwindow* window,
int key, int scancode, int action, int mods);
void _glfwInputChar(_GLFWwindow* window,

View File

@ -261,6 +261,10 @@ void glfwDefaultWindowHints(void)
// The default is to use full Retina resolution framebuffers
_glfw.hints.window.ns.retina = GLFW_TRUE;
// Handle keyboard and drag-and-dtop in GLFW by default
_glfw.hints.window.handleDND = GLFW_TRUE;
_glfw.hints.window.handleKeyboard = GLFW_TRUE;
}
GLFWAPI void glfwWindowHint(int hint, int value)
@ -386,6 +390,12 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_REFRESH_RATE:
_glfw.hints.refreshRate = value;
return;
case GLFW_HANDLE_DND:
_glfw.hints.window.handleDND = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_HANDLE_KEYBOARD:
_glfw.hints.window.handleKeyboard = value ? GLFW_TRUE : GLFW_FALSE;
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);

View File

@ -646,6 +646,9 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
_glfw.x11.context,
(XPointer) window);
window->handleDND = wndconfig->handleDND;
window->handleKeyboard = wndconfig->handleKeyboard;
if (!wndconfig->decorated)
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
@ -759,6 +762,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
}
// Announce support for Xdnd (drag and drop)
if (wndconfig->handleDND)
{
const Atom version = _GLFW_XDND_VERSION;
XChangeProperty(_glfw.x11.display, window->x11.handle,
@ -768,7 +772,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
_glfwPlatformSetWindowTitle(window, wndconfig->title);
if (_glfw.x11.im)
if (wndconfig->handleKeyboard && _glfw.x11.im)
{
window->x11.ic = XCreateIC(_glfw.x11.im,
XNInputStyle,
@ -780,7 +784,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
NULL);
}
if (window->x11.ic)
if (wndconfig->handleKeyboard && window->x11.ic)
{
unsigned long filter = 0;
if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
@ -1163,13 +1167,19 @@ static void processEvent(XEvent *event)
if (_glfw.x11.im)
filtered = XFilterEvent(event, None);
_GLFWwindow* window = NULL;
XFindContext(_glfw.x11.display,
event->xany.window,
_glfw.x11.context,
(XPointer*) &window);
if (_glfw.x11.randr.available)
{
if (event->type == _glfw.x11.randr.eventBase + RRNotify)
{
XRRUpdateConfiguration(event);
_glfwPollMonitorsX11();
return;
goto unhandled_event;
}
}
@ -1183,7 +1193,7 @@ static void processEvent(XEvent *event)
_glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;
}
return;
goto unhandled_event;
}
}
@ -1222,20 +1232,16 @@ static void processEvent(XEvent *event)
XFreeEventData(_glfw.x11.display, &event->xcookie);
}
return;
goto unhandled_event;
}
if (event->type == SelectionRequest)
{
handleSelectionRequest(event);
return;
goto unhandled_event;
}
_GLFWwindow* window = NULL;
if (XFindContext(_glfw.x11.display,
event->xany.window,
_glfw.x11.context,
(XPointer*) &window) != 0)
if (!window)
{
// This is an event for a window that has already been destroyed
return;
@ -1243,6 +1249,15 @@ static void processEvent(XEvent *event)
switch (event->type)
{
unhandled_event:
default:
{
if (!window)
return;
_glfwInputUnhandledEvent(window, (void *) event);
return;
}
case ReparentNotify:
{
window->x11.parent = event->xreparent.parent;
@ -1251,6 +1266,9 @@ static void processEvent(XEvent *event)
case KeyPress:
{
if (!window->handleKeyboard)
goto unhandled_event;
const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
@ -1351,6 +1369,9 @@ static void processEvent(XEvent *event)
case KeyRelease:
{
if (!window->handleKeyboard)
goto unhandled_event;
const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state);
@ -1392,6 +1413,9 @@ static void processEvent(XEvent *event)
case ButtonPress:
{
if (!window->handleKeyboard)
goto unhandled_event;
const int mods = translateState(event->xbutton.state);
if (event->xbutton.button == Button1)
@ -1578,13 +1602,11 @@ static void processEvent(XEvent *event)
return;
if (event->xclient.message_type == None)
return;
goto unhandled_event;
if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
{
const Atom protocol = event->xclient.data.l[0];
if (protocol == None)
return;
if (protocol == _glfw.x11.WM_DELETE_WINDOW)
{
@ -1592,6 +1614,7 @@ static void processEvent(XEvent *event)
// example by the user pressing a 'close' window decoration
// button
_glfwInputWindowCloseRequest(window);
return;
}
else if (protocol == _glfw.x11.NET_WM_PING)
{
@ -1605,9 +1628,14 @@ static void processEvent(XEvent *event)
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&reply);
return;
}
}
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
if (!window->handleDND)
goto unhandled_event;
if (event->xclient.message_type == _glfw.x11.XdndEnter)
{
// A drag operation has entered the window
unsigned long i, count;
@ -1859,9 +1887,6 @@ static void processEvent(XEvent *event)
return;
}
case DestroyNotify:
return;
}
}
@ -3139,6 +3164,12 @@ GLFWAPI Display* glfwGetX11Display(void)
return _glfw.x11.display;
}
GLFWAPI int glfwGetX11Screen(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
return _glfw.x11.screen;
}
GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;