2018-02-21 22:05:17 +00:00
// ImGui Platform Binding for: GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
2018-02-16 20:38:38 +00:00
// Implemented features:
2018-02-28 17:51:40 +00:00
// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
2018-04-10 17:21:52 +00:00
// [X] Multi-viewport windows (when ImGuiConfigFlags_ViewportsEnable is enabled).
2018-02-16 20:38:38 +00:00
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2018-03-18 17:44:57 +00:00
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
2018-04-06 21:34:43 +00:00
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
2018-04-09 17:35:14 +00:00
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
2018-02-16 20:38:38 +00: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 17:51:40 +00:00
// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
2018-03-20 21:14:34 +00:00
// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
2018-02-16 20:38:38 +00: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 09:29:37 +00:00
// GLFW
2018-02-16 20:38:38 +00:00
# include <GLFW/glfw3.h>
# ifdef _WIN32
# undef APIENTRY
# define GLFW_EXPOSE_NATIVE_WIN32
2018-03-18 17:44:57 +00:00
# include <GLFW/glfw3native.h> // for glfwGetWin32Window
2018-02-16 20:38:38 +00:00
# endif
2018-03-13 22:16:15 +00:00
# ifdef GLFW_HOVERED
# define GLFW_HAS_GLFW_HOVERED 1
# else
# define GLFW_HAS_GLFW_HOVERED 0
# endif
2018-04-05 15:06:23 +00:00
# define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+
2018-04-11 19:27:19 +00:00
# define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+
2018-03-13 22:16:15 +00:00
# define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+
2018-02-16 20:38:38 +00:00
2018-04-11 19:27:19 +00:00
2018-02-16 20:38:38 +00:00
// Data
2018-03-02 18:23:01 +00:00
enum GlfwClientApi
{
GlfwClientApi_Unknown ,
GlfwClientApi_OpenGL ,
GlfwClientApi_Vulkan
} ;
static GLFWwindow * g_Window = NULL ;
static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown ;
static double g_Time = 0.0f ;
static bool g_MouseJustPressed [ 5 ] = { false , false , false , false , false } ;
static GLFWcursor * g_MouseCursors [ ImGuiMouseCursor_Count_ ] = { 0 } ;
2018-02-16 20:38:38 +00:00
2018-02-27 22:27:41 +00:00
// Forward Declarations
static void ImGui_ImplGlfw_InitPlatformInterface ( ) ;
static void ImGui_ImplGlfw_ShutdownPlatformInterface ( ) ;
2018-02-27 09:29:37 +00:00
static const char * ImGui_ImplGlfw_GetClipboardText ( void * user_data )
2018-02-16 20:38:38 +00:00
{
return glfwGetClipboardString ( ( GLFWwindow * ) user_data ) ;
}
2018-02-27 09:29:37 +00:00
static void ImGui_ImplGlfw_SetClipboardText ( void * user_data , const char * text )
2018-02-16 20:38:38 +00:00
{
glfwSetClipboardString ( ( GLFWwindow * ) user_data , text ) ;
}
void ImGui_ImplGlfw_MouseButtonCallback ( GLFWwindow * , int button , int action , int /*mods*/ )
{
2018-02-27 09:29:37 +00:00
if ( action = = GLFW_PRESS & & button > = 0 & & button < IM_ARRAYSIZE ( g_MouseJustPressed ) )
2018-02-16 20:38:38 +00:00
g_MouseJustPressed [ button ] = true ;
}
void ImGui_ImplGlfw_ScrollCallback ( GLFWwindow * , double xoffset , double yoffset )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . MouseWheelH + = ( float ) xoffset ;
io . MouseWheel + = ( float ) yoffset ;
}
void ImGui_ImplGlfw_KeyCallback ( GLFWwindow * , int key , int , int action , int mods )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
if ( action = = GLFW_PRESS )
io . KeysDown [ key ] = true ;
if ( action = = GLFW_RELEASE )
io . KeysDown [ key ] = false ;
( void ) mods ; // Modifiers are not reliable across systems
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 ] ;
io . KeySuper = io . KeysDown [ GLFW_KEY_LEFT_SUPER ] | | io . KeysDown [ GLFW_KEY_RIGHT_SUPER ] ;
}
void ImGui_ImplGlfw_CharCallback ( GLFWwindow * , unsigned int c )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
if ( c > 0 & & c < 0x10000 )
io . AddInputCharacter ( ( unsigned short ) c ) ;
}
2018-02-27 09:29:37 +00:00
void ImGui_ImplGlfw_InstallCallbacks ( GLFWwindow * window )
{
glfwSetMouseButtonCallback ( window , ImGui_ImplGlfw_MouseButtonCallback ) ;
glfwSetScrollCallback ( window , ImGui_ImplGlfw_ScrollCallback ) ;
glfwSetKeyCallback ( window , ImGui_ImplGlfw_KeyCallback ) ;
glfwSetCharCallback ( window , ImGui_ImplGlfw_CharCallback ) ;
}
2018-03-15 15:42:21 +00:00
static bool ImGui_ImplGlfw_Init ( GLFWwindow * window , bool install_callbacks , GlfwClientApi client_api )
2018-02-16 20:38:38 +00:00
{
g_Window = window ;
2018-03-20 21:14:34 +00:00
// Setup back-end capabilities flags
2018-02-16 20:38:38 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2018-03-20 21:14:34 +00:00
io . BackendFlags | = ImGuiBackendFlags_HasMouseCursors ; // We can honor GetMouseCursor() values (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io . BackendFlags | = ImGuiBackendFlags_PlatformHasViewports ; // We can create multi-viewports on the Platform side (optional)
# if GLFW_HAS_GLFW_HOVERED
io . BackendFlags | = ImGuiBackendFlags_HasMouseHoveredViewport ; // We can set io.MouseHoveredViewport correctly (optional, not easy)
# endif
// Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
io . KeyMap [ ImGuiKey_Tab ] = GLFW_KEY_TAB ;
2018-02-16 20:38:38 +00: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 ;
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 09:29:37 +00:00
io . SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText ;
io . GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText ;
2018-02-16 20:38:38 +00:00
io . ClipboardUserData = g_Window ;
# ifdef _WIN32
io . ImeWindowHandle = glfwGetWin32Window ( g_Window ) ;
# endif
2018-02-19 21:29:52 +00:00
g_MouseCursors [ ImGuiMouseCursor_Arrow ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_TextInput ] = glfwCreateStandardCursor ( GLFW_IBEAM_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeAll ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ; // FIXME: GLFW doesn't have this.
g_MouseCursors [ ImGuiMouseCursor_ResizeNS ] = glfwCreateStandardCursor ( GLFW_VRESIZE_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeEW ] = glfwCreateStandardCursor ( GLFW_HRESIZE_CURSOR ) ;
g_MouseCursors [ ImGuiMouseCursor_ResizeNESW ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ; // FIXME: GLFW doesn't have this.
g_MouseCursors [ ImGuiMouseCursor_ResizeNWSE ] = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ; // FIXME: GLFW doesn't have this.
2018-02-16 20:38:38 +00:00
if ( install_callbacks )
2018-02-27 09:29:37 +00:00
ImGui_ImplGlfw_InstallCallbacks ( window ) ;
2018-02-16 20:38:38 +00:00
2018-02-27 22:27:41 +00: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 ;
2018-04-10 17:21:52 +00:00
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
2018-02-27 22:27:41 +00:00
ImGui_ImplGlfw_InitPlatformInterface ( ) ;
2018-03-15 15:42:21 +00:00
g_ClientApi = client_api ;
2018-03-02 18:23:01 +00:00
return true ;
}
2018-03-15 15:42:21 +00:00
bool ImGui_ImplGlfw_InitForOpenGL ( GLFWwindow * window , bool install_callbacks )
{
return ImGui_ImplGlfw_Init ( window , install_callbacks , GlfwClientApi_OpenGL ) ;
}
2018-03-02 18:23:01 +00:00
bool ImGui_ImplGlfw_InitForVulkan ( GLFWwindow * window , bool install_callbacks )
{
2018-03-15 15:42:21 +00:00
return ImGui_ImplGlfw_Init ( window , install_callbacks , GlfwClientApi_Vulkan ) ;
2018-02-16 20:38:38 +00:00
}
void ImGui_ImplGlfw_Shutdown ( )
{
2018-02-27 22:27:41 +00:00
ImGui_ImplGlfw_ShutdownPlatformInterface ( ) ;
2018-02-19 21:29:52 +00:00
for ( ImGuiMouseCursor cursor_n = 0 ; cursor_n < ImGuiMouseCursor_Count_ ; cursor_n + + )
{
glfwDestroyCursor ( g_MouseCursors [ cursor_n ] ) ;
g_MouseCursors [ cursor_n ] = NULL ;
}
2018-03-02 18:23:01 +00:00
g_ClientApi = GlfwClientApi_Unknown ;
2018-02-16 20:38:38 +00:00
}
2018-02-27 22:27:41 +00:00
static void ImGui_ImplGlfw_UpdateMouse ( )
2018-02-16 20:38:38 +00:00
{
2018-02-27 22:27:41 +00:00
#if 0
2018-03-20 21:14:34 +00:00
// Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if ( io . WantSetMousePos )
glfwSetCursorPos ( g_Window , ( double ) io . MousePos . x , ( double ) io . MousePos . y ) ;
2018-02-27 22:27:41 +00:00
# endif
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . MousePos = ImVec2 ( - FLT_MAX , - FLT_MAX ) ;
io . MousePosViewport = 0 ;
io . MouseHoveredViewport = 0 ;
2018-02-27 09:29:37 +00:00
// Update buttons
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 20:38:38 +00:00
2018-04-10 20:58:39 +00:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int n = 0 ; n < platform_io . Viewports . Size ; n + + )
2018-02-16 20:38:38 +00:00
{
2018-04-10 20:58:39 +00:00
ImGuiViewport * viewport = platform_io . Viewports [ n ] ;
2018-02-27 22:27:41 +00:00
GLFWwindow * window = ( GLFWwindow * ) viewport - > PlatformHandle ;
IM_ASSERT ( window ! = NULL ) ;
if ( glfwGetWindowAttrib ( window , GLFW_FOCUSED ) )
2018-02-16 20:38:38 +00:00
{
double mouse_x , mouse_y ;
2018-02-27 22:27:41 +00:00
glfwGetCursorPos ( window , & mouse_x , & mouse_y ) ;
io . MousePos = ImVec2 ( ( float ) mouse_x + viewport - > Pos . x , ( float ) mouse_y + viewport - > Pos . y ) ;
io . MousePosViewport = viewport - > ID ;
for ( int i = 0 ; i < IM_ARRAYSIZE ( io . MouseDown ) ; i + + )
io . MouseDown [ i ] | = glfwGetMouseButton ( window , i ) ! = 0 ;
2018-02-16 20:38:38 +00:00
}
2018-02-27 22:27:41 +00:00
# if GLFW_HAS_GLFW_HOVERED
2018-04-05 15:06:23 +00:00
io . BackendFlags | = ImGuiBackendFlags_HasMouseHoveredViewport ;
if ( glfwGetWindowAttrib ( window , GLFW_HOVERED ) & & ! ( viewport - > Flags & ImGuiViewportFlags_NoInputs ) )
2018-02-27 22:27:41 +00:00
io . MouseHoveredViewport = viewport - > ID ;
# endif
}
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
2018-04-06 21:34:43 +00:00
if ( ( io . ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange ) = = 0 & & glfwGetInputMode ( g_Window , GLFW_CURSOR ) ! = GLFW_CURSOR_DISABLED )
2018-02-16 20:38:38 +00:00
{
2018-03-20 21:14:34 +00:00
ImGuiMouseCursor cursor = ImGui : : GetMouseCursor ( ) ;
if ( io . MouseDrawCursor | | cursor = = ImGuiMouseCursor_None )
{
glfwSetInputMode ( g_Window , GLFW_CURSOR , GLFW_CURSOR_HIDDEN ) ;
}
else
{
glfwSetCursor ( g_Window , g_MouseCursors [ cursor ] ? g_MouseCursors [ cursor ] : g_MouseCursors [ ImGuiMouseCursor_Arrow ] ) ;
glfwSetInputMode ( g_Window , GLFW_CURSOR , GLFW_CURSOR_NORMAL ) ;
}
2018-02-16 20:38:38 +00:00
}
2018-02-27 09:29:37 +00:00
}
void ImGui_ImplGlfw_NewFrame ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
IM_ASSERT ( io . Fonts - > IsBuilt ( ) ) ; // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()
// Setup display size
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 ) ;
io . DisplayFramebufferScale = ImVec2 ( w > 0 ? ( ( float ) display_w / w ) : 0 , h > 0 ? ( ( float ) display_h / h ) : 0 ) ;
// Setup time step
2018-02-27 22:27:41 +00:00
double current_time = glfwGetTime ( ) ;
2018-02-27 09:29:37 +00:00
io . DeltaTime = g_Time > 0.0 ? ( float ) ( current_time - g_Time ) : ( float ) ( 1.0f / 60.0f ) ;
g_Time = current_time ;
2018-02-27 22:27:41 +00:00
ImGui_ImplGlfw_UpdateMouse ( ) ;
2018-02-16 20:38:38 +00:00
// Gamepad navigation mapping [BETA]
memset ( io . NavInputs , 0 , sizeof ( io . NavInputs ) ) ;
2018-02-28 17:51:40 +00:00
if ( io . ConfigFlags & ImGuiConfigFlags_NavEnableGamepad )
2018-02-16 20:38:38 +00:00
{
// 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
2018-03-20 21:14:34 +00:00
if ( axes_count > 0 & & buttons_count > 0 )
io . BackendFlags | = ImGuiBackendFlags_HasGamepad ;
else
io . BackendFlags & = ~ ImGuiBackendFlags_HasGamepad ;
2018-02-16 20:38:38 +00:00
}
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
ImGui : : NewFrame ( ) ;
}
2018-02-27 22:27:41 +00:00
// --------------------------------------------------------------------------------------------------------
// Platform Windows
// --------------------------------------------------------------------------------------------------------
2018-03-18 21:19:02 +00:00
struct ImGuiViewportDataGlfw
2018-02-27 22:27:41 +00:00
{
GLFWwindow * Window ;
bool WindowOwned ;
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw ( ) { Window = NULL ; WindowOwned = false ; }
~ ImGuiViewportDataGlfw ( ) { IM_ASSERT ( Window = = NULL ) ; }
2018-02-27 22:27:41 +00:00
} ;
2018-03-15 09:54:27 +00:00
static void ImGui_ImplGlfw_WindowCloseCallback ( GLFWwindow * window )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
viewport - > PlatformRequestClose = true ;
}
static void ImGui_ImplGlfw_WindowPosCallback ( GLFWwindow * window , int , int )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
viewport - > PlatformRequestMove = true ;
}
static void ImGui_ImplGlfw_WindowSizeCallback ( GLFWwindow * window , int , int )
{
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( window ) )
viewport - > PlatformRequestResize = true ;
}
2018-03-18 17:44:57 +00:00
static void ImGui_ImplGlfw_CreateWindow ( ImGuiViewport * viewport )
2018-02-27 22:27:41 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = IM_NEW ( ImGuiViewportDataGlfw ) ( ) ;
2018-02-27 22:27:41 +00:00
viewport - > PlatformUserData = data ;
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
glfwWindowHint ( GLFW_VISIBLE , false ) ;
glfwWindowHint ( GLFW_FOCUSED , false ) ;
glfwWindowHint ( GLFW_DECORATED , ( viewport - > Flags & ImGuiViewportFlags_NoDecoration ) ? false : true ) ;
2018-04-11 19:27:19 +00:00
# if GLFW_HAS_WINDOW_TOPMOST
glfwWindowHint ( GLFW_FLOATING , ( viewport - > Flags & imGuiViewportFlags_TopMost ) ? true : false ) ;
# endif
2018-03-02 18:23:01 +00: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-27 22:27:41 +00:00
data - > WindowOwned = true ;
viewport - > PlatformHandle = ( void * ) data - > Window ;
ImGui_ImplGlfw_InstallCallbacks ( data - > Window ) ;
2018-03-15 09:54:27 +00:00
glfwSetWindowCloseCallback ( data - > Window , ImGui_ImplGlfw_WindowCloseCallback ) ;
glfwSetWindowPosCallback ( data - > Window , ImGui_ImplGlfw_WindowPosCallback ) ;
glfwSetWindowSizeCallback ( data - > Window , ImGui_ImplGlfw_WindowSizeCallback ) ;
2018-02-27 22:27:41 +00:00
}
2018-03-18 17:44:57 +00:00
static void ImGui_ImplGlfw_DestroyWindow ( ImGuiViewport * viewport )
2018-02-27 22:27:41 +00:00
{
2018-03-18 21:19:02 +00:00
if ( ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData )
2018-02-27 22:27:41 +00:00
{
2018-04-09 20:01:24 +00:00
if ( data - > WindowOwned )
{
2018-04-11 19:27:19 +00:00
# if GLFW_HAS_GLFW_HOVERED && defined(_WIN32)
2018-04-09 20:01:24 +00:00
HWND hwnd = glfwGetWin32Window ( data - > Window ) ;
: : RemovePropA ( hwnd , " IMGUI_VIEWPORT " ) ;
# endif
2018-02-27 22:27:41 +00:00
glfwDestroyWindow ( data - > Window ) ;
2018-04-09 20:01:24 +00:00
}
2018-02-27 22:27:41 +00:00
data - > Window = NULL ;
IM_DELETE ( data ) ;
}
viewport - > PlatformUserData = viewport - > PlatformHandle = NULL ;
}
# if defined(_WIN32) && GLFW_HAS_GLFW_HOVERED
static WNDPROC g_GlfwWndProc = NULL ;
static LRESULT CALLBACK WndProcNoInputs ( HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam )
{
if ( msg = = WM_NCHITTEST )
{
2018-04-05 10:00:07 +00:00
// Let mouse pass-through the window. This will allow the back-end to set io.MouseHoveredViewport properly (which is OPTIONAL).
// 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
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
2018-02-27 22:27:41 +00: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-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00:00
# if defined(_WIN32)
// GLFW hack: Hide icon from task bar
HWND hwnd = glfwGetWin32Window ( data - > Window ) ;
2018-04-10 17:15:44 +00:00
if ( viewport - > Flags & ImGuiViewportFlags_NoTaskBarIcon )
2018-02-27 22:27:41 +00: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
2018-04-11 19:27:19 +00:00
# if GLFW_HAS_GLFW_HOVERED && defined(_WIN32)
2018-02-27 22:27:41 +00: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
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
// The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3. See https://github.com/glfw/glfw/issues/1179
if ( viewport - > Flags & ImGuiViewportFlags_NoFocusOnAppearing )
{
: : ShowWindow ( hwnd , SW_SHOWNA ) ;
return ;
}
# endif
glfwShowWindow ( data - > Window ) ;
}
static ImVec2 ImGui_ImplGlfw_GetWindowPos ( ImGuiViewport * viewport )
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00: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-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00:00
glfwSetWindowPos ( data - > Window , ( int ) pos . x , ( int ) pos . y ) ;
}
static ImVec2 ImGui_ImplGlfw_GetWindowSize ( ImGuiViewport * viewport )
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00: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-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00:00
glfwSetWindowSize ( data - > Window , ( int ) size . x , ( int ) size . y ) ;
}
static void ImGui_ImplGlfw_SetWindowTitle ( ImGuiViewport * viewport , const char * title )
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-02-27 22:27:41 +00:00
glfwSetWindowTitle ( data - > Window , title ) ;
}
2018-04-05 15:06:23 +00: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 14:20:47 +00:00
static void ImGui_ImplGlfw_RenderWindow ( ImGuiViewport * viewport , void * )
2018-02-27 22:27:41 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-03-02 18:23:01 +00:00
if ( g_ClientApi = = GlfwClientApi_OpenGL )
glfwMakeContextCurrent ( data - > Window ) ;
2018-02-27 22:27:41 +00:00
}
2018-03-19 14:20:47 +00:00
static void ImGui_ImplGlfw_SwapBuffers ( ImGuiViewport * viewport , void * )
2018-02-27 22:27:41 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-03-02 18:23:01 +00:00
if ( g_ClientApi = = GlfwClientApi_OpenGL )
glfwSwapBuffers ( data - > Window ) ;
2018-02-27 22:27:41 +00:00
}
2018-03-13 22:16:15 +00:00
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
// 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-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = ( ImGuiViewportDataGlfw * ) viewport - > PlatformUserData ;
2018-03-13 22:16:15 +00: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-04-10 20:32:08 +00:00
// FIXME-PLATFORM: Update when changed (using glfwSetMonitorCallback?)
static void ImGui_ImplGlfw_UpdateMonitors ( )
{
2018-04-10 20:58:39 +00:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
2018-04-10 20:32:08 +00:00
int monitors_count = 0 ;
GLFWmonitor * * glfw_monitors = glfwGetMonitors ( & monitors_count ) ;
2018-04-10 20:58:39 +00:00
platform_io . Monitors . resize ( monitors_count ) ;
2018-04-10 20:32:08 +00:00
for ( int n = 0 ; n < monitors_count ; n + + )
{
int x , y ;
glfwGetMonitorPos ( glfw_monitors [ n ] , & x , & y ) ;
const GLFWvidmode * vid_mode = glfwGetVideoMode ( glfw_monitors [ n ] ) ;
2018-04-10 20:58:39 +00:00
platform_io . Monitors [ n ] . Pos = ImVec2 ( ( float ) x , ( float ) y ) ;
platform_io . Monitors [ n ] . Size = ImVec2 ( ( float ) vid_mode - > width , ( float ) vid_mode - > height ) ;
2018-04-10 20:32:08 +00:00
}
}
2018-02-27 22:27:41 +00:00
static void ImGui_ImplGlfw_InitPlatformInterface ( )
{
// Register platform interface (will be coupled with a renderer interface)
2018-03-18 17:44:57 +00: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 ;
platform_io . Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle ;
platform_io . Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow ;
platform_io . Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers ;
2018-04-05 15:06:23 +00:00
# if GLFW_HAS_WINDOW_ALPHA
platform_io . Platform_SetWindowAlpha = ImGui_ImplGlfw_SetWindowAlpha ;
# endif
2018-03-13 22:16:15 +00:00
# if GLFW_HAS_VULKAN
2018-03-18 17:44:57 +00:00
platform_io . Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface ;
2018-03-13 22:16:15 +00:00
# endif
2018-03-12 17:43:25 +00:00
2018-04-10 20:32:08 +00:00
ImGui_ImplGlfw_UpdateMonitors ( ) ;
2018-04-09 20:01:24 +00:00
// Register main window handle (which is owned by the main application, not by us)
2018-02-27 22:27:41 +00:00
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
2018-03-18 21:19:02 +00:00
ImGuiViewportDataGlfw * data = IM_NEW ( ImGuiViewportDataGlfw ) ( ) ;
2018-02-27 22:27:41 +00:00
data - > Window = g_Window ;
data - > WindowOwned = false ;
main_viewport - > PlatformUserData = data ;
2018-04-09 20:01:24 +00:00
main_viewport - > PlatformHandle = ( void * ) g_Window ;
2018-02-27 22:27:41 +00:00
}
static void ImGui_ImplGlfw_ShutdownPlatformInterface ( )
{
}