1 
2 //          Copyright Marcelo S. N. Mancini(Hipreme) 2020.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 module imgui_backend.impl_sdl;
8 // // SDL
9 import bindbc.sdl;
10 
11 /// Whether to use the implemetation defined in D, or link against compiled ImGUI backend. 
12 version(CIMGUI_USER_DEFINED_IMPLEMENTATION_SDL)
13 {
14     import bindbc.cimgui;
15     import core.stdc.string : memset, strncpy, strncmp;
16     version(Windows)
17     {
18         version(CIMGUI_VIEWPORT_BRANCH)
19         {
20             pragma(lib, "user32");
21             import core.sys.windows.windows : GetWindowLong, LONG, HWND, SetWindowLong,
22                 ShowWindow, SW_SHOWNA, GWL_EXSTYLE, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW;
23         }
24     }
25 
26     // // dear imgui: Platform Binding for SDL2
27     // // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
28     // // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
29     // // (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.)
30 
31     // // Implemented features:
32     // //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
33     // //  [X] Platform: Clipboard support.
34     // //  [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. igIsKeyPressed(SDL_SCANCODE_SPACE).
35     // //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
36     // // Missing features:
37     // //  [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
38 
39     // // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
40     // // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
41     // // https://github.com/ocornut/imgui
42 
43     // // CHANGELOG
44     // // (minor and older changes stripped away, please see git history for details)
45     // //  2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
46     // //  2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
47     // //  2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
48     // //  2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
49     // //  2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
50     // //  2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
51     // //  2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
52     // //  2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
53     // //  2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
54     // //  2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
55     // //  2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
56     // //  2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
57     // //  2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
58     // //  2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
59     // //  2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
60     // //  2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
61     // //  2018-02-16: Inputs: Added support for mouse cursors, honoring igGetMouseCursor() value.
62     // //  2018-02-06: Misc: Removed call to igShutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
63     // //  2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
64     // //  2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
65     // //  2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
66     // //  2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
67     // //  2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
68     // //  2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
69     // //  2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
70     // //  2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
71 
72     enum SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE =     sdlSupport >= SDLSupport.sdl204;
73     enum SDL_HAS_WINDOW_ALPHA             =     sdlSupport >= SDLSupport.sdl205;
74     enum SDL_HAS_ALWAYS_ON_TOP            =     sdlSupport >= SDLSupport.sdl205;
75     enum SDL_HAS_USABLE_DISPLAY_BOUNDS    =     sdlSupport >= SDLSupport.sdl205;
76     enum SDL_HAS_PER_MONITOR_DPI          =     sdlSupport >= SDLSupport.sdl204;
77     enum SDL_HAS_VULKAN                   =     sdlSupport >= SDLSupport.sdl206;
78     enum SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH =     sdlSupport >= SDLSupport.sdl205;
79 
80     static if(!SDL_HAS_VULKAN)
81     {
82         static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
83     }
84 
85 
86 
87     // // Data
88     static SDL_Window*  g_Window = null;
89     static Uint64       g_Time = 0;
90     static bool[3]      g_MousePressed = [false, false, false];
91     static SDL_Cursor*[ImGuiMouseCursor_COUNT]  g_MouseCursors;
92     static char*        g_ClipboardTextData = null;
93     static bool         g_MouseCanUseGlobalState = true;
94 
95     //Must be an enum right now because I don't wish to bother at vulkan, PR's are welcome to adapting it
96     enum                g_UseVulkan = false;
97 
98 
99     enum MAP_BUTTON_SDL(ImGuiIO* io,SDL_GameController* game_controller, ulong NAV_NO, SDL_GameControllerButton BUTTON_NO)
100     {
101         io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f;
102     }
103     enum MAP_ANALOG_SDL(ImGuiIO* io, SDL_GameController* game_controller, ulong NAV_NO, SDL_GameControllerAxis AXIS_NO, int V0, int V1)
104     {
105         float vn = cast(float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / cast(float)(V1 - V0);
106         if (vn > 1.0f) 
107             vn = 1.0f; 
108         if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) 
109             io.NavInputs[NAV_NO] = vn;
110     }
111 
112 
113     /// SDL_gamecontroller.h suggests using this value.
114     enum thumb_dead_zone = 8000;
115 
116 
117     extern(C++) static const (char)* ImGui_ImplSDL2_GetClipboardText(void*)
118     {
119         if (g_ClipboardTextData)
120             SDL_free(g_ClipboardTextData);
121         g_ClipboardTextData = SDL_GetClipboardText();
122         return g_ClipboardTextData;
123     }
124 
125 
126     extern(C++) static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
127     {
128         SDL_SetClipboardText(text);
129     }
130 
131     // // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
132     // // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
133     // // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
134     // // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
135     // // If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
136     bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
137     {
138         ImGuiIO* io = igGetIO();
139 
140         switch (event.type)
141         {
142             case SDL_MOUSEWHEEL:
143             {
144                 if (event.wheel.x > 0) io.MouseWheelH += 1;
145                 if (event.wheel.x < 0) io.MouseWheelH -= 1;
146                 if (event.wheel.y > 0) io.MouseWheel += 1;
147                 if (event.wheel.y < 0) io.MouseWheel -= 1;
148                 return true;
149             }
150             case SDL_MOUSEBUTTONDOWN:
151             {
152                 if (event.button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
153                 if (event.button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
154                 if (event.button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
155                 return true;
156             }
157             case SDL_TEXTINPUT:
158             {
159                 ImGuiIO_AddInputCharactersUTF8(io, cast(const (char)*)event.text.text);
160                 return true;
161             }
162             case SDL_KEYDOWN:
163             case SDL_KEYUP:
164             {
165                 int key = event.key.keysym.scancode;
166                 IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
167                 io.KeysDown[key] = (event.type == SDL_KEYDOWN);
168                 io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
169                 io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
170                 io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
171                 version(Windows)
172                 {
173                     io.KeySuper = false;
174                 }
175                 else
176                 {
177                     io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
178                 }
179                 return true;
180             }
181             version(CIMGUI_VIEWPORT_BRANCH)
182             {
183                 case SDL_WINDOWEVENT:
184                     Uint8 window_event = event.window.event;
185                     if (window_event == SDL_WINDOWEVENT_CLOSE || window_event == SDL_WINDOWEVENT_MOVED || window_event == SDL_WINDOWEVENT_RESIZED)
186                         if (ImGuiViewport* viewport = igFindViewportByPlatformHandle(cast(void*)SDL_GetWindowFromID(event.window.windowID)))
187                         {
188                             if (window_event == SDL_WINDOWEVENT_CLOSE)
189                                 viewport.PlatformRequestClose = true;
190                             if (window_event == SDL_WINDOWEVENT_MOVED)
191                                 viewport.PlatformRequestMove = true;
192                             if (window_event == SDL_WINDOWEVENT_RESIZED)
193                                 viewport.PlatformRequestResize = true;
194                             return true;
195                         }
196                     break;
197             }
198             default:break;
199         }
200         return false;
201     }
202 
203     static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
204     {
205         g_Window = window;
206 
207         // Setup back-end capabilities flags
208         ImGuiIO* io = igGetIO();
209         io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional)
210 
211         //Viewport specific code
212         static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
213         {
214             io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports;
215         }
216         else //This code was deleted on viewport branch
217         {
218             io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;        // We can honor io.WantSetMousePos requests (optional, rarely used)
219         }
220         io.BackendPlatformName = "imgui_impl_sdl";
221 
222         // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
223         io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
224         io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
225         io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
226         io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
227         io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
228         io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
229         io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
230         io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
231         io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
232         io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
233         io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
234         io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
235         io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
236         io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
237         io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
238         io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
239         io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
240         io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
241         io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
242         io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
243         io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
244         io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
245 
246         io.SetClipboardTextFn = &ImGui_ImplSDL2_SetClipboardText;
247         io.GetClipboardTextFn = &ImGui_ImplSDL2_GetClipboardText;
248         io.ClipboardUserData = null;
249 
250         // Load mouse cursors
251         g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
252         g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
253         g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
254         g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
255         g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
256         g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
257         g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
258         g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
259         g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
260 
261         // Check and store if we are on Wayland
262         g_MouseCanUseGlobalState = strncmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0;
263 
264         version(CIMGUI_VIEWPORT_BRANCH)
265         {
266             ImGuiViewport* main_viewport = igGetMainViewport();
267             main_viewport.PlatformHandle = cast(void*)window;
268         }
269 
270         version(Windows)
271         {
272             SDL_SysWMinfo wmInfo;
273             SDL_VERSION(&wmInfo.version_);
274             version(CIMGUI_VIEWPORT_BRANCH)
275             {
276                 if(SDL_GetWindowWMInfo(window, &wmInfo))
277                 {
278                     main_viewport.PlatformHandleRaw = wmInfo.info.win.window;
279                 }
280             }
281             else
282             {
283                 SDL_GetWindowWMInfo(window, &wmInfo);
284                 //io.ImeWindowHandle = wmInfo.info.win.window;
285             }
286         }
287 
288         version(CIMGUI_VIEWPORT_BRANCH)
289         {
290             ImGui_ImplSDL2_UpdateMonitors();
291             // We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
292             // We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of static if(ef to avoid unused-function warnings.)
293             if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports))
294             {
295                 ImGui_ImplSDL2_InitPlatformInterface(window, sdl_gl_context);
296             }
297         }
298         else
299         {
300             cast(void)window;
301         }
302         return true;
303     }
304 
305     bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
306     {
307         cast(void)sdl_gl_context; // Viewport branch will need this.
308         return ImGui_ImplSDL2_Init(window, sdl_gl_context);
309     }
310 
311     bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
312     {
313         static if(!SDL_HAS_VULKAN)
314         {
315             IM_ASSERT(0, "Unsupported");
316         }
317         return ImGui_ImplSDL2_Init(window, null);
318     }
319 
320     bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
321     {
322         version(Windows){}
323         else
324         {
325             IM_ASSERT(0, "Unsupported");
326         }
327         return ImGui_ImplSDL2_Init(window, null);
328     }
329 
330     bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
331     {
332         return ImGui_ImplSDL2_Init(window, null);
333     }
334 
335     void ImGui_ImplSDL2_Shutdown()
336     {
337         version(CIMGUI_VIEWPORT_BRANCH)
338             ImGui_ImplSDL2_ShutdownPlatformInterface();
339         g_Window = null;
340         // Destroy last known clipboard data
341         if (g_ClipboardTextData)
342             SDL_free(g_ClipboardTextData);
343         g_ClipboardTextData = null;
344 
345         // Destroy SDL mouse cursors
346         for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
347             SDL_FreeCursor(g_MouseCursors[cursor_n]);
348         memset(cast(void*)g_MouseCursors, 0, g_MouseCursors.sizeof);
349     }
350 
351     static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
352     {
353         ImGuiIO* io = igGetIO();
354         // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
355         version(CIMGUI_VIEWPORT_BRANCH)
356         {
357             io.MouseHoveredViewport = 0;
358             if (io.WantSetMousePos)
359             {
360                 static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
361                 {
362                     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
363                         SDL_WarpMouseGlobal(cast(int)io.MousePos.x, cast(int)io.MousePos.y);
364                     else
365                         SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
366                 }
367                 else
368                     SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
369             }
370             else
371                 io.MousePos = ImVec2(-igGET_FLT_MAX(), -igGET_FLT_MAX());   
372         }
373         else
374         {
375             if (io.WantSetMousePos)
376                 SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
377             else
378                 io.MousePos = ImVec2(-igGET_FLT_MAX(), -igGET_FLT_MAX());
379         }
380 
381         int mx, my;
382         Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
383         io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON!SDL_BUTTON_LEFT) != 0;  // 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.
384         io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON!SDL_BUTTON_RIGHT) != 0;
385         io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON!SDL_BUTTON_MIDDLE) != 0;
386         g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
387 
388         static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
389         {
390             version(CIMGUI_VIEWPORT_BRANCH) //Mantaining compatibility with non docking branch
391             {
392                 if (g_MouseCanUseGlobalState)
393                 {
394                     // SDL 2.0.4 and later has SDL_GetGlobalMouseState() and SDL_CaptureMouse()
395                     int mouse_x_global, mouse_y_global;
396                     SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
397 
398                     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
399                     {
400                         // 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)
401                         if (SDL_Window* focused_window = SDL_GetKeyboardFocus())
402                             if (igFindViewportByPlatformHandle(cast(void*)focused_window) != null)
403                                 io.MousePos = ImVec2(cast(float)mouse_x_global, cast(float)mouse_y_global);
404                     }
405                     else
406                     {
407                         // Single-viewport mode: mouse position in client window coordinatesio.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
408                         if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
409                         {
410                             int window_x, window_y;
411                             SDL_GetWindowPosition(g_Window, &window_x, &window_y);
412                             io.MousePos = ImVec2(cast(float)(mouse_x_global - window_x), cast(float)(mouse_y_global - window_y));
413                         }
414                     }
415                 }
416                 else
417                 {
418                     if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
419                         io.MousePos = ImVec2(cast(float)mx, cast(float)my);
420                 }
421                 
422             }
423             else
424             {
425                 SDL_Window* focused_window = SDL_GetKeyboardFocus();
426                 if (g_Window == focused_window)
427                 {
428                     if (g_MouseCanUseGlobalState)
429                     {
430                         // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
431                         // The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
432                         // Won't use this workaround when on Wayland, as there is no global mouse position.
433                         int wx, wy;
434                         SDL_GetWindowPosition(focused_window, &wx, &wy);
435                         SDL_GetGlobalMouseState(&mx, &my);
436                         mx -= wx;
437                         my -= wy;
438                     }
439                     io.MousePos = ImVec2(cast(float)mx, cast(float)my);
440                 }
441             }
442             // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
443             // The function is only supported from SDL 2.0.4 (released Jan 2016)
444             bool any_mouse_button_down = igIsAnyMouseDown();
445             SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
446         }
447         else
448         {
449             if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
450                 io.MousePos = ImVec2(cast(float)mx, cast(float)my);
451         }
452     }
453 
454     static void ImGui_ImplSDL2_UpdateMouseCursor()
455     {
456         ImGuiIO* io = igGetIO();
457         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
458             return;
459 
460         ImGuiMouseCursor imgui_cursor = igGetMouseCursor();
461         if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
462         {
463             // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
464             SDL_ShowCursor(SDL_FALSE);
465         }
466         else
467         {
468             // Show OS mouse cursor
469             SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
470             SDL_ShowCursor(SDL_TRUE);
471         }
472     }
473 
474     static void ImGui_ImplSDL2_UpdateGamepads()
475     {
476         ImGuiIO* io = igGetIO();
477         memset(cast(void*)io.NavInputs, 0, io.NavInputs.sizeof);
478         if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) 
479             return;
480 
481         // Get gamepad
482         SDL_GameController* game_controller = SDL_GameControllerOpen(0);
483         if (!game_controller)
484         {
485             io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
486             return;
487         }
488 
489         // Update gamepad inputs
490         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_Activate,      SDL_CONTROLLER_BUTTON_A);               // Cross / A
491         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_Cancel,        SDL_CONTROLLER_BUTTON_B);               // Circle / B
492         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_Menu,          SDL_CONTROLLER_BUTTON_X);               // Square / X
493         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_Input,         SDL_CONTROLLER_BUTTON_Y);               // Triangle / Y
494         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_DpadLeft,      SDL_CONTROLLER_BUTTON_DPAD_LEFT);       // D-Pad Left
495         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_DpadRight,     SDL_CONTROLLER_BUTTON_DPAD_RIGHT);      // D-Pad Right
496         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_DpadUp,        SDL_CONTROLLER_BUTTON_DPAD_UP);         // D-Pad Up
497         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_DpadDown,      SDL_CONTROLLER_BUTTON_DPAD_DOWN);       // D-Pad Down
498         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_FocusPrev,     SDL_CONTROLLER_BUTTON_LEFTSHOULDER);    // L1 / LB
499         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_FocusNext,     SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);   // R1 / RB
500         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_TweakSlow,     SDL_CONTROLLER_BUTTON_LEFTSHOULDER);    // L1 / LB
501         MAP_BUTTON_SDL(io,game_controller,ImGuiNavInput_TweakFast,     SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);   // R1 / RB
502         MAP_ANALOG_SDL(io,game_controller,ImGuiNavInput_LStickLeft,    SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32_768);
503         MAP_ANALOG_SDL(io,game_controller,ImGuiNavInput_LStickRight,   SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32_767);
504         MAP_ANALOG_SDL(io,game_controller,ImGuiNavInput_LStickUp,      SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32_767);
505         MAP_ANALOG_SDL(io,game_controller,ImGuiNavInput_LStickDown,    SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32_767);
506 
507         io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
508     }
509 
510     void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
511     {
512         ImGuiIO* io = igGetIO();
513         IM_ASSERT(ImFontAtlas_IsBuilt(io.Fonts), "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
514 
515         // Setup display size (every frame to accommodate for window resizing)
516         int w, h;
517         int display_w, display_h;
518         SDL_GetWindowSize(window, &w, &h);
519         if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
520             w = h = 0;
521         SDL_GL_GetDrawableSize(window, &display_w, &display_h);
522         io.DisplaySize = ImVec2(cast(float)w, cast(float)h);
523         if (w > 0 && h > 0)
524             io.DisplayFramebufferScale = ImVec2(cast(float)display_w / w, cast(float)display_h / h);
525 
526         // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
527         static if(staticBinding) //Won't be supporting it any early
528         {
529             static Uint64 frequency = SDL_GetPerformanceFrequency();
530         }
531         else
532         {
533             Uint64 frequency = SDL_GetPerformanceFrequency();
534         }
535         Uint64 current_time = SDL_GetPerformanceCounter();
536         io.DeltaTime = g_Time > 0 ? cast(float)(cast(double)(current_time - g_Time) / frequency) : cast(float)(1.0f / 60.0f);
537         g_Time = current_time;
538 
539         ImGui_ImplSDL2_UpdateMousePosAndButtons();
540         ImGui_ImplSDL2_UpdateMouseCursor();
541 
542         // Update game controllers (if enabled and available)
543         ImGui_ImplSDL2_UpdateGamepads();
544     }
545 
546     //Starting viewport branch support
547     version(CIMGUI_VIEWPORT_BRANCH)
548     {
549         static void ImGui_ImplSDL2_UpdateMonitors()
550         {
551             ImGuiPlatformIO* platform_io = igGetPlatformIO();
552             ImVector_resize!ImVector_ImGuiPlatformMonitor(platform_io.Monitors, 0); //ImVector function, should be probably implemented
553             int display_count = SDL_GetNumVideoDisplays();
554             for (int n = 0; n < display_count; n++)
555             {
556                 // 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.
557                 ImGuiPlatformMonitor monitor;
558                 SDL_Rect r;
559                 SDL_GetDisplayBounds(n, &r);
560                 monitor.MainPos = monitor.WorkPos = ImVec2(cast(float)r.x, cast(float)r.y);
561                 monitor.MainSize = monitor.WorkSize = ImVec2(cast(float)r.w, cast(float)r.h);
562                 static if(SDL_HAS_USABLE_DISPLAY_BOUNDS)
563                 {
564                     SDL_GetDisplayUsableBounds(n, &r);
565                     monitor.WorkPos = ImVec2(cast(float)r.x, cast(float)r.y);
566                     monitor.WorkSize = ImVec2(cast(float)r.w, cast(float)r.h);
567                 }
568                 static if(SDL_HAS_PER_MONITOR_DPI)
569                 {
570                     float dpi = 0.0f;
571                     if (!SDL_GetDisplayDPI(n, &dpi, null, null))
572                         monitor.DpiScale = dpi / 96.0f;
573                 }
574                 ImVector_push_back!ImVector_ImGuiPlatformMonitor(platform_io.Monitors, monitor);
575             }
576         }
577 
578         extern(C) struct ImGuiViewportDataSDL2
579         {
580             SDL_Window*     Window;
581             Uint32          WindowID;
582             bool            WindowOwned;
583             SDL_GLContext   GLContext;
584 
585             // ~this() 
586             // {
587             //    IM_ASSERT(Window == null && GLContext == null, "Null Reference"); 
588             // }
589         }
590 
591         extern(C++) static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
592         {
593             //ImGuiViewportDataSDL2* data = IM_NEW!ImGuiViewportDataSDL2;
594 
595             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)igMemAlloc(ImGuiViewportDataSDL2.sizeof);
596             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
597 
598 
599             ImGuiViewport* main_viewport = igGetMainViewport();
600             ImGuiViewportDataSDL2* main_viewport_data = cast(ImGuiViewportDataSDL2*)main_viewport.PlatformUserData;
601 
602             // Share GL resources with main context
603             bool use_opengl = (main_viewport_data.GLContext != null);
604             SDL_GLContext backup_context = null;
605             if (use_opengl)
606             {
607                 backup_context = SDL_GL_GetCurrentContext();
608                 SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
609                 SDL_GL_MakeCurrent(main_viewport_data.Window, main_viewport_data.GLContext);
610             }
611 
612             Uint32 sdl_flags = 0;
613             sdl_flags |= use_opengl ? SDL_WINDOW_OPENGL : (g_UseVulkan ? SDL_WINDOW_VULKAN : 0);
614             sdl_flags |= SDL_GetWindowFlags(g_Window) & SDL_WINDOW_ALLOW_HIGHDPI;
615             sdl_flags |= SDL_WINDOW_HIDDEN;
616             sdl_flags |= (viewport.Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
617             sdl_flags |= (viewport.Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
618             version(Windows)
619             {
620                 // See SDL hack in ImGui_ImplSDL2_ShowWindow().
621                 sdl_flags |= (viewport.Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_SKIP_TASKBAR : 0;
622             }
623             static if(SDL_HAS_ALWAYS_ON_TOP)
624             {
625                 sdl_flags |= (viewport.Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
626             }
627             //Should declare SDL_WindowFlags as an uint
628             data.Window = SDL_CreateWindow("No Title Yet".ptr, cast(int)viewport.Pos.x, cast(int)viewport.Pos.y, cast(int)viewport.Size.x, cast(int)viewport.Size.y, cast(SDL_WindowFlags)sdl_flags);
629             data.WindowOwned = true;
630             if (use_opengl)
631             {
632                 data.GLContext = SDL_GL_CreateContext(data.Window);
633                 SDL_GL_SetSwapInterval(0);
634             }
635             if (use_opengl && backup_context)
636                 SDL_GL_MakeCurrent(data.Window, backup_context);
637 
638             viewport.PlatformHandle = cast(void*)data.Window;
639             version(Windows)
640             {
641                 SDL_SysWMinfo info;
642                 SDL_VERSION(&info.version_);
643                 if (SDL_GetWindowWMInfo(data.Window, &info))
644                     viewport.PlatformHandleRaw = info.info.win.window;
645             }
646             viewport.PlatformUserData = data;
647         }
648 
649         extern(C++) static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
650         {
651             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
652             if (ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData)
653             {
654                 if (data.GLContext && data.WindowOwned)
655                     SDL_GL_DeleteContext(data.GLContext);
656                 if (data.Window && data.WindowOwned)
657                     SDL_DestroyWindow(data.Window);
658                 data.GLContext = null;
659                 data.Window = null;
660                 IM_DELETE(data);
661             }
662             viewport.PlatformUserData = viewport.PlatformHandle = null;
663         }
664 
665         extern(C++) static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport)
666         {
667             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
668             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
669             version(Windows)
670             {
671                 HWND hwnd = cast(HWND)viewport.PlatformHandleRaw;
672 
673                 // SDL hack: Hide icon from task bar
674                 // Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition.
675                 if (viewport.Flags & ImGuiViewportFlags_NoTaskBarIcon)
676                 {
677                     LONG ex_style = GetWindowLong(hwnd, GWL_EXSTYLE);
678                     ex_style &= ~WS_EX_APPWINDOW;
679                     ex_style |= WS_EX_TOOLWINDOW;
680                     SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
681                 }
682 
683                 // SDL hack: SDL always activate/focus windows :/
684                 if (viewport.Flags & ImGuiViewportFlags_NoFocusOnAppearing)
685                 {
686                     ShowWindow(hwnd, SW_SHOWNA);
687                     return;
688                 }
689             }
690             
691             SDL_ShowWindow(data.Window);
692         }
693 
694         extern(C) static void ImGui_ImplSDL2_GetWindowPos(ImGuiViewport* viewport, ImVec2* _out_vec)
695         {
696             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
697             int x = 0, y = 0;
698             SDL_GetWindowPosition(data.Window, &x, &y);
699             _out_vec.x = cast(float)x;
700             _out_vec.y = cast(float)y;
701         }
702 
703         extern(C++) static void ImGui_ImplSDL2_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
704         {
705             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
706             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
707             SDL_SetWindowPosition(data.Window, cast(int)pos.x, cast(int)pos.y);
708         }
709 
710         extern(C) static void ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport, ImVec2* _out_vec)
711         {
712             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
713             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
714             int w = 0, h = 0;
715             SDL_GetWindowSize(data.Window, &w, &h);
716             _out_vec.x = cast(float)w;
717             _out_vec.y = cast(float)h;
718         }
719 
720         extern(C++) static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
721         {
722             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
723             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
724             SDL_SetWindowSize(data.Window, cast(int)size.x, cast(int)size.y);
725         }
726 
727         extern(C++) static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const (char)* title)
728         {
729             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
730             SDL_SetWindowTitle(data.Window, title);
731         }
732 
733         static if(SDL_HAS_WINDOW_ALPHA)
734         {
735             extern(C++) static void ImGui_ImplSDL2_SetWindowAlpha(ImGuiViewport* viewport, float alpha)
736             {
737                 //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
738                 ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
739                 SDL_SetWindowOpacity(data.Window, alpha);
740             }
741         }
742 
743         extern(C++) static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport)
744         {
745             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
746             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
747             SDL_RaiseWindow(data.Window);
748         }
749 
750         extern(C++) static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport)
751         {
752             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
753             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
754             return (SDL_GetWindowFlags(data.Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
755         }
756 
757         extern(C++) static bool ImGui_ImplSDL2_GetWindowMinimized(ImGuiViewport* viewport)
758         {
759             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
760             return (SDL_GetWindowFlags(data.Window) & SDL_WINDOW_MINIMIZED) != 0;
761         }
762 
763         extern(C++) static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*)
764         {
765             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
766             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
767             if (data.GLContext)
768               SDL_GL_MakeCurrent(data.Window, data.GLContext);
769         }
770 
771         extern(C++) static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport, void*)
772         {
773             //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
774             ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
775             if (data.GLContext)
776             {
777                 SDL_GL_MakeCurrent(data.Window, data.GLContext);
778                 SDL_GL_SwapWindow(data.Window);
779             }
780         }
781 
782         static if(SDL_HAS_VULKAN && g_UseVulkan)
783         {
784             import bindbc.vulkan; //Don't know if it is already there
785             extern(C) static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
786             {
787                 //ImGuiViewport* viewport = &viewportp._ImGuiViewport;
788                 ImGuiViewportDataSDL2* data = cast(ImGuiViewportDataSDL2*)viewport.PlatformUserData;
789                 cast(void)vk_allocator;
790                 SDL_bool ret = SDL_Vulkan_CreateSurface(data.Window, cast(VkInstance)vk_instance, cast(VkSurfaceKHR*)out_vk_surface);
791                 return ret ? 0 : 1; // ret ? VK_SUCCESS : VK_NOT_READY
792             }
793         }
794         extern(C++) static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context)
795         {
796             // Register platform interface (will be coupled with a renderer interface)
797             
798             ImGuiPlatformIO* platform_io = igGetPlatformIO();
799 
800             platform_io.Platform_CreateWindow = &ImGui_ImplSDL2_CreateWindow;
801             platform_io.Platform_DestroyWindow = &ImGui_ImplSDL2_DestroyWindow;
802             platform_io.Platform_ShowWindow = &ImGui_ImplSDL2_ShowWindow;
803             platform_io.Platform_SetWindowPos = &ImGui_ImplSDL2_SetWindowPos;
804 
805             ImGuiPlatformIO_Set_Platform_GetWindowPos(platform_io, &ImGui_ImplSDL2_GetWindowPos);
806             // platform_io.Platform_GetWindowPos = &ImGui_ImplSDL2_GetWindowPos;
807             platform_io.Platform_SetWindowSize = &ImGui_ImplSDL2_SetWindowSize;
808             // platform_io.Platform_GetWindowSize = &ImGui_ImplSDL2_GetWindowSize;
809             ImGuiPlatformIO_Set_Platform_GetWindowSize(platform_io, &ImGui_ImplSDL2_GetWindowSize);
810             platform_io.Platform_SetWindowFocus = &ImGui_ImplSDL2_SetWindowFocus;
811             platform_io.Platform_GetWindowFocus = &ImGui_ImplSDL2_GetWindowFocus;
812             platform_io.Platform_GetWindowMinimized = &ImGui_ImplSDL2_GetWindowMinimized;
813             platform_io.Platform_SetWindowTitle = &ImGui_ImplSDL2_SetWindowTitle;
814             platform_io.Platform_RenderWindow = &ImGui_ImplSDL2_RenderWindow;
815             platform_io.Platform_SwapBuffers = &ImGui_ImplSDL2_SwapBuffers;
816             static if(SDL_HAS_WINDOW_ALPHA)
817             {
818                 platform_io.Platform_SetWindowAlpha = &ImGui_ImplSDL2_SetWindowAlpha;
819             }
820             static if(SDL_HAS_VULKAN && g_UseVulkan)
821             {
822                 platform_io.Platform_CreateVkSurface = &ImGui_ImplSDL2_CreateVkSurface;
823             }
824 
825             // SDL2 by default doesn't pass mouse clicks to the application when the click focused a window. This is getting in the way of our interactions and we disable that behavior.
826             static if(SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH)
827             {
828                 SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
829             }
830 
831             // Register main window handle (which is owned by the main application, not by us)
832             // 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.
833             ImGuiViewport* main_viewport = igGetMainViewport();
834             ImGuiViewportDataSDL2* data = IM_NEW!ImGuiViewportDataSDL2;
835             data.Window = window;
836             data.WindowID = SDL_GetWindowID(window);
837             data.WindowOwned = false;
838             data.GLContext = sdl_gl_context;
839             main_viewport.PlatformUserData = data;
840             main_viewport.PlatformHandle = data.Window;
841             
842         }
843 
844         static void ImGui_ImplSDL2_ShutdownPlatformInterface()
845         {
846         }
847 
848     }
849 }
850 else    // CIMGUI_USER_DEFINED_IMPLEMENTATION_SDL
851         // binds functions dynamically
852 {
853     import bindbc.loader : SharedLib, bindSymbol;
854     extern(C) @nogc nothrow
855     {
856         alias pImGui_ImplSDL2_InitForOpenGL = bool function(SDL_Window* window,void* sdl_gl_context);
857         alias pImGui_ImplSDL2_InitForVulkan = bool function(SDL_Window* window);
858         alias pImGui_ImplSDL2_InitForD3D = bool function(SDL_Window* window);
859         alias pImGui_ImplSDL2_InitForMetal = bool function(SDL_Window* window);
860         alias pImGui_ImplSDL2_Shutdown = void function();
861         alias pImGui_ImplSDL2_NewFrame = void function(SDL_Window* window);
862         alias pImGui_ImplSDL2_ProcessEvent = bool function(const SDL_Event* event);
863     }
864 
865     __gshared
866     {
867         pImGui_ImplSDL2_InitForOpenGL ImGui_ImplSDL2_InitForOpenGL;
868         pImGui_ImplSDL2_InitForVulkan ImGui_ImplSDL2_InitForVulkan;
869         pImGui_ImplSDL2_InitForD3D ImGui_ImplSDL2_InitForD3D;
870         pImGui_ImplSDL2_InitForMetal ImGui_ImplSDL2_InitForMetal;
871         pImGui_ImplSDL2_Shutdown ImGui_ImplSDL2_Shutdown;
872         pImGui_ImplSDL2_NewFrame ImGui_ImplSDL2_NewFrame;
873         pImGui_ImplSDL2_ProcessEvent ImGui_ImplSDL2_ProcessEvent;
874     }
875     void bindSDLImgui(SharedLib lib)
876     {
877         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForOpenGL, "ImGui_ImplSDL2_InitForOpenGL");
878         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForVulkan, "ImGui_ImplSDL2_InitForVulkan");
879         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForD3D, "ImGui_ImplSDL2_InitForD3D");
880         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForMetal, "ImGui_ImplSDL2_InitForMetal");
881         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_Shutdown, "ImGui_ImplSDL2_Shutdown");
882         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_NewFrame, "ImGui_ImplSDL2_NewFrame");
883         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_ProcessEvent, "ImGui_ImplSDL2_ProcessEvent");
884     }
885 
886 }