2020-10-12 18:34:22 +03:00
// dear imgui: Platform Backend for GLFW
2021-01-28 14:11:26 +03:00
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
2018-02-22 01:05:17 +03:00
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
2019-08-29 16:53:33 +03:00
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
2018-02-16 23:38:38 +03:00
// Implemented features:
2018-06-11 13:33:51 +03:00
// [X] Platform: Clipboard support.
2018-09-20 11:37:55 +03:00
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
2019-12-05 17:43:05 +03:00
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
2018-06-30 15:33:45 +03:00
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
2018-06-12 17:24:24 +03:00
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
2018-02-16 23:38:38 +03:00
2020-07-17 16:57:50 +03:00
// Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
2020-10-14 13:22:53 +03:00
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
2018-02-16 23:38:38 +03:00
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2021-01-15 21:20:42 +03:00
// 2021-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
2020-01-17 13:36:56 +03:00
// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
2019-12-05 17:43:05 +03:00
// 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
2019-10-18 17:25:18 +03:00
// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
2019-07-22 04:39:50 +03:00
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
2019-05-11 11:33:56 +03:00
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
2019-03-12 20:27:14 +03:00
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
2018-11-30 20:18:15 +03:00
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
2018-11-08 18:24:41 +03:00
// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
2018-08-01 12:34:17 +03:00
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
2018-06-29 17:30:41 +03:00
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
2018-06-08 20:37:33 +03:00
// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
2018-04-07 00:34:43 +03:00
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
2018-04-09 20:35:14 +03:00
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
2018-02-16 23:38:38 +03:00
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
2018-02-28 20:51:40 +03:00
// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
2018-03-21 00:14:34 +03:00
// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
2018-02-16 23:38:38 +03:00
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
# include "imgui.h"
# include "imgui_impl_glfw.h"
2018-02-27 12:29:37 +03:00
// GLFW
2018-02-16 23:38:38 +03:00
# include <GLFW/glfw3.h>
# ifdef _WIN32
# undef APIENTRY
# define GLFW_EXPOSE_NATIVE_WIN32
2018-03-18 20:44:57 +03:00
# include <GLFW/glfw3native.h> // for glfwGetWin32Window
2018-02-16 23:38:38 +03:00
# endif
2019-05-11 11:54:56 +03:00
# define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING
# define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED
# define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity
# define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
# define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
# define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwFocusWindow
# define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
# define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorWorkarea
2020-03-26 10:42:04 +03:00
# define GLFW_HAS_OSX_WINDOW_POS_FIX (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION * 10 >= 3310) // 3.3.1+ Fixed: Resizing window repositions it on MacOS #1553
2019-12-13 19:06:27 +03:00
# ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
2019-12-05 17:43:05 +03:00
# define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
2019-12-06 17:08:04 +03:00
# else
# define GLFW_HAS_NEW_CURSORS (0)
# endif
2020-07-17 16:57:50 +03:00
# ifdef GLFW_MOUSE_PASSTHROUGH // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2020-07-17 (passthrough)
# define GLFW_HAS_MOUSE_PASSTHROUGH (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_MOUSE_PASSTHROUGH
# else
# define GLFW_HAS_MOUSE_PASSTHROUGH (0)
# endif
2018-04-11 22:27:19 +03:00
2018-02-16 23:38:38 +03:00
// Data
2018-03-02 21:23:01 +03:00
enum GlfwClientApi
{
GlfwClientApi_Unknown ,
GlfwClientApi_OpenGL ,
2021-02-10 19:27:33 +03:00
GlfwClientApi_Vulkan
2018-03-02 21:23:01 +03:00
} ;
2018-11-08 18:56:51 +03:00
static GLFWwindow * g_Window = NULL ; // Main window
2018-11-08 18:24:41 +03:00
static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown ;
static double g_Time = 0.0 ;
2020-05-25 12:42:20 +03:00
static bool g_MouseJustPressed [ ImGuiMouseButton_COUNT ] = { } ;
2019-10-18 13:54:30 +03:00
static GLFWcursor * g_MouseCursors [ ImGuiMouseCursor_COUNT ] = { } ;
2021-03-08 11:25:07 +03:00
static GLFWwindow * g_KeyOwnerWindows [ 512 ] = { } ;
2019-10-18 17:25:18 +03:00
static bool g_InstalledCallbacks = false ;
2018-11-08 18:56:51 +03:00
static bool g_WantUpdateMonitors = true ;
2018-11-08 18:24:41 +03:00
2018-11-08 18:56:51 +03:00
// Chain GLFW callbacks for main viewport: our callbacks will call the user's previously installed callbacks, if any.
2018-11-08 18:24:41 +03:00
static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL ;
static GLFWscrollfun g_PrevUserCallbackScroll = NULL ;
static GLFWkeyfun g_PrevUserCallbackKey = NULL ;
static GLFWcharfun g_PrevUserCallbackChar = NULL ;
2020-02-09 19:31:18 +03:00
static GLFWmonitorfun g_PrevUserCallbackMonitor = NULL ;
2018-02-16 23:38:38 +03:00
2018-02-28 01:27:41 +03:00
// Forward Declarations
2020-02-09 19:31:18 +03:00
static void ImGui_ImplGlfw_UpdateMonitors ( ) ;
2018-02-28 01:27:41 +03:00
static void ImGui_ImplGlfw_InitPlatformInterface ( ) ;
static void ImGui_ImplGlfw_ShutdownPlatformInterface ( ) ;
2018-02-27 12:29:37 +03:00
static const char * ImGui_ImplGlfw_GetClipboardText ( void * user_data )
2018-02-16 23:38:38 +03:00
{
return glfwGetClipboardString ( ( GLFWwindow * ) user_data ) ;
}
2018-02-27 12:29:37 +03:00
static void ImGui_ImplGlfw_SetClipboardText ( void * user_data , const char * text )
2018-02-16 23:38:38 +03:00
{
glfwSetClipboardString ( ( GLFWwindow * ) user_data , text ) ;
}
2018-11-08 18:24:41 +03:00
void ImGui_ImplGlfw_MouseButtonCallback ( GLFWwindow * window , int button , int action , int mods )
2018-02-16 23:38:38 +03:00
{
2018-11-08 18:56:51 +03:00
if ( g_PrevUserCallbackMousebutton ! = NULL & & window = = g_Window )
2018-11-08 18:24:41 +03:00
g_PrevUserCallbackMousebutton ( window , button , action , mods ) ;
2018-02-27 12:29:37 +03:00
if ( action = = GLFW_PRESS & & button > = 0 & & button < IM_ARRAYSIZE ( g_MouseJustPressed ) )
2018-02-16 23:38:38 +03:00
g_MouseJustPressed [ button ] = true ;
}
2018-11-08 18:24:41 +03:00
void ImGui_ImplGlfw_ScrollCallback ( GLFWwindow * window , double xoffset , double yoffset )
2018-02-16 23:38:38 +03:00
{
2018-11-08 18:56:51 +03:00
if ( g_PrevUserCallbackScroll ! = NULL & & window = = g_Window )
2018-11-08 18:24:41 +03:00
g_PrevUserCallbackScroll ( window , xoffset , yoffset ) ;
2018-02-16 23:38:38 +03:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . MouseWheelH + = ( float ) xoffset ;
io . MouseWheel + = ( float ) yoffset ;
}
2018-11-08 18:24:41 +03:00
void ImGui_ImplGlfw_KeyCallback ( GLFWwindow * window , int key , int scancode , int action , int mods )
2018-02-16 23:38:38 +03:00
{
2018-11-08 18:56:51 +03:00
if ( g_PrevUserCallbackKey ! = NULL & & window = = g_Window )
2018-11-08 18:24:41 +03:00
g_PrevUserCallbackKey ( window , key , scancode , action , mods ) ;
2018-02-16 23:38:38 +03:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
if ( action = = GLFW_PRESS )
2021-03-08 11:25:07 +03:00
{
2018-02-16 23:38:38 +03:00
io . KeysDown [ key ] = true ;
2021-03-08 11:25:07 +03:00
g_KeyOwnerWindows [ key ] = window ;
}
2018-02-16 23:38:38 +03:00
if ( action = = GLFW_RELEASE )
2021-03-08 11:25:07 +03:00
{
2018-02-16 23:38:38 +03:00
io . KeysDown [ key ] = false ;
2021-03-08 11:25:07 +03:00
g_KeyOwnerWindows [ key ] = NULL ;
}
2018-02-16 23:38:38 +03:00
2018-11-08 18:24:41 +03:00
// Modifiers are not reliable across systems
2018-02-16 23:38:38 +03:00
io . KeyCtrl = io . KeysDown [ GLFW_KEY_LEFT_CONTROL ] | | io . KeysDown [ GLFW_KEY_RIGHT_CONTROL ] ;
io . KeyShift = io . KeysDown [ GLFW_KEY_LEFT_SHIFT ] | | io . KeysDown [ GLFW_KEY_RIGHT_SHIFT ] ;
io . KeyAlt = io . KeysDown [ GLFW_KEY_LEFT_ALT ] | | io . KeysDown [ GLFW_KEY_RIGHT_ALT ] ;
2020-01-17 17:18:33 +03:00
# ifdef _WIN32
io . KeySuper = false ;
# else
2018-02-16 23:38:38 +03:00
io . KeySuper = io . KeysDown [ GLFW_KEY_LEFT_SUPER ] | | io . KeysDown [ GLFW_KEY_RIGHT_SUPER ] ;
2020-01-17 17:18:33 +03:00
# endif
2018-02-16 23:38:38 +03:00
}
2018-11-08 18:24:41 +03:00
void ImGui_ImplGlfw_CharCallback ( GLFWwindow * window , unsigned int c )
2018-02-16 23:38:38 +03:00
{
2018-11-08 18:56:51 +03:00
if ( g_PrevUserCallbackChar ! = NULL & & window = = g_Window )
2018-11-08 18:24:41 +03:00
g_PrevUserCallbackChar ( window , c ) ;
2018-02-16 23:38:38 +03:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2019-05-11 11:33:56 +03:00
io . AddInputCharacter ( c ) ;
2018-02-16 23:38:38 +03:00
}
2020-02-09 19:31:18 +03:00
void ImGui_ImplGlfw_MonitorCallback ( GLFWmonitor * , int )
{
g_WantUpdateMonitors = true ;
}
2018-03-15 18:42:21 +03:00
static bool ImGui_ImplGlfw_Init ( GLFWwindow * window , bool install_callbacks , GlfwClientApi client_api )
2018-02-16 23:38:38 +03:00
{
g_Window = window ;
2018-05-25 13:44:56 +03:00
g_Time = 0.0 ;
2018-02-16 23:38:38 +03:00
2020-10-12 18:34:22 +03:00
// Setup backend capabilities flags
2018-02-16 23:38:38 +03:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2018-03-21 00:14:34 +03:00
io . BackendFlags | = ImGuiBackendFlags_HasMouseCursors ; // We can honor GetMouseCursor() values (optional)
2018-05-11 15:05:40 +03:00
io . BackendFlags | = ImGuiBackendFlags_HasSetMousePos ; // We can honor io.WantSetMousePos requests (optional, rarely used)
2018-03-21 00:14:34 +03:00
io . BackendFlags | = ImGuiBackendFlags_PlatformHasViewports ; // We can create multi-viewports on the Platform side (optional)
2020-07-17 16:57:50 +03:00
# if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
2018-03-21 00:14:34 +03:00
io . BackendFlags | = ImGuiBackendFlags_HasMouseHoveredViewport ; // We can set io.MouseHoveredViewport correctly (optional, not easy)
# endif
2018-11-30 20:18:15 +03:00
io . BackendPlatformName = " imgui_impl_glfw " ;
2018-03-21 00:14:34 +03:00
2021-03-04 13:03:40 +03:00
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
2018-03-21 00:14:34 +03:00
io . KeyMap [ ImGuiKey_Tab ] = GLFW_KEY_TAB ;
2018-02-16 23:38:38 +03:00
io . KeyMap [ ImGuiKey_LeftArrow ] = GLFW_KEY_LEFT ;
io . KeyMap [ ImGuiKey_RightArrow ] = GLFW_KEY_RIGHT ;
io . KeyMap [ ImGuiKey_UpArrow ] = GLFW_KEY_UP ;
io . KeyMap [ ImGuiKey_DownArrow ] = GLFW_KEY_DOWN ;
io . KeyMap [ ImGuiKey_PageUp ] = GLFW_KEY_PAGE_UP ;
io . KeyMap [ ImGuiKey_PageDown ] = GLFW_KEY_PAGE_DOWN ;
io . KeyMap [ ImGuiKey_Home ] = GLFW_KEY_HOME ;
io . KeyMap [ ImGuiKey_End ] = GLFW_KEY_END ;
io . KeyMap [ ImGuiKey_Insert ] = GLFW_KEY_INSERT ;
io . KeyMap [ ImGuiKey_Delete ] = GLFW_KEY_DELETE ;
io . KeyMap [ ImGuiKey_Backspace ] = GLFW_KEY_BACKSPACE ;
io . KeyMap [ ImGuiKey_Space ] = GLFW_KEY_SPACE ;
io . KeyMap [ ImGuiKey_Enter ] = GLFW_KEY_ENTER ;
io . KeyMap [ ImGuiKey_Escape ] = GLFW_KEY_ESCAPE ;
2019-07-22 04:39:50 +03:00
io . KeyMap [ ImGuiKey_KeyPadEnter ] = GLFW_KEY_KP_ENTER ;
2018-02-16 23:38:38 +03:00
io . KeyMap [ ImGuiKey_A ] = GLFW_KEY_A ;
io . KeyMap [ ImGuiKey_C ] = GLFW_KEY_C ;
io . KeyMap [ ImGuiKey_V ] = GLFW_KEY_V ;
io . KeyMap [ ImGuiKey_X ] = GLFW_KEY_X ;
io . KeyMap [ ImGuiKey_Y ] = GLFW_KEY_Y ;
io . KeyMap [ ImGuiKey_Z ] = GLFW_KEY_Z ;
2018-02-27 12:29:37 +03:00
io . SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText ;
io . GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText ;
2018-02-16 23:38:38 +03:00
io . ClipboardUserData = g_Window ;
2020-01-17 13:36:56 +03:00
// Create mouse cursors
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
// Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
GLFWerrorfun prev_error_callback = glfwSetErrorCallback ( NULL ) ;
2018-02-20 00:29:52 +03:00
g_MouseCursors [ ImGuiMouseCursor_Arrow ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_TextInput ] = glfwCreateStandardCursor ( GLFW_IBEAM_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNS ] = glfwCreateStandardCursor ( GLFW_VRESIZE_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeEW ] = glfwCreateStandardCursor ( GLFW_HRESIZE_CURSOR ) ;
2018-06-29 13:16:17 +03:00
g_MouseCursors [ ImGuiMouseCursor_Hand ] = glfwCreateStandardCursor ( GLFW_HAND_CURSOR ) ;
2019-12-02 11:36:59 +03:00
# if GLFW_HAS_NEW_CURSORS
g_MouseCursors [ ImGuiMouseCursor_ResizeAll ] = glfwCreateStandardCursor ( GLFW_RESIZE_ALL_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNESW ] = glfwCreateStandardCursor ( GLFW_RESIZE_NESW_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNWSE ] = glfwCreateStandardCursor ( GLFW_RESIZE_NWSE_CURSOR ) ;
2019-12-02 11:52:06 +03:00
g_MouseCursors [ ImGuiMouseCursor_NotAllowed ] = glfwCreateStandardCursor ( GLFW_NOT_ALLOWED_CURSOR ) ;
2019-12-02 11:36:59 +03:00
# else
g_MouseCursors [ ImGuiMouseCursor_ResizeAll ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNESW ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNWSE ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
2019-12-02 11:52:06 +03:00
g_MouseCursors [ ImGuiMouseCursor_NotAllowed ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
2019-12-02 11:36:59 +03:00
# endif
2020-01-17 13:36:56 +03:00
glfwSetErrorCallback ( prev_error_callback ) ;
2019-01-20 19:56:17 +03:00
2018-11-08 18:24:41 +03:00
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
g_PrevUserCallbackMousebutton = NULL ;
g_PrevUserCallbackScroll = NULL ;
g_PrevUserCallbackKey = NULL ;
g_PrevUserCallbackChar = NULL ;
2020-02-09 19:31:18 +03:00
g_PrevUserCallbackMonitor = NULL ;
2018-02-16 23:38:38 +03:00
if ( install_callbacks )
2018-11-08 18:06:22 +03:00
{
2019-10-18 17:25:18 +03:00
g_InstalledCallbacks = true ;
2018-11-08 18:24:41 +03:00
g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback ( window , ImGui_ImplGlfw_MouseButtonCallback ) ;
g_PrevUserCallbackScroll = glfwSetScrollCallback ( window , ImGui_ImplGlfw_ScrollCallback ) ;
g_PrevUserCallbackKey = glfwSetKeyCallback ( window , ImGui_ImplGlfw_KeyCallback ) ;
g_PrevUserCallbackChar = glfwSetCharCallback ( window , ImGui_ImplGlfw_CharCallback ) ;
2020-02-09 19:31:18 +03:00
g_PrevUserCallbackMonitor = glfwSetMonitorCallback ( ImGui_ImplGlfw_MonitorCallback ) ;
2018-11-08 18:06:22 +03:00
}
2018-02-16 23:38:38 +03:00
2020-02-09 19:31:18 +03:00
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
ImGui_ImplGlfw_UpdateMonitors ( ) ;
glfwSetMonitorCallback ( ImGui_ImplGlfw_MonitorCallback ) ;
2018-02-28 01:27:41 +03:00
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
main_viewport - > PlatformHandle = ( void * ) g_Window ;
2019-06-19 00:35:48 +03:00
# ifdef _WIN32
main_viewport - > PlatformHandleRaw = glfwGetWin32Window ( g_Window ) ;
# endif
2018-04-10 20:21:52 +03:00
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
2018-02-28 01:27:41 +03:00
ImGui_ImplGlfw_InitPlatformInterface ( ) ;
2018-03-15 18:42:21 +03:00
g_ClientApi = client_api ;
2018-03-02 21:23:01 +03:00
return true ;
}
2018-03-15 18:42:21 +03:00
bool ImGui_ImplGlfw_InitForOpenGL ( GLFWwindow * window , bool install_callbacks )
{
return ImGui_ImplGlfw_Init ( window , install_callbacks , GlfwClientApi_OpenGL ) ;
}
2018-03-02 21:23:01 +03:00
bool ImGui_ImplGlfw_InitForVulkan ( GLFWwindow * window , bool install_callbacks )
{
2018-03-15 18:42:21 +03:00
return ImGui_ImplGlfw_Init ( window , install_callbacks , GlfwClientApi_Vulkan ) ;
2018-02-16 23:38:38 +03:00
}
2021-02-10 19:27:33 +03:00
bool ImGui_ImplGlfw_InitForOther ( GLFWwindow * window , bool install_callbacks )
2021-01-28 14:11:26 +03:00
{
2021-02-10 19:27:33 +03:00
return ImGui_ImplGlfw_Init ( window , install_callbacks , GlfwClientApi_Unknown ) ;
2021-01-28 14:11:26 +03:00
}
2018-02-16 23:38:38 +03:00
void ImGui_ImplGlfw_Shutdown ( )
{
2018-02-28 01:27:41 +03:00
ImGui_ImplGlfw_ShutdownPlatformInterface ( ) ;
2019-10-18 17:25:18 +03:00
if ( g_InstalledCallbacks )
{
glfwSetMouseButtonCallback ( g_Window , g_PrevUserCallbackMousebutton ) ;
glfwSetScrollCallback ( g_Window , g_PrevUserCallbackScroll ) ;
glfwSetKeyCallback ( g_Window , g_PrevUserCallbackKey ) ;
glfwSetCharCallback ( g_Window , g_PrevUserCallbackChar ) ;
g_InstalledCallbacks = false ;
}
2018-06-20 12:06:29 +03:00
for ( ImGuiMouseCursor cursor_n = 0 ; cursor_n < ImGuiMouseCursor_COUNT ; cursor_n + + )
2018-02-20 00:29:52 +03:00
{
glfwDestroyCursor ( g_MouseCursors [ cursor_n ] ) ;
g_MouseCursors [ cursor_n ] = NULL ;
}
2018-03-02 21:23:01 +03:00
g_ClientApi = GlfwClientApi_Unknown ;
2018-02-16 23:38:38 +03:00
}
2018-05-11 17:41:32 +03:00
static void ImGui_ImplGlfw_UpdateMousePosAndButtons ( )
2018-02-16 23:38:38 +03:00
{
2018-02-27 12:29:37 +03:00
// Update buttons
2019-06-06 17:16:18 +03:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2018-02-27 12:29:37 +03:00
for ( int i = 0 ; i < IM_ARRAYSIZE ( io . MouseDown ) ; i + + )
{
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io . MouseDown [ i ] = g_MouseJustPressed [ i ] | | glfwGetMouseButton ( g_Window , i ) ! = 0 ;
g_MouseJustPressed [ i ] = false ;
}
2018-02-16 23:38:38 +03:00
2019-06-06 17:16:18 +03:00
// Update mouse position
const ImVec2 mouse_pos_backup = io . MousePos ;
io . MousePos = ImVec2 ( - FLT_MAX , - FLT_MAX ) ;
io . MouseHoveredViewport = 0 ;
2018-04-10 23:58:39 +03:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int n = 0 ; n < platform_io . Viewports . Size ; n + + )
2018-02-16 23:38:38 +03:00
{
2018-04-10 23:58:39 +03:00
ImGuiViewport * viewport = platform_io . Viewports [ n ] ;
2018-02-28 01:27:41 +03:00
GLFWwindow * window = ( GLFWwindow * ) viewport - > PlatformHandle ;
IM_ASSERT ( window ! = NULL ) ;
2018-08-01 12:34:17 +03:00
# ifdef __EMSCRIPTEN__
2018-08-01 13:27:56 +03:00
const bool focused = true ;
IM_ASSERT ( platform_io . Viewports . Size = = 1 ) ;
2018-08-01 12:34:17 +03:00
# else
2018-08-01 13:27:56 +03:00
const bool focused = glfwGetWindowAttrib ( window , GLFW_FOCUSED ) ! = 0 ;
2018-08-01 12:34:17 +03:00
# endif
2018-08-01 13:27:56 +03:00
if ( focused )
2018-02-16 23:38:38 +03:00
{
2018-05-11 15:05:40 +03:00
if ( io . WantSetMousePos )
{
glfwSetCursorPos ( window , ( double ) ( mouse_pos_backup . x - viewport - > Pos . x ) , ( double ) ( mouse_pos_backup . y - viewport - > Pos . y ) ) ;
}
else
{
double mouse_x , mouse_y ;
glfwGetCursorPos ( window , & mouse_x , & mouse_y ) ;
2018-12-06 18:30:10 +03:00
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
{
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
int window_x , window_y ;
glfwGetWindowPos ( window , & window_x , & window_y ) ;
io . MousePos = ImVec2 ( ( float ) mouse_x + window_x , ( float ) mouse_y + window_y ) ;
}
else
{
// Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
io . MousePos = ImVec2 ( ( float ) mouse_x , ( float ) mouse_y ) ;
}
2018-05-11 15:05:40 +03:00
}
2018-02-28 01:27:41 +03:00
for ( int i = 0 ; i < IM_ARRAYSIZE ( io . MouseDown ) ; i + + )
io . MouseDown [ i ] | = glfwGetMouseButton ( window , i ) ! = 0 ;
2018-02-16 23:38:38 +03:00
}
2018-02-28 01:27:41 +03:00
2018-12-06 18:30:10 +03:00
// (Optional) When using multiple viewports: set io.MouseHoveredViewport to the viewport the OS mouse cursor is hovering.
// Important: this information is not easy to provide and many high-level windowing library won't be able to provide it correctly, because
// - This is _ignoring_ viewports with the ImGuiViewportFlags_NoInputs flag (pass-through windows).
// - This is _regardless_ of whether another viewport is focused or being dragged from.
2020-10-14 15:43:45 +03:00
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, imgui will ignore this field and infer the information by relying on the
2018-12-06 18:30:10 +03:00
// rectangles and last focused time of every viewports it knows about. It will be unaware of other windows that may be sitting between or over your windows.
// [GLFW] FIXME: This is currently only correct on Win32. See what we do below with the WM_NCHITTEST, missing an equivalent for other systems.
// See https://github.com/glfw/glfw/issues/1236 if you want to help in making this a GLFW feature.
2020-07-17 16:57:50 +03:00
# if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
const bool window_no_input = ( viewport - > Flags & ImGuiViewportFlags_NoInputs ) ! = 0 ;
# if GLFW_HAS_MOUSE_PASSTHROUGH
glfwSetWindowAttrib ( window , GLFW_MOUSE_PASSTHROUGH , window_no_input ) ;
# endif
if ( glfwGetWindowAttrib ( window , GLFW_HOVERED ) & & ! window_no_input )
2018-02-28 01:27:41 +03:00
io . MouseHoveredViewport = viewport - > ID ;
# endif
}
2018-05-11 17:41:32 +03:00
}
static void ImGui_ImplGlfw_UpdateMouseCursor ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
if ( ( io . ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange ) | | glfwGetInputMode ( g_Window , GLFW_CURSOR ) = = GLFW_CURSOR_DISABLED )
return ;
2018-02-28 01:27:41 +03:00
2018-05-11 17:41:32 +03:00
ImGuiMouseCursor imgui_cursor = ImGui : : GetMouseCursor ( ) ;
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int n = 0 ; n < platform_io . Viewports . Size ; n + + )
2018-02-16 23:38:38 +03:00
{
2018-05-11 17:41:32 +03:00
GLFWwindow * window = ( GLFWwindow * ) platform_io . Viewports [ n ] - > PlatformHandle ;
if ( imgui_cursor = = ImGuiMouseCursor_None | | io . MouseDrawCursor )
2018-03-21 00:14:34 +03:00
{
2018-05-11 17:41:32 +03:00
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode ( window , GLFW_CURSOR , GLFW_CURSOR_HIDDEN ) ;
}
else
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor ( window , g_MouseCursors [ imgui_cursor ] ? g_MouseCursors [ imgui_cursor ] : g_MouseCursors [ ImGuiMouseCursor_Arrow ] ) ;
glfwSetInputMode ( window , GLFW_CURSOR , GLFW_CURSOR_NORMAL ) ;
2018-03-21 00:14:34 +03:00
}
2018-02-16 23:38:38 +03:00
}
2018-02-27 12:29:37 +03:00
}
2019-02-14 20:55:08 +03:00
static void ImGui_ImplGlfw_UpdateGamepads ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
memset ( io . NavInputs , 0 , sizeof ( io . NavInputs ) ) ;
if ( ( io . ConfigFlags & ImGuiConfigFlags_NavEnableGamepad ) = = 0 )
return ;
// Update gamepad inputs
# define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
# define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
int axes_count = 0 , buttons_count = 0 ;
const float * axes = glfwGetJoystickAxes ( GLFW_JOYSTICK_1 , & axes_count ) ;
const unsigned char * buttons = glfwGetJoystickButtons ( GLFW_JOYSTICK_1 , & buttons_count ) ;
MAP_BUTTON ( ImGuiNavInput_Activate , 0 ) ; // Cross / A
MAP_BUTTON ( ImGuiNavInput_Cancel , 1 ) ; // Circle / B
MAP_BUTTON ( ImGuiNavInput_Menu , 2 ) ; // Square / X
MAP_BUTTON ( ImGuiNavInput_Input , 3 ) ; // Triangle / Y
MAP_BUTTON ( ImGuiNavInput_DpadLeft , 13 ) ; // D-Pad Left
MAP_BUTTON ( ImGuiNavInput_DpadRight , 11 ) ; // D-Pad Right
MAP_BUTTON ( ImGuiNavInput_DpadUp , 10 ) ; // D-Pad Up
MAP_BUTTON ( ImGuiNavInput_DpadDown , 12 ) ; // D-Pad Down
MAP_BUTTON ( ImGuiNavInput_FocusPrev , 4 ) ; // L1 / LB
MAP_BUTTON ( ImGuiNavInput_FocusNext , 5 ) ; // R1 / RB
MAP_BUTTON ( ImGuiNavInput_TweakSlow , 4 ) ; // L1 / LB
MAP_BUTTON ( ImGuiNavInput_TweakFast , 5 ) ; // R1 / RB
MAP_ANALOG ( ImGuiNavInput_LStickLeft , 0 , - 0.3f , - 0.9f ) ;
MAP_ANALOG ( ImGuiNavInput_LStickRight , 0 , + 0.3f , + 0.9f ) ;
MAP_ANALOG ( ImGuiNavInput_LStickUp , 1 , + 0.3f , + 0.9f ) ;
MAP_ANALOG ( ImGuiNavInput_LStickDown , 1 , - 0.3f , - 0.9f ) ;
# undef MAP_BUTTON
# undef MAP_ANALOG
if ( axes_count > 0 & & buttons_count > 0 )
io . BackendFlags | = ImGuiBackendFlags_HasGamepad ;
else
io . BackendFlags & = ~ ImGuiBackendFlags_HasGamepad ;
}
2020-02-09 19:31:18 +03:00
static void ImGui_ImplGlfw_UpdateMonitors ( )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
int monitors_count = 0 ;
GLFWmonitor * * glfw_monitors = glfwGetMonitors ( & monitors_count ) ;
platform_io . Monitors . resize ( 0 ) ;
for ( int n = 0 ; n < monitors_count ; n + + )
{
ImGuiPlatformMonitor monitor ;
int x , y ;
glfwGetMonitorPos ( glfw_monitors [ n ] , & x , & y ) ;
const GLFWvidmode * vid_mode = glfwGetVideoMode ( glfw_monitors [ n ] ) ;
2020-09-04 18:26:31 +03:00
monitor . MainPos = monitor . WorkPos = ImVec2 ( ( float ) x , ( float ) y ) ;
monitor . MainSize = monitor . WorkSize = ImVec2 ( ( float ) vid_mode - > width , ( float ) vid_mode - > height ) ;
2020-02-09 19:31:18 +03:00
# if GLFW_HAS_MONITOR_WORK_AREA
int w , h ;
glfwGetMonitorWorkarea ( glfw_monitors [ n ] , & x , & y , & w , & h ) ;
2020-09-04 18:26:31 +03:00
if ( w > 0 & & h > 0 ) // Workaround a small GLFW issue reporting zero on monitor changes: https://github.com/glfw/glfw/pull/1761
{
monitor . WorkPos = ImVec2 ( ( float ) x , ( float ) y ) ;
monitor . WorkSize = ImVec2 ( ( float ) w , ( float ) h ) ;
}
2020-02-09 19:31:18 +03:00
# endif
# if GLFW_HAS_PER_MONITOR_DPI
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
float x_scale , y_scale ;
glfwGetMonitorContentScale ( glfw_monitors [ n ] , & x_scale , & y_scale ) ;
monitor . DpiScale = x_scale ;
# endif
platform_io . Monitors . push_back ( monitor ) ;
}
g_WantUpdateMonitors = false ;
}
2018-02-27 12:29:37 +03:00
void ImGui_ImplGlfw_NewFrame ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
2020-10-12 18:34:22 +03:00
IM_ASSERT ( io . Fonts - > IsBuilt ( ) & & " Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame(). " ) ;
2018-02-27 12:29:37 +03:00
2018-12-23 19:39:04 +03:00
// Setup display size (every frame to accommodate for window resizing)
2018-02-27 12:29:37 +03:00
int w , h ;
int display_w , display_h ;
glfwGetWindowSize ( g_Window , & w , & h ) ;
glfwGetFramebufferSize ( g_Window , & display_w , & display_h ) ;
io . DisplaySize = ImVec2 ( ( float ) w , ( float ) h ) ;
2019-03-12 20:27:14 +03:00
if ( w > 0 & & h > 0 )
io . DisplayFramebufferScale = ImVec2 ( ( float ) display_w / w , ( float ) display_h / h ) ;
2018-04-26 17:07:54 +03:00
if ( g_WantUpdateMonitors )
ImGui_ImplGlfw_UpdateMonitors ( ) ;
2018-02-27 12:29:37 +03:00
// Setup time step
2018-02-28 01:27:41 +03:00
double current_time = glfwGetTime ( ) ;
2020-06-30 16:31:54 +03:00
io . DeltaTime = g_Time > 0.0 ? ( float ) ( current_time - g_Time ) : ( float ) ( 1.0f / 60.0f ) ;
2018-02-27 12:29:37 +03:00
g_Time = current_time ;
2018-05-11 17:41:32 +03:00
ImGui_ImplGlfw_UpdateMousePosAndButtons ( ) ;
ImGui_ImplGlfw_UpdateMouseCursor ( ) ;
2018-02-16 23:38:38 +03:00
2019-04-23 13:26:14 +03:00
// Update game controllers (if enabled and available)
2019-02-14 20:55:08 +03:00
ImGui_ImplGlfw_UpdateGamepads ( ) ;
2018-02-16 23:38:38 +03:00
}
2018-02-28 01:27:41 +03:00
2018-04-24 18:09:50 +03:00
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
2020-10-14 15:43:45 +03:00
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
2018-04-24 18:09:50 +03:00
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
2018-02-28 01:27:41 +03:00
2020-01-20 21:33:46 +03:00
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
2018-03-19 00:19:02 +03:00
struct ImGuiViewportDataGlfw
2018-02-28 01:27:41 +03:00
{
GLFWwindow * Window ;
bool WindowOwned ;
2020-04-15 15:00:37 +03:00
int IgnoreWindowPosEventFrame ;
2019-08-29 16:53:33 +03:00
int IgnoreWindowSizeEventFrame ;
2018-02-28 01:27:41 +03:00
2020-04-15 15:00:37 +03:00
ImGuiViewportDataGlfw ( ) { Window = NULL ; WindowOwned = false ; IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = - 1 ; }
2018-03-19 00:19:02 +03:00
~ ImGuiViewportDataGlfw ( ) { IM_ASSERT ( Window = = NULL ) ; }
2018-02-28 01:27:41 +03:00
} ;
2018-03-15 12:54:27 +03:00
static void ImGui_ImplGlfw_WindowCloseCallback ( GLFWwindow * window )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
viewport - > PlatformRequestClose = true ;
}
2020-04-15 15:00:37 +03:00
// GLFW may dispatch window pos/size events after calling glfwSetWindowPos()/glfwSetWindowSize().
// However: depending on the platform the callback may be invoked at different time:
// - on Windows it appears to be called within the glfwSetWindowPos()/glfwSetWindowSize() call
// - on Linux it is queued and invoked during glfwPollEvents()
// Because the event doesn't always fire on glfwSetWindowXXX() we use a frame counter tag to only
// ignore recent glfwSetWindowXXX() calls.
2018-03-15 12:54:27 +03:00
static void ImGui_ImplGlfw_WindowPosCallback ( GLFWwindow * window , int , int )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
2020-04-15 15:00:37 +03:00
{
if ( ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData )
{
bool ignore_event = ( ImGui : : GetFrameCount ( ) < = data - > IgnoreWindowPosEventFrame + 1 ) ;
//data->IgnoreWindowPosEventFrame = -1;
if ( ignore_event )
return ;
}
2018-03-15 12:54:27 +03:00
viewport - > PlatformRequestMove = true ;
2020-04-15 15:00:37 +03:00
}
2018-03-15 12:54:27 +03:00
}
static void ImGui_ImplGlfw_WindowSizeCallback ( GLFWwindow * window , int , int )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
2019-08-23 16:12:06 +03:00
{
if ( ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData )
{
2019-08-29 16:53:33 +03:00
bool ignore_event = ( ImGui : : GetFrameCount ( ) < = data - > IgnoreWindowSizeEventFrame + 1 ) ;
2020-04-15 15:00:37 +03:00
//data->IgnoreWindowSizeEventFrame = -1;
2019-08-29 16:53:33 +03:00
if ( ignore_event )
2019-08-23 16:12:06 +03:00
return ;
}
2018-03-15 12:54:27 +03:00
viewport - > PlatformRequestResize = true ;
2019-08-23 16:12:06 +03:00
}
2018-03-15 12:54:27 +03:00
}
2018-03-18 20:44:57 +03:00
static void ImGui_ImplGlfw_CreateWindow ( ImGuiViewport * viewport )
2018-02-28 01:27:41 +03:00
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = IM_NEW ( ImGuiViewportDataGlfw ) ( ) ;
2018-02-28 01:27:41 +03:00
viewport - > PlatformUserData = data ;
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
2019-05-11 11:54:56 +03:00
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
2018-02-28 01:27:41 +03:00
glfwWindowHint ( GLFW_VISIBLE , false ) ;
glfwWindowHint ( GLFW_FOCUSED , false ) ;
2019-05-11 11:54:56 +03:00
# if GLFW_HAS_FOCUS_ON_SHOW
2021-02-18 14:53:15 +03:00
glfwWindowHint ( GLFW_FOCUS_ON_SHOW , false ) ;
2019-05-11 11:54:56 +03:00
# endif
2018-02-28 01:27:41 +03:00
glfwWindowHint ( GLFW_DECORATED , ( viewport - > Flags & ImGuiViewportFlags_NoDecoration ) ? false : true ) ;
2018-04-11 22:27:19 +03:00
# if GLFW_HAS_WINDOW_TOPMOST
2018-05-10 13:10:10 +03:00
glfwWindowHint ( GLFW_FLOATING , ( viewport - > Flags & ImGuiViewportFlags_TopMost ) ? true : false ) ;
2018-04-11 22:27:19 +03:00
# endif
2018-03-02 21:23:01 +03:00
GLFWwindow * share_window = ( g_ClientApi = = GlfwClientApi_OpenGL ) ? g_Window : NULL ;
data - > Window = glfwCreateWindow ( ( int ) viewport - > Size . x , ( int ) viewport - > Size . y , " No Title Yet " , NULL , share_window ) ;
2018-02-28 01:27:41 +03:00
data - > WindowOwned = true ;
viewport - > PlatformHandle = ( void * ) data - > Window ;
2019-06-19 00:35:48 +03:00
# ifdef _WIN32
viewport - > PlatformHandleRaw = glfwGetWin32Window ( data - > Window ) ;
# endif
2018-11-23 17:50:33 +03:00
glfwSetWindowPos ( data - > Window , ( int ) viewport - > Pos . x , ( int ) viewport - > Pos . y ) ;
2018-11-08 18:56:51 +03:00
2020-01-20 21:33:46 +03:00
// Install GLFW callbacks for secondary viewports
2018-11-08 18:56:51 +03:00
glfwSetMouseButtonCallback ( data - > Window , ImGui_ImplGlfw_MouseButtonCallback ) ;
glfwSetScrollCallback ( data - > Window , ImGui_ImplGlfw_ScrollCallback ) ;
glfwSetKeyCallback ( data - > Window , ImGui_ImplGlfw_KeyCallback ) ;
glfwSetCharCallback ( data - > Window , ImGui_ImplGlfw_CharCallback ) ;
2018-03-15 12:54:27 +03:00
glfwSetWindowCloseCallback ( data - > Window , ImGui_ImplGlfw_WindowCloseCallback ) ;
glfwSetWindowPosCallback ( data - > Window , ImGui_ImplGlfw_WindowPosCallback ) ;
glfwSetWindowSizeCallback ( data - > Window , ImGui_ImplGlfw_WindowSizeCallback ) ;
2018-08-25 21:15:18 +03:00
if ( g_ClientApi = = GlfwClientApi_OpenGL )
{
glfwMakeContextCurrent ( data - > Window ) ;
glfwSwapInterval ( 0 ) ;
}
2018-02-28 01:27:41 +03:00
}
2018-03-18 20:44:57 +03:00
static void ImGui_ImplGlfw_DestroyWindow ( ImGuiViewport * viewport )
2018-02-28 01:27:41 +03:00
{
2018-03-19 00:19:02 +03:00
if ( ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData )
2018-02-28 01:27:41 +03:00
{
2018-04-09 23:01:24 +03:00
if ( data - > WindowOwned )
{
2020-07-17 16:57:50 +03:00
# if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
2019-06-19 00:35:48 +03:00
HWND hwnd = ( HWND ) viewport - > PlatformHandleRaw ;
2018-04-09 23:01:24 +03:00
: : RemovePropA ( hwnd , " IMGUI_VIEWPORT " ) ;
# endif
2021-03-08 11:25:07 +03:00
// Release any keys that were pressed in the window being destroyed and are still held down,
// because we will not receive any release events after window is destroyed.
for ( int i = 0 ; i < IM_ARRAYSIZE ( g_KeyOwnerWindows ) ; i + + )
if ( g_KeyOwnerWindows [ i ] = = data - > Window )
ImGui_ImplGlfw_KeyCallback ( data - > Window , i , 0 , GLFW_RELEASE , 0 ) ; // Later params are only used for main viewport, on which this function is never called.
2018-02-28 01:27:41 +03:00
glfwDestroyWindow ( data - > Window ) ;
2018-04-09 23:01:24 +03:00
}
2018-02-28 01:27:41 +03:00
data - > Window = NULL ;
IM_DELETE ( data ) ;
}
viewport - > PlatformUserData = viewport - > PlatformHandle = NULL ;
}
2020-01-20 21:33:46 +03:00
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
2020-07-17 16:57:50 +03:00
# if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
2018-02-28 01:27:41 +03:00
static WNDPROC g_GlfwWndProc = NULL ;
static LRESULT CALLBACK WndProcNoInputs ( HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam )
{
if ( msg = = WM_NCHITTEST )
{
2020-10-14 15:43:45 +03:00
// Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL).
2018-04-05 13:00:07 +03:00
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
2020-03-06 19:53:09 +03:00
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
2018-02-28 01:27:41 +03:00
ImGuiViewport * viewport = ( ImGuiViewport * ) : : GetPropA ( hWnd , " IMGUI_VIEWPORT " ) ;
if ( viewport - > Flags & ImGuiViewportFlags_NoInputs )
return HTTRANSPARENT ;
}
return : : CallWindowProc ( g_GlfwWndProc , hWnd , msg , wParam , lParam ) ;
}
# endif
static void ImGui_ImplGlfw_ShowWindow ( ImGuiViewport * viewport )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-28 01:27:41 +03:00
# if defined(_WIN32)
// GLFW hack: Hide icon from task bar
2019-06-19 00:35:48 +03:00
HWND hwnd = ( HWND ) viewport - > PlatformHandleRaw ;
2018-04-10 20:15:44 +03:00
if ( viewport - > Flags & ImGuiViewportFlags_NoTaskBarIcon )
2018-02-28 01:27:41 +03:00
{
LONG ex_style = : : GetWindowLong ( hwnd , GWL_EXSTYLE ) ;
ex_style & = ~ WS_EX_APPWINDOW ;
ex_style | = WS_EX_TOOLWINDOW ;
: : SetWindowLong ( hwnd , GWL_EXSTYLE , ex_style ) ;
}
// GLFW hack: install hook for WM_NCHITTEST message handler
2020-07-17 16:57:50 +03:00
# if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
2018-02-28 01:27:41 +03:00
: : SetPropA ( hwnd , " IMGUI_VIEWPORT " , viewport ) ;
if ( g_GlfwWndProc = = NULL )
g_GlfwWndProc = ( WNDPROC ) : : GetWindowLongPtr ( hwnd , GWLP_WNDPROC ) ;
: : SetWindowLongPtr ( hwnd , GWLP_WNDPROC , ( LONG_PTR ) WndProcNoInputs ) ;
# endif
2019-05-11 11:54:56 +03:00
# if !GLFW_HAS_FOCUS_ON_SHOW
2018-02-28 01:27:41 +03:00
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
2019-02-19 18:36:06 +03:00
// The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3 via a GLFW_FOCUS_ON_SHOW window attribute.
// See https://github.com/glfw/glfw/issues/1189
// FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.
2018-02-28 01:27:41 +03:00
if ( viewport - > Flags & ImGuiViewportFlags_NoFocusOnAppearing )
{
: : ShowWindow ( hwnd , SW_SHOWNA ) ;
return ;
}
2019-05-11 11:54:56 +03:00
# endif
2018-02-28 01:27:41 +03:00
# endif
glfwShowWindow ( data - > Window ) ;
}
static ImVec2 ImGui_ImplGlfw_GetWindowPos ( ImGuiViewport * viewport )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-28 01:27:41 +03:00
int x = 0 , y = 0 ;
glfwGetWindowPos ( data - > Window , & x , & y ) ;
return ImVec2 ( ( float ) x , ( float ) y ) ;
}
static void ImGui_ImplGlfw_SetWindowPos ( ImGuiViewport * viewport , ImVec2 pos )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2020-04-15 15:00:37 +03:00
data - > IgnoreWindowPosEventFrame = ImGui : : GetFrameCount ( ) ;
2018-02-28 01:27:41 +03:00
glfwSetWindowPos ( data - > Window , ( int ) pos . x , ( int ) pos . y ) ;
}
static ImVec2 ImGui_ImplGlfw_GetWindowSize ( ImGuiViewport * viewport )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-28 01:27:41 +03:00
int w = 0 , h = 0 ;
glfwGetWindowSize ( data - > Window , & w , & h ) ;
return ImVec2 ( ( float ) w , ( float ) h ) ;
}
static void ImGui_ImplGlfw_SetWindowSize ( ImGuiViewport * viewport , ImVec2 size )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2020-03-26 10:42:04 +03:00
# if __APPLE__ && !GLFW_HAS_OSX_WINDOW_POS_FIX
2019-08-29 14:02:42 +03:00
// Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
// positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
// doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
// on the upper-left corner.
int x , y , width , height ;
glfwGetWindowPos ( data - > Window , & x , & y ) ;
glfwGetWindowSize ( data - > Window , & width , & height ) ;
glfwSetWindowPos ( data - > Window , x , y - height + size . y ) ;
# endif
2019-08-29 16:53:33 +03:00
data - > IgnoreWindowSizeEventFrame = ImGui : : GetFrameCount ( ) ;
2018-02-28 01:27:41 +03:00
glfwSetWindowSize ( data - > Window , ( int ) size . x , ( int ) size . y ) ;
}
static void ImGui_ImplGlfw_SetWindowTitle ( ImGuiViewport * viewport , const char * title )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-28 01:27:41 +03:00
glfwSetWindowTitle ( data - > Window , title ) ;
}
2018-04-25 16:15:14 +03:00
static void ImGui_ImplGlfw_SetWindowFocus ( ImGuiViewport * viewport )
{
2018-09-20 19:46:36 +03:00
# if GLFW_HAS_FOCUS_WINDOW
2018-04-25 16:15:14 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
glfwFocusWindow ( data - > Window ) ;
2018-09-20 19:46:36 +03:00
# else
// FIXME: What are the effect of not having this function? At the moment imgui doesn't actually call SetWindowFocus - we set that up ahead, will answer that question later.
( void ) viewport ;
# endif
2018-04-25 16:15:14 +03:00
}
static bool ImGui_ImplGlfw_GetWindowFocus ( ImGuiViewport * viewport )
{
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
return glfwGetWindowAttrib ( data - > Window , GLFW_FOCUSED ) ! = 0 ;
}
2018-11-23 18:18:30 +03:00
static bool ImGui_ImplGlfw_GetWindowMinimized ( ImGuiViewport * viewport )
{
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
return glfwGetWindowAttrib ( data - > Window , GLFW_ICONIFIED ) ! = 0 ;
}
2018-04-05 18:06:23 +03:00
# if GLFW_HAS_WINDOW_ALPHA
static void ImGui_ImplGlfw_SetWindowAlpha ( ImGuiViewport * viewport , float alpha )
{
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
glfwSetWindowOpacity ( data - > Window , alpha ) ;
}
# endif
2018-03-19 17:20:47 +03:00
static void ImGui_ImplGlfw_RenderWindow ( ImGuiViewport * viewport , void * )
2018-02-28 01:27:41 +03:00
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-03-02 21:23:01 +03:00
if ( g_ClientApi = = GlfwClientApi_OpenGL )
glfwMakeContextCurrent ( data - > Window ) ;
2018-02-28 01:27:41 +03:00
}
2018-03-19 17:20:47 +03:00
static void ImGui_ImplGlfw_SwapBuffers ( ImGuiViewport * viewport , void * )
2018-02-28 01:27:41 +03:00
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2019-08-23 16:12:06 +03:00
if ( g_ClientApi = = GlfwClientApi_OpenGL )
2019-03-02 05:55:55 +03:00
{
glfwMakeContextCurrent ( data - > Window ) ;
2018-03-02 21:23:01 +03:00
glfwSwapBuffers ( data - > Window ) ;
2019-03-02 05:55:55 +03:00
}
2018-02-28 01:27:41 +03:00
}
2018-04-24 13:40:38 +03:00
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
//--------------------------------------------------------------------------------------------------------
// We provide a Win32 implementation because this is such a common issue for IME users
2021-03-02 20:27:07 +03:00
# if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
2018-04-24 13:40:38 +03:00
# define HAS_WIN32_IME 1
# include <imm.h>
# ifdef _MSC_VER
# pragma comment(lib, "imm32")
# endif
static void ImGui_ImplWin32_SetImeInputPos ( ImGuiViewport * viewport , ImVec2 pos )
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION , { ( LONG ) ( pos . x - viewport - > Pos . x ) , ( LONG ) ( pos . y - viewport - > Pos . y ) } , { 0 , 0 , 0 , 0 } } ;
2019-06-19 00:35:48 +03:00
if ( HWND hwnd = ( HWND ) viewport - > PlatformHandleRaw )
if ( HIMC himc = : : ImmGetContext ( hwnd ) )
{
: : ImmSetCompositionWindow ( himc , & cf ) ;
: : ImmReleaseContext ( hwnd , himc ) ;
}
2018-04-24 13:40:38 +03:00
}
# else
# define HAS_WIN32_IME 0
# endif
//--------------------------------------------------------------------------------------------------------
2018-03-14 01:16:15 +03:00
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
2018-04-24 13:40:38 +03:00
//--------------------------------------------------------------------------------------------------------
2018-03-14 01:16:15 +03:00
// Avoid including <vulkan.h> so we can build without it
# if GLFW_HAS_VULKAN
# ifndef VULKAN_H_
# define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
# if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
# else
# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
# endif
VK_DEFINE_HANDLE ( VkInstance )
VK_DEFINE_NON_DISPATCHABLE_HANDLE ( VkSurfaceKHR )
struct VkAllocationCallbacks ;
enum VkResult { VK_RESULT_MAX_ENUM = 0x7FFFFFFF } ;
# endif // VULKAN_H_
extern " C " { extern GLFWAPI VkResult glfwCreateWindowSurface ( VkInstance instance , GLFWwindow * window , const VkAllocationCallbacks * allocator , VkSurfaceKHR * surface ) ; }
static int ImGui_ImplGlfw_CreateVkSurface ( ImGuiViewport * viewport , ImU64 vk_instance , const void * vk_allocator , ImU64 * out_vk_surface )
{
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-03-14 01:16:15 +03:00
IM_ASSERT ( g_ClientApi = = GlfwClientApi_Vulkan ) ;
VkResult err = glfwCreateWindowSurface ( ( VkInstance ) vk_instance , data - > Window , ( const VkAllocationCallbacks * ) vk_allocator , ( VkSurfaceKHR * ) out_vk_surface ) ;
return ( int ) err ;
}
# endif // GLFW_HAS_VULKAN
2018-02-28 01:27:41 +03:00
static void ImGui_ImplGlfw_InitPlatformInterface ( )
{
// Register platform interface (will be coupled with a renderer interface)
2018-03-18 20:44:57 +03:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
platform_io . Platform_CreateWindow = ImGui_ImplGlfw_CreateWindow ;
platform_io . Platform_DestroyWindow = ImGui_ImplGlfw_DestroyWindow ;
platform_io . Platform_ShowWindow = ImGui_ImplGlfw_ShowWindow ;
platform_io . Platform_SetWindowPos = ImGui_ImplGlfw_SetWindowPos ;
platform_io . Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos ;
platform_io . Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize ;
platform_io . Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize ;
2018-04-25 16:15:14 +03:00
platform_io . Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus ;
platform_io . Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus ;
2018-11-23 18:18:30 +03:00
platform_io . Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized ;
2018-03-18 20:44:57 +03:00
platform_io . Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle ;
platform_io . Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow ;
platform_io . Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers ;
2018-04-05 18:06:23 +03:00
# if GLFW_HAS_WINDOW_ALPHA
platform_io . Platform_SetWindowAlpha = ImGui_ImplGlfw_SetWindowAlpha ;
# endif
2018-03-14 01:16:15 +03:00
# if GLFW_HAS_VULKAN
2018-03-18 20:44:57 +03:00
platform_io . Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface ;
2018-03-14 01:16:15 +03:00
# endif
2018-04-24 13:40:38 +03:00
# if HAS_WIN32_IME
platform_io . Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos ;
# endif
2018-03-12 20:43:25 +03:00
2018-04-09 23:01:24 +03:00
// Register main window handle (which is owned by the main application, not by us)
2020-01-20 21:33:46 +03:00
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
2018-02-28 01:27:41 +03:00
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
2018-03-19 00:19:02 +03:00
ImGuiViewportDataGlfw * data = IM_NEW ( ImGuiViewportDataGlfw ) ( ) ;
2018-02-28 01:27:41 +03:00
data - > Window = g_Window ;
data - > WindowOwned = false ;
main_viewport - > PlatformUserData = data ;
2018-04-09 23:01:24 +03:00
main_viewport - > PlatformHandle = ( void * ) g_Window ;
2018-02-28 01:27:41 +03:00
}
static void ImGui_ImplGlfw_ShutdownPlatformInterface ( )
{
}