mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
Added empty event callback function. Implemented for Windows only at the moment
This commit is contained in:
parent
46cebb5081
commit
57e00a0a3a
3
.gitignore
vendored
3
.gitignore
vendored
@ -101,3 +101,6 @@ tests/triangle-vulkan
|
||||
tests/window
|
||||
tests/windows
|
||||
|
||||
/.idea
|
||||
/cmake-build-debug
|
||||
/.gitignore
|
||||
|
@ -1974,6 +1974,23 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor* monitor, int event);
|
||||
*/
|
||||
typedef void (* GLFWjoystickfun)(int jid, int event);
|
||||
|
||||
/*! @brief The function pointer type for empty event callbacks.
|
||||
*
|
||||
* This is the function pointer type for empty event callbacks.
|
||||
* An empty event callback function has the following signature:
|
||||
* @code
|
||||
* void function_name()
|
||||
* @endcode
|
||||
*
|
||||
* @sa @ref empty_event
|
||||
* @sa @ref glfwSetEmptyEventCallback
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef void (* GLFWemptyeventfun)(void);
|
||||
|
||||
/*! @brief Video mode type.
|
||||
*
|
||||
* This describes a single video mode.
|
||||
@ -5697,7 +5714,36 @@ GLFWAPI int glfwJoystickIsGamepad(int jid);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback);
|
||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback);/*! @brief Sets the joystick configuration callback.
|
||||
*
|
||||
*
|
||||
* This function sets the empty event callback, or removes the currently
|
||||
* set callback. This is called on the GLFW thread at some point in the future
|
||||
* when glfwPostEmptyEvent is called from any thread.
|
||||
*
|
||||
* @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()
|
||||
* @endcode
|
||||
* For more information about the callback parameters, see the
|
||||
* [function pointer type](@ref GLFWemptyeventfun).
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread
|
||||
*
|
||||
* @sa @ref empty_event
|
||||
*
|
||||
* @since Added in version TODO
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWemptyeventfun glfwSetEmptyEventCallback(GLFWemptyeventfun callback);
|
||||
|
||||
/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings.
|
||||
*
|
||||
|
@ -1253,6 +1253,13 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWemptyeventfun glfwSetEmptyEventCallback(GLFWemptyeventfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP(GLFWemptyeventfun, _glfw.callbacks.emptyEvent, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||
{
|
||||
int jid;
|
||||
|
@ -866,6 +866,7 @@ struct _GLFWlibrary
|
||||
struct {
|
||||
GLFWmonitorfun monitor;
|
||||
GLFWjoystickfun joystick;
|
||||
GLFWemptyeventfun emptyEvent;
|
||||
} callbacks;
|
||||
|
||||
// These are defined in platform.h
|
||||
|
@ -363,6 +363,19 @@ static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// this check may not be necessary, but it checks just in case the message
|
||||
// has not been registered. this skips having to check uMsg != WM_NULL
|
||||
UINT emptyEventMsg = _glfw.win32.emptyEventMessage;
|
||||
if (emptyEventMsg != 0 && uMsg == emptyEventMsg)
|
||||
{
|
||||
if (_glfw.callbacks.emptyEvent)
|
||||
_glfw.callbacks.emptyEvent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
@ -405,6 +418,14 @@ static GLFWbool createHelperWindow(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.emptyEventMessage = RegisterWindowMessageW(L"GLFW.EmptyEventMessage");
|
||||
if (!_glfw.win32.emptyEventMessage)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register empty event message");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// HACK: The command to the first ShowWindow call is ignored if the parent
|
||||
// process passed along a STARTUPINFO, so clear that with a no-op call
|
||||
ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
|
||||
|
@ -457,6 +457,7 @@ typedef struct _GLFWlibraryWin32
|
||||
RAWINPUT* rawInput;
|
||||
int rawInputSize;
|
||||
UINT mouseTrailSize;
|
||||
UINT emptyEventMessage;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
|
@ -2128,7 +2128,7 @@ void _glfwWaitEventsTimeoutWin32(double timeout)
|
||||
|
||||
void _glfwPostEmptyEventWin32(void)
|
||||
{
|
||||
PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||
PostMessageW(_glfw.win32.helperWindowHandle, _glfw.win32.emptyEventMessage, 0, 0);
|
||||
}
|
||||
|
||||
void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
|
@ -23,6 +23,16 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
// TODO: Implement the postEmptyEvent test on multiple platforms. Works for Windows so far
|
||||
#ifdef WIN32
|
||||
#define USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
#include <Windows.h>
|
||||
#endif // USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
|
||||
|
||||
#define GLAD_GL_IMPLEMENTATION
|
||||
#include <glad/gl.h>
|
||||
#define GLFW_INCLUDE_NONE
|
||||
@ -48,6 +58,35 @@
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
|
||||
DWORD WINAPI win32ThreadEmptyEventTest(void)
|
||||
{
|
||||
// Sleep for 3 seconds, and then post an empty event. The onEmptyEventPosted
|
||||
// method should then be fired shortly after, on the GLFW main thread.
|
||||
|
||||
Sleep(3000);
|
||||
glfwPostEmptyEvent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void onEmptyEventPosted(void)
|
||||
{
|
||||
// If you hold your LMB down on the window border (aka initialise the resize
|
||||
// phase), you will see a big difference in stack trace here compared to
|
||||
// when not resizing. This is because DefWindowProc seems to use its own
|
||||
// message loop temporarily, and passes any unhandled messages back to the
|
||||
// dummy window's wndproc, which detects the empty event message, firing the
|
||||
// event callback.
|
||||
// This is the only effective way to run code on the main thread during the
|
||||
// window resize phase while the user isn't moving their mouse, apart from the
|
||||
// actual resize events obviously
|
||||
MessageBoxExW(NULL, L"Callback event received!", L"Empty Event Callback", NULL, NULL);
|
||||
// printf("Empty event received! Put a break point here, and this will be fired on the main thread");
|
||||
}
|
||||
|
||||
#endif // USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int windowed_x, windowed_y, windowed_width, windowed_height;
|
||||
@ -66,12 +105,14 @@ int main(int argc, char** argv)
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwSetEmptyEventCallback(onEmptyEventPosted);
|
||||
|
||||
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(600, 600, "Window Features", NULL, NULL);
|
||||
GLFWwindow* window = glfwCreateWindow(750, 600, "Window Features", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
@ -121,7 +162,7 @@ int main(int argc, char** argv)
|
||||
nk_glfw3_new_frame();
|
||||
if (nk_begin(nk, "main", area, 0))
|
||||
{
|
||||
nk_layout_row_dynamic(nk, 30, 5);
|
||||
nk_layout_row_dynamic(nk, 30, 6);
|
||||
|
||||
if (nk_button_label(nk, "Toggle Fullscreen"))
|
||||
{
|
||||
@ -156,10 +197,16 @@ int main(int argc, char** argv)
|
||||
const double time = glfwGetTime() + 3.0;
|
||||
while (glfwGetTime() < time)
|
||||
glfwWaitEventsTimeout(1.0);
|
||||
|
||||
glfwShowWindow(window);
|
||||
}
|
||||
|
||||
#ifdef USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
if (nk_button_label(nk, "Empty Event(3s)"))
|
||||
{
|
||||
CreateThread(NULL, 0, win32ThreadEmptyEventTest, NULL, 0, NULL);
|
||||
}
|
||||
#endif // USE_WIN32_THREAD_EMPTY_EVENT_TEST
|
||||
|
||||
nk_layout_row_dynamic(nk, 30, 1);
|
||||
|
||||
if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH))
|
||||
|
Loading…
Reference in New Issue
Block a user