WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 89 additions & 13 deletions backends/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ struct ImGui_ImplWin32_Data
ImGuiMouseCursor LastMouseCursor;
UINT32 KeyboardCodePage;

int MouseX, MouseY; // against spurious WM_MOUSEMOVE events

#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
bool HasGamepad;
bool WantUpdateHasGamepad;
Expand Down Expand Up @@ -180,6 +182,8 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
bd->Time = perf_counter;
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
bd->MouseX = -1;
bd->MouseY = -1;

// Set platform dependent data in viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
Expand Down Expand Up @@ -393,20 +397,59 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
#endif
}

void ImGui_ImplWin32_NewFrame()
bool ImGui_ImplWin32_NewFrame(bool poll_only)
{
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized? Did you call ImGui_ImplWin32_Init()?");
ImGuiIO& io = ImGui::GetIO();

INT64 current_time;




for (;;)
{
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);

double next_refresh = !poll_only ? io.NextRefresh : 0.0;

double cur_delta = double(current_time - bd->Time) / bd->TicksPerSecond;
if (cur_delta <= next_refresh)
{
double ms_to_wait_double = (next_refresh - cur_delta) * 1000.0f;
unsigned int ms_to_wait = ms_to_wait_double >= MAXDWORD ? INFINITE : unsigned int(ms_to_wait_double);
if (ms_to_wait)
MsgWaitForMultipleObjectsEx(0, nullptr, ms_to_wait, QS_ALLEVENTS, 0);
}


MSG msg;
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
if (msg.message != WM_QUIT)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
return false;
}


if (cur_delta <= next_refresh)
continue;

break;
}


// Setup display size (every frame to accommodate for window resizing)
RECT rect = { 0, 0, 0, 0 };
::GetClientRect(bd->hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));

// Setup time step
INT64 current_time = 0;
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
bd->Time = current_time;

Expand All @@ -426,6 +469,8 @@ void ImGui_ImplWin32_NewFrame()

// Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads(io);

return true;
}

// Map VK_xxx to ImGuiKey_xxx.
Expand Down Expand Up @@ -628,6 +673,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
// This version is in theory thread-safe in the sense that no path should access ImGui::GetCurrentContext().
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io)
{
const char* key_refresh_reason = nullptr;
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
if (bd == nullptr)
return 0;
Expand All @@ -652,8 +698,19 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
return 0;
io.AddMouseSourceEvent(mouse_source);
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);

{ // SergeyN - filter out spurious mouse events
int m_x = GET_X_LPARAM(lParam), m_y = GET_Y_LPARAM(lParam);
if (bd->MouseX != m_x || bd->MouseY != m_y) // spurious WM_MOUSEMOVE events are a real thing. don't act on them
{
bd->MouseX = m_x, bd->MouseY = m_y;

io.SetNextRefresh(0, "mouse move"); //return 0;

io.AddMouseSourceEvent(mouse_source);
io.AddMousePosEvent((float)m_x, (float)m_y);
}
}
return 0;
}
case WM_MOUSELEAVE:
Expand All @@ -665,6 +722,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
if (bd->MouseHwnd == hwnd)
bd->MouseHwnd = nullptr;
bd->MouseTrackedArea = 0;
bd->MouseX = -1, bd->MouseY = -1;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}
return 0;
Expand All @@ -679,11 +737,18 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}
return 0;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
case WM_LBUTTONDOWN: key_refresh_reason = "mouse lbuttonup down"; goto md;
case WM_LBUTTONDBLCLK: key_refresh_reason = "mouse lbuttonup dblclk"; goto md;
case WM_RBUTTONDOWN: key_refresh_reason = "mouse rbuttonup down"; goto md;
case WM_RBUTTONDBLCLK: key_refresh_reason = "mouse rbuttonup dblclk"; goto md;
case WM_MBUTTONDOWN: key_refresh_reason = "mouse mbuttonup donw"; goto md;
case WM_MBUTTONDBLCLK: key_refresh_reason = "mouse mbuttonup dblclk"; goto md;
case WM_XBUTTONDOWN: key_refresh_reason = "mouse xbuttonup down"; goto md;
case WM_XBUTTONDBLCLK: key_refresh_reason = "mouse xbuttonup dblclk";
md:
{
io.SetNextRefresh(0, key_refresh_reason);

ImGuiMouseSource mouse_source = ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo();
int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
Expand All @@ -700,11 +765,14 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
io.AddMouseButtonEvent(button, true);
return 0;
}
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_XBUTTONUP:
case WM_LBUTTONUP:key_refresh_reason = "mouse lbuttonup up"; goto mu;
case WM_RBUTTONUP:key_refresh_reason = "mouse rbutton up"; goto mu;
case WM_MBUTTONUP:key_refresh_reason = "mouse mbutton up"; goto mu;
case WM_XBUTTONUP:key_refresh_reason = "mouse xbutton up";
mu:
{
io.SetNextRefresh(0, key_refresh_reason);

ImGuiMouseSource mouse_source = ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo();
int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; }
Expand All @@ -719,19 +787,27 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
return 0;
}
case WM_MOUSEWHEEL:
io.SetNextRefresh(0, "wheel up");
io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
return 0;
case WM_MOUSEHWHEEL:
io.SetNextRefresh(0, "wheel down");
io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
return 0;
case WM_KEYDOWN:
key_refresh_reason = "key down"; goto l;
case WM_KEYUP:
key_refresh_reason = "key up"; goto l;
case WM_SYSKEYDOWN:
key_refresh_reason = "syskey down"; goto l;
case WM_SYSKEYUP:
{
key_refresh_reason = "key up";
l:
const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
if (wParam < 256)
{
io.SetNextRefresh(0, key_refresh_reason);
// Submit modifiers
ImGui_ImplWin32_UpdateKeyModifiers(io);

Expand Down
2 changes: 1 addition & 1 deletion backends/imgui_impl_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplWin32_NewFrame(bool poll = false);

// Win32 message handler your application need to call.
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
Expand Down
43 changes: 42 additions & 1 deletion examples/example_win32_directx11/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "imgui_impl_dx11.h"
#include <d3d11.h>
#include <tchar.h>
#include <cstdio>
#include <string>

// Data
static ID3D11Device* g_pd3dDevice = nullptr;
Expand Down Expand Up @@ -91,13 +93,18 @@ int main(int, char**)
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
int fame_number = 0;
LARGE_INTEGER last_frame_time, timer_freq;
QueryPerformanceFrequency(&timer_freq);
QueryPerformanceCounter(&last_frame_time);

// Main loop
bool done = false;
while (!done)
{
// Poll and handle messages (inputs, window resize, etc.)
// See the WndProc() function below for our to dispatch events to the Win32 backend.
#if 0
MSG msg;
while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{
Expand All @@ -106,6 +113,8 @@ int main(int, char**)
if (msg.message == WM_QUIT)
done = true;
}
#endif

if (done)
break;

Expand All @@ -126,9 +135,19 @@ int main(int, char**)
CreateRenderTarget();
}


// Start the Dear ImGui frame
if (!ImGui_ImplWin32_NewFrame())
break;

LARGE_INTEGER t0; QueryPerformanceCounter(&t0);
auto refresh_reason = io.NextRefreshStack.Entries[0];// double refresh_delay = io.NextRefresh >= FLT_MAX ? 99.99f : io.NextRefresh;

// Start the Dear ImGui frame
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();

LARGE_INTEGER t1; QueryPerformanceCounter(&t1);

ImGui::NewFrame();

// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
Expand Down Expand Up @@ -168,17 +187,39 @@ int main(int, char**)
ImGui::End();
}

LARGE_INTEGER t2; QueryPerformanceCounter(&t2);

// Rendering
ImGui::Render();

const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

LARGE_INTEGER t3; QueryPerformanceCounter(&t3);

// Present
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
//HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);


LARGE_INTEGER t4; QueryPerformanceCounter(&t4);

double layout_time = double(t2.QuadPart - t1.QuadPart) / timer_freq.QuadPart;
double render_time = double((t1.QuadPart - t0.QuadPart) + (t3.QuadPart - t2.QuadPart)) / timer_freq.QuadPart;
double present_time = double(t4.QuadPart - t3.QuadPart) / timer_freq.QuadPart;
double sleep_time = double(t0.QuadPart - last_frame_time.QuadPart) / timer_freq.QuadPart;

printf("ImGui #%i(%+6.3fs %ims(I%ims,R%ims,P%ims)), reason: %s (%0.2fs) ... %s", fame_number++, sleep_time, (int)round((layout_time + render_time) * 1000.0), (int)round(layout_time * 1000.0), (int)round(render_time * 1000.0), (int)round(present_time * 1000.0), refresh_reason.reason, refresh_reason.delay, io.NextRefreshStack.Size ? "" : "\n");
if (io.NextRefreshStack.Size)
{
printf(" refresh stack:");
for (int i = 0; i < io.NextRefreshStack.Size; ++i)
printf("%c%s(+%0.2fs)", i == 0 ? ' ' : ',', io.NextRefreshStack.Entries[i].reason, io.NextRefreshStack.Entries[i].delay);
printf("\n");
}
}

// Cleanup
Expand Down
Loading
Loading