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 
10 enum CIMGUI_USER_DEFINED_IMPLEMENTATION = true;
11 import bindbc.sdl;
12 
13 static if(CIMGUI_USER_DEFINED_IMPLEMENTATION)
14 {
15     import bindbc.cimgui;
16     import core.stdc.string : memset, strncpy, strncmp;
17     version(Windows)
18     {
19         static if(CIMGUI_VIEWPORT_BRANCH)
20         {
21             pragma(lib, "user32");
22             import core.sys.windows.windows : GetWindowLong, LONG, HWND, SetWindowLong,
23                 ShowWindow, SW_SHOWNA, GWL_EXSTYLE, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW;
24         }
25     }
26 
27     // // dear imgui: Platform Binding for SDL2
28     // // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
29     // // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
30     // // (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.)
31 
32     // // Implemented features:
33     // //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
34     // //  [X] Platform: Clipboard support.
35     // //  [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. igIsKeyPressed(SDL_SCANCODE_SPACE).
36     // //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
37     // // Missing features:
38     // //  [ ] 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.
39 
40     // // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
41     // // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
42     // // https://github.com/ocornut/imgui
43 
44     // // CHANGELOG
45     // // (minor and older changes stripped away, please see git history for details)
46     // //  2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
47     // //  2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
48     // //  2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
49     // //  2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
50     // //  2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
51     // //  2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
52     // //  2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
53     // //  2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
54     // //  2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
55     // //  2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
56     // //  2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
57     // //  2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
58     // //  2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
59     // //  2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
60     // //  2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
61     // //  2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
62     // //  2018-02-16: Inputs: Added support for mouse cursors, honoring igGetMouseCursor() value.
63     // //  2018-02-06: Misc: Removed call to igShutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
64     // //  2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
65     // //  2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
66     // //  2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
67     // //  2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
68     // //  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.
69     // //  2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
70     // //  2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
71     // //  2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
72 
73     enum SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE =     sdlSupport >= SDLSupport.sdl204;
74     enum SDL_HAS_WINDOW_ALPHA             =     sdlSupport >= SDLSupport.sdl205;
75     enum SDL_HAS_ALWAYS_ON_TOP            =     sdlSupport >= SDLSupport.sdl205;
76     enum SDL_HAS_USABLE_DISPLAY_BOUNDS    =     sdlSupport >= SDLSupport.sdl205;
77     enum SDL_HAS_PER_MONITOR_DPI          =     sdlSupport >= SDLSupport.sdl204;
78     enum SDL_HAS_VULKAN                   =     sdlSupport >= SDLSupport.sdl206;
79     enum SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH =     sdlSupport >= SDLSupport.sdl205;
80 
81     static if(!SDL_HAS_VULKAN)
82     {
83         static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
84     }
85 
86 
87 
88     // // Data
89     static SDL_Window*  g_Window = null;
90     static Uint64       g_Time = 0;
91     static bool[3]      g_MousePressed = [false, false, false];
92     static SDL_Cursor*[ImGuiMouseCursor_COUNT]  g_MouseCursors;
93     static char*        g_ClipboardTextData = null;
94     static bool         g_MouseCanUseGlobalState = true;
95 
96     //Must be an enum right now because I don't wish to bother at vulkan, PR's are welcome to adapting it
97     enum                g_UseVulkan = false;
98 
99 
100     enum MAP_BUTTON_SDL(ImGuiIO* io,SDL_GameController* game_controller, ulong NAV_NO, SDL_GameControllerButton BUTTON_NO)
101     {
102         io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f;
103     }
104     enum MAP_ANALOG_SDL(ImGuiIO* io, SDL_GameController* game_controller, ulong NAV_NO, SDL_GameControllerAxis AXIS_NO, int V0, int V1)
105     {
106         float vn = cast(float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / cast(float)(V1 - V0);
107         if (vn > 1.0f) 
108             vn = 1.0f; 
109         if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) 
110             io.NavInputs[NAV_NO] = vn;
111     }
112 
113 
114     /// SDL_gamecontroller.h suggests using this value.
115     enum thumb_dead_zone = 8000;
116 
117 
118     extern(C) static const (char)* ImGui_ImplSDL2_GetClipboardText(void*)
119     {
120         if (g_ClipboardTextData)
121             SDL_free(g_ClipboardTextData);
122         g_ClipboardTextData = SDL_GetClipboardText();
123         return g_ClipboardTextData;
124     }
125 
126 
127     extern(C) static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
128     {
129         SDL_SetClipboardText(text);
130     }
131 
132     // // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
133     // // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
134     // // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
135     // // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
136     // // 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.
137     bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
138     {
139         ImGuiIO* io = igGetIO();
140 
141         switch (event.type)
142         {
143             case SDL_MOUSEWHEEL:
144             {
145                 if (event.wheel.x > 0) io.MouseWheelH += 1;
146                 if (event.wheel.x < 0) io.MouseWheelH -= 1;
147                 if (event.wheel.y > 0) io.MouseWheel += 1;
148                 if (event.wheel.y < 0) io.MouseWheel -= 1;
149                 return true;
150             }
151             case SDL_MOUSEBUTTONDOWN:
152             {
153                 if (event.button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
154                 if (event.button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
155                 if (event.button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
156                 return true;
157             }
158             case SDL_TEXTINPUT:
159             {
160                 ImGuiIO_AddInputCharactersUTF8(io, cast(const (char)*)event.text.text);
161                 return true;
162             }
163             case SDL_KEYDOWN:
164             case SDL_KEYUP:
165             {
166                 int key = event.key.keysym.scancode;
167                 IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
168                 io.KeysDown[key] = (event.type == SDL_KEYDOWN);
169                 io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
170                 io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
171                 io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
172                 version(Windows)
173                 {
174                     io.KeySuper = false;
175                 }
176                 else
177                 {
178                     io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
179                 }
180                 return true;
181             }
182             static if(CIMGUI_VIEWPORT_BRANCH)
183             {
184                 case SDL_WINDOWEVENT:
185                     Uint8 window_event = event.window.event;
186                     if (window_event == SDL_WINDOWEVENT_CLOSE || window_event == SDL_WINDOWEVENT_MOVED || window_event == SDL_WINDOWEVENT_RESIZED)
187                         if (ImGuiViewport* viewport = igFindViewportByPlatformHandle(cast(void*)SDL_GetWindowFromID(event.window.windowID)))
188                         {
189                             if (window_event == SDL_WINDOWEVENT_CLOSE)
190                                 viewport.PlatformRequestClose = true;
191                             if (window_event == SDL_WINDOWEVENT_MOVED)
192                                 viewport.PlatformRequestMove = true;
193                             if (window_event == SDL_WINDOWEVENT_RESIZED)
194                                 viewport.PlatformRequestResize = true;
195                             return true;
196                         }
197                     break;
198             }
199             default:break;
200         }
201         return false;
202     }
203 
204     static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
205     {
206         g_Window = window;
207 
208         // Setup back-end capabilities flags
209         ImGuiIO* io = igGetIO();
210         io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional)
211 
212         //Viewport specific code
213         static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
214         {
215             io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports;
216         }
217         else //This code was deleted on viewport branch
218         {
219             io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;        // We can honor io.WantSetMousePos requests (optional, rarely used)
220         }
221         io.BackendPlatformName = "imgui_impl_sdl";
222 
223         // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
224         io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
225         io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
226         io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
227         io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
228         io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
229         io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
230         io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
231         io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
232         io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
233         io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
234         io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
235         io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
236         io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
237         io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
238         io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
239         io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
240         io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
241         io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
242         io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
243         io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
244         io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
245         io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
246 
247         io.SetClipboardTextFn = &ImGui_ImplSDL2_SetClipboardText;
248         io.GetClipboardTextFn = &ImGui_ImplSDL2_GetClipboardText;
249         io.ClipboardUserData = null;
250 
251         // Load mouse cursors
252         g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
253         g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
254         g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
255         g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
256         g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
257         g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
258         g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
259         g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
260         g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
261 
262         // Check and store if we are on Wayland
263         g_MouseCanUseGlobalState = strncmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0;
264 
265         static if(CIMGUI_VIEWPORT_BRANCH)
266         {
267             ImGuiViewport* main_viewport = igGetMainViewport();
268             main_viewport.PlatformHandle = cast(void*)window;
269         }
270 
271         version(Windows)
272         {
273             SDL_SysWMinfo wmInfo;
274             SDL_VERSION(&wmInfo.version_);
275             static if(CIMGUI_VIEWPORT_BRANCH)
276             {
277                 if(SDL_GetWindowWMInfo(window, &wmInfo))
278                 {
279                     main_viewport.PlatformHandleRaw = wmInfo.info.win.window;
280                 }
281             }
282             else
283             {
284                 SDL_GetWindowWMInfo(window, &wmInfo);
285                 //io.ImeWindowHandle = wmInfo.info.win.window;
286             }
287         }
288 
289         static if(CIMGUI_VIEWPORT_BRANCH)
290         {
291             ImGui_ImplSDL2_UpdateMonitors();
292             // We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
293             // We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of static if(ef to avoid unused-function warnings.)
294             if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports))
295             {
296                 ImGui_ImplSDL2_InitPlatformInterface(window, sdl_gl_context);
297             }
298         }
299         else
300         {
301             cast(void)window;
302         }
303         return true;
304     }
305 
306     bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
307     {
308         cast(void)sdl_gl_context; // Viewport branch will need this.
309         return ImGui_ImplSDL2_Init(window, sdl_gl_context);
310     }
311 
312     bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
313     {
314         static if(!SDL_HAS_VULKAN)
315         {
316             IM_ASSERT(0, "Unsupported");
317         }
318         return ImGui_ImplSDL2_Init(window, null);
319     }
320 
321     bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
322     {
323         version(Windows){}
324         else
325         {
326             IM_ASSERT(0, "Unsupported");
327         }
328         return ImGui_ImplSDL2_Init(window, null);
329     }
330 
331     bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
332     {
333         return ImGui_ImplSDL2_Init(window, null);
334     }
335 
336     void ImGui_ImplSDL2_Shutdown()
337     {
338         static if(CIMGUI_VIEWPORT_BRANCH)
339             ImGui_ImplSDL2_ShutdownPlatformInterface();
340         g_Window = null;
341         // Destroy last known clipboard data
342         if (g_ClipboardTextData)
343             SDL_free(g_ClipboardTextData);
344         g_ClipboardTextData = null;
345 
346         // Destroy SDL mouse cursors
347         for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
348             SDL_FreeCursor(g_MouseCursors[cursor_n]);
349         memset(cast(void*)g_MouseCursors, 0, g_MouseCursors.sizeof);
350     }
351 
352     static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
353     {
354         ImGuiIO* io = igGetIO();
355         // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
356         static if(!CIMGUI_VIEWPORT_BRANCH)
357         {
358             if (io.WantSetMousePos)
359                 SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
360             else
361                 io.MousePos = ImVec2(-igGET_FLT_MAX(), -igGET_FLT_MAX());
362         }
363         else
364         {
365             io.MouseHoveredViewport = 0;
366             if (io.WantSetMousePos)
367             {
368                 static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
369                 {
370                     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
371                         SDL_WarpMouseGlobal(cast(int)io.MousePos.x, cast(int)io.MousePos.y);
372                     else
373                         SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
374                 }
375                 else
376                     SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
377             }
378             else
379                 io.MousePos = ImVec2(-igGET_FLT_MAX(), -igGET_FLT_MAX());
380         }
381 
382         int mx, my;
383         Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
384         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.
385         io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON!SDL_BUTTON_RIGHT) != 0;
386         io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON!SDL_BUTTON_MIDDLE) != 0;
387         g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
388 
389         static if(SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE)
390         {
391             static if(!CIMGUI_VIEWPORT_BRANCH) //Mantaining compatibility with non docking branch
392             {
393                 SDL_Window* focused_window = SDL_GetKeyboardFocus();
394                 if (g_Window == focused_window)
395                 {
396                     if (g_MouseCanUseGlobalState)
397                     {
398                         // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
399                         // 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.
400                         // Won't use this workaround when on Wayland, as there is no global mouse position.
401                         int wx, wy;
402                         SDL_GetWindowPosition(focused_window, &wx, &wy);
403                         SDL_GetGlobalMouseState(&mx, &my);
404                         mx -= wx;
405                         my -= wy;
406                     }
407                     io.MousePos = ImVec2(cast(float)mx, cast(float)my);
408                 }
409             }
410             else
411             {
412                 if (g_MouseCanUseGlobalState)
413                 {
414                     // SDL 2.0.4 and later has SDL_GetGlobalMouseState() and SDL_CaptureMouse()
415                     int mouse_x_global, mouse_y_global;
416                     SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
417 
418                     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
419                     {
420                         // 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)
421                         if (SDL_Window* focused_window = SDL_GetKeyboardFocus())
422                             if (igFindViewportByPlatformHandle(cast(void*)focused_window) != null)
423                                 io.MousePos = ImVec2(cast(float)mouse_x_global, cast(float)mouse_y_global);
424                     }
425                     else
426                     {
427                         // 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)
428                         if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
429                         {
430                             int window_x, window_y;
431                             SDL_GetWindowPosition(g_Window, &window_x, &window_y);
432                             io.MousePos = ImVec2(cast(float)(mouse_x_global - window_x), cast(float)(mouse_y_global - window_y));
433                         }
434                     }
435                 }
436                 else
437                 {
438                     if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
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     static if(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 //Uses DLL
851 {
852     import bindbc.loader : SharedLib, bindSymbol;
853     extern(C) @nogc nothrow
854     {
855         alias pImGui_ImplSDL2_InitForOpenGL = bool function(SDL_Window* window,void* sdl_gl_context);
856         alias pImGui_ImplSDL2_InitForVulkan = bool function(SDL_Window* window);
857         alias pImGui_ImplSDL2_InitForD3D = bool function(SDL_Window* window);
858         alias pImGui_ImplSDL2_InitForMetal = bool function(SDL_Window* window);
859         alias pImGui_ImplSDL2_Shutdown = void function();
860         alias pImGui_ImplSDL2_NewFrame = void function(SDL_Window* window);
861         alias pImGui_ImplSDL2_ProcessEvent = bool function(const SDL_Event* event);
862     }
863 
864     __gshared
865     {
866         pImGui_ImplSDL2_InitForOpenGL ImGui_ImplSDL2_InitForOpenGL;
867         pImGui_ImplSDL2_InitForVulkan ImGui_ImplSDL2_InitForVulkan;
868         pImGui_ImplSDL2_InitForD3D ImGui_ImplSDL2_InitForD3D;
869         pImGui_ImplSDL2_InitForMetal ImGui_ImplSDL2_InitForMetal;
870         pImGui_ImplSDL2_Shutdown ImGui_ImplSDL2_Shutdown;
871         pImGui_ImplSDL2_NewFrame ImGui_ImplSDL2_NewFrame;
872         pImGui_ImplSDL2_ProcessEvent ImGui_ImplSDL2_ProcessEvent;
873     }
874     void bindSDLImgui(SharedLib lib)
875     {
876         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForOpenGL, "ImGui_ImplSDL2_InitForOpenGL");
877         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForVulkan, "ImGui_ImplSDL2_InitForVulkan");
878         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForD3D, "ImGui_ImplSDL2_InitForD3D");
879         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_InitForMetal, "ImGui_ImplSDL2_InitForMetal");
880         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_Shutdown, "ImGui_ImplSDL2_Shutdown");
881         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_NewFrame, "ImGui_ImplSDL2_NewFrame");
882         lib.bindSymbol(cast(void**)&ImGui_ImplSDL2_ProcessEvent, "ImGui_ImplSDL2_ProcessEvent");
883     }
884 
885 }