mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-09 23:54:20 +00:00
Merge 4f978fd312 into b467a0466c
This commit is contained in:
commit
021a7c7802
7 changed files with 295 additions and 28 deletions
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
|
|
@ -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*)¤t_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*)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
|
||||
bd->Time = current_time;
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
|
|
@ -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:
|
||||
|
|
@ -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;
|
||||
|
|
@ -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; }
|
||||
|
|
@ -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; }
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -93,6 +95,10 @@ 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;
|
||||
|
|
@ -100,6 +106,7 @@ int main(int, char**)
|
|||
{
|
||||
// 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))
|
||||
{
|
||||
|
|
@ -108,6 +115,8 @@ int main(int, char**)
|
|||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (done)
|
||||
break;
|
||||
|
||||
|
|
@ -128,9 +137,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!).
|
||||
|
|
@ -170,17 +189,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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include <d3d12.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <tchar.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DX12_ENABLE_DEBUG_LAYER
|
||||
|
|
@ -188,6 +190,9 @@ 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);
|
||||
LARGE_INTEGER last_frame_time, timer_freq;
|
||||
QueryPerformanceFrequency(&timer_freq);
|
||||
QueryPerformanceCounter(&last_frame_time);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
|
|
@ -195,6 +200,7 @@ int main(int, char**)
|
|||
{
|
||||
// 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))
|
||||
{
|
||||
|
|
@ -203,6 +209,8 @@ int main(int, char**)
|
|||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (done)
|
||||
break;
|
||||
|
||||
|
|
@ -215,8 +223,17 @@ int main(int, char**)
|
|||
g_SwapChainOccluded = false;
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
ImGui_ImplDX12_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!).
|
||||
|
|
@ -256,6 +273,8 @@ int main(int, char**)
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
LARGE_INTEGER t2; QueryPerformanceCounter(&t2);
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
|
|
@ -288,10 +307,32 @@ int main(int, char**)
|
|||
g_pd3dCommandQueue->Signal(g_fence, ++g_fenceLastSignaledValue);
|
||||
frameCtx->FenceValue = g_fenceLastSignaledValue;
|
||||
|
||||
LARGE_INTEGER t3; QueryPerformanceCounter(&t3);
|
||||
|
||||
// Present
|
||||
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
|
||||
//HRESULT hr = g_pSwapChain->Present(0, g_SwapChainTearingSupport ? DXGI_PRESENT_ALLOW_TEARING : 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", g_frameIndex, 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");
|
||||
}
|
||||
|
||||
|
||||
last_frame_time = t3;
|
||||
g_frameIndex++;
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +481,7 @@ bool CreateDeviceD3D(HWND hWnd)
|
|||
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
g_pSwapChain->SetMaximumFrameLatency(APP_NUM_BACK_BUFFERS);
|
||||
g_pSwapChain->SetMaximumFrameLatency(/*NUM_BACK_BUFFERS*/1);
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
}
|
||||
|
||||
|
|
|
|||
60
imgui.cpp
60
imgui.cpp
|
|
@ -4384,6 +4384,8 @@ void ImGui::Initialize()
|
|||
RegisterFontAtlas(atlas);
|
||||
|
||||
g.Initialized = true;
|
||||
|
||||
g.IO.SetNextRefresh(0, "context created");
|
||||
}
|
||||
|
||||
// This function is merely here to free heap allocations.
|
||||
|
|
@ -4855,10 +4857,16 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
|||
// but once unlocked on a given item we also moving.
|
||||
//if (g.HoverDelayTimer >= delay && (g.HoverDelayTimer - g.IO.DeltaTime < delay || g.MouseStationaryTimer - g.IO.DeltaTime < g.Style.HoverStationaryDelay)) { IMGUI_DEBUG_LOG("HoverDelayTimer = %f/%f, MouseStationaryTimer = %f\n", g.HoverDelayTimer, delay, g.MouseStationaryTimer); }
|
||||
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverItemUnlockedStationaryId != hover_delay_id)
|
||||
return false;
|
||||
{
|
||||
g.IO.SetNextRefresh(0, "HoverDelay start");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g.HoverItemDelayTimer < delay)
|
||||
return false;
|
||||
{
|
||||
g.IO.SetNextRefresh(delay- g.HoverItemDelayTimer, "HoverDelay continue");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5438,6 +5446,9 @@ void ImGui::NewFrame()
|
|||
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// set 'no need for refresh later' initially until one of the widgets tells otherwise
|
||||
g.IO.ResetNextRefresh();
|
||||
|
||||
// Remove pending delete hooks before frame start.
|
||||
// This deferred removal avoid issues of removal while iterating the hook vector
|
||||
for (int n = g.Hooks.Size - 1; n >= 0; n--)
|
||||
|
|
@ -7220,7 +7231,10 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
|
|||
// Collapse button (submitting first so it gets priority when choosing a navigation init fallback)
|
||||
if (has_collapse_button)
|
||||
if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos))
|
||||
{
|
||||
window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function
|
||||
g.IO.SetNextRefresh(0, "window collapse toggled");
|
||||
}
|
||||
|
||||
// Close button
|
||||
if (has_close_button)
|
||||
|
|
@ -7545,13 +7559,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
|
||||
// Hide new windows for one frame until they calculate their size
|
||||
if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
|
||||
{
|
||||
window->HiddenFramesCannotSkipItems = 1;
|
||||
}
|
||||
|
||||
// Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
|
||||
// We reset Size/ContentSize for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
|
||||
if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
|
||||
{
|
||||
window->HiddenFramesCannotSkipItems = 1;
|
||||
window->HiddenFramesCannotSkipItems = 1;
|
||||
if (flags & ImGuiWindowFlags_AlwaysAutoResize)
|
||||
{
|
||||
if (!window_size_x_set_by_api)
|
||||
|
|
@ -7562,6 +7578,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
}
|
||||
}
|
||||
|
||||
if (window->HiddenFramesCannotSkipItems|window->HiddenFramesCanSkipItems|window->HiddenFramesForRenderOnly) g.IO.SetNextRefresh(0, "Window hidden frame"); // don't delay rendering of new frame to get hidden frames working
|
||||
|
||||
// SELECT VIEWPORT
|
||||
// FIXME-VIEWPORT: In the docking/viewport branch, this is the point where we select the current viewport (which may affect the style)
|
||||
|
||||
|
|
@ -10508,7 +10526,10 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
|||
if (event_n == g.InputEventsQueue.Size)
|
||||
g.InputEventsQueue.resize(0);
|
||||
else
|
||||
{
|
||||
g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n);
|
||||
g.IO.SetNextRefresh(0, "inputs queue drain");
|
||||
}
|
||||
|
||||
// Clear buttons state when focus is lost
|
||||
// - this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle.
|
||||
|
|
@ -15873,7 +15894,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha
|
|||
#ifdef _WIN32
|
||||
#include <shellapi.h> // ShellExecuteA()
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "shell32")
|
||||
//#pragma comment(lib, "shell32")
|
||||
#endif
|
||||
static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path)
|
||||
{
|
||||
|
|
@ -15881,7 +15902,10 @@ static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path)
|
|||
ImVector<wchar_t> path_wbuf;
|
||||
path_wbuf.resize(path_wsize);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, path, -1, path_wbuf.Data, path_wsize);
|
||||
return (INT_PTR)::ShellExecuteW(NULL, L"open", path_wbuf.Data, NULL, NULL, SW_SHOWDEFAULT) > 32;
|
||||
// return (INT_PTR)::ShellExecuteW(NULL, L"open", path_wbuf.Data, NULL, NULL, SW_SHOWDEFAULT) > 32;
|
||||
typedef decltype(&::ShellExecuteA) PFN_ShellExecuteA; static PFN_ShellExecuteA fShellExecuteA;
|
||||
static HMODULE hshell32dll = [] { HMODULE h = LoadLibraryA("SHELL32.dll"); if (h) { atexit([]{ FreeLibrary(hshell32dll); }); fShellExecuteA = (PFN_ShellExecuteA) GetProcAddress(hshell32dll, "ShellExecuteA"); } return h; }();
|
||||
if (fShellExecuteA) return (INT_PTR)fShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; else return false;
|
||||
}
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -15920,7 +15944,7 @@ static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { ret
|
|||
|
||||
#include <imm.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "imm32")
|
||||
//#pragma comment(lib, "imm32")
|
||||
#endif
|
||||
|
||||
static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data)
|
||||
|
|
@ -15930,20 +15954,36 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* view
|
|||
if (hwnd == 0)
|
||||
return;
|
||||
|
||||
typedef decltype(&::ImmGetContext) PFN_ImmGetContext; static PFN_ImmGetContext fImmGetContext;
|
||||
typedef decltype(&::ImmSetCompositionWindow) PFN_ImmSetCompositionWindow; static PFN_ImmSetCompositionWindow fImmSetCompositionWindow;
|
||||
typedef decltype(&::ImmSetCandidateWindow) PFN_ImmSetCandidateWindow; static PFN_ImmSetCandidateWindow fImmSetCandidateWindow;
|
||||
typedef decltype(&::ImmReleaseContext) PFN_ImmReleaseContext; static PFN_ImmReleaseContext fImmReleaseContext;
|
||||
static HMODULE himm32dll = []() {
|
||||
HMODULE h = LoadLibraryA("imm32.dll"); if (h) {
|
||||
fImmGetContext = (PFN_ImmGetContext) GetProcAddress(himm32dll, "ImmGetContext");
|
||||
fImmSetCompositionWindow = (PFN_ImmSetCompositionWindow) GetProcAddress(himm32dll, "ImmSetCompositionWindow");
|
||||
fImmSetCandidateWindow = (PFN_ImmSetCandidateWindow) GetProcAddress(himm32dll, "ImmSetCandidateWindow");
|
||||
fImmReleaseContext = (PFN_ImmReleaseContext) GetProcAddress(himm32dll, "ImmReleaseContext");
|
||||
if (fImmGetContext && fImmSetCompositionWindow && fImmSetCandidateWindow && fImmReleaseContext) { atexit([]{ FreeLibrary(himm32dll); }); }
|
||||
FreeLibrary(h);
|
||||
h = nullptr;
|
||||
} return h;}();
|
||||
|
||||
|
||||
//::ImmAssociateContextEx(hwnd, NULL, data->WantVisible ? IACE_DEFAULT : 0);
|
||||
if (HIMC himc = ::ImmGetContext(hwnd))
|
||||
if (HIMC himc = himm32dll ? fImmGetContext(hwnd) : nullptr)
|
||||
{
|
||||
COMPOSITIONFORM composition_form = {};
|
||||
composition_form.ptCurrentPos.x = (LONG)data->InputPos.x;
|
||||
composition_form.ptCurrentPos.y = (LONG)data->InputPos.y;
|
||||
composition_form.dwStyle = CFS_FORCE_POSITION;
|
||||
::ImmSetCompositionWindow(himc, &composition_form);
|
||||
fImmSetCompositionWindow(himc, &composition_form);
|
||||
CANDIDATEFORM candidate_form = {};
|
||||
candidate_form.dwStyle = CFS_CANDIDATEPOS;
|
||||
candidate_form.ptCurrentPos.x = (LONG)data->InputPos.x;
|
||||
candidate_form.ptCurrentPos.y = (LONG)data->InputPos.y;
|
||||
::ImmSetCandidateWindow(himc, &candidate_form);
|
||||
::ImmReleaseContext(hwnd, himc);
|
||||
fImmSetCandidateWindow(himc, &candidate_form);
|
||||
fImmReleaseContext(hwnd, himc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
47
imgui.h
47
imgui.h
|
|
@ -2538,6 +2538,53 @@ struct ImGuiIO
|
|||
int MetricsRenderWindows; // Number of visible windows
|
||||
int MetricsActiveWindows; // Number of active windows
|
||||
ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
|
||||
float NextRefresh; // Optional: tells when should next render happen to see any change in results, 0 on init so that first draw goes through
|
||||
#if 1
|
||||
struct NextRefreshStack_t
|
||||
{
|
||||
size_t Size;
|
||||
struct NextRefreshEntry_t { float delay; char reason[64]; } Entries[16];
|
||||
} NextRefreshStack;
|
||||
|
||||
void ResetNextRefresh()
|
||||
{
|
||||
NextRefresh = FLT_MAX;
|
||||
NextRefreshStack.Size = 0;
|
||||
NextRefreshStack.Entries[0].reason[0]='\0';
|
||||
NextRefreshStack.Entries[0].delay = FLT_MAX;
|
||||
}
|
||||
void SetNextRefresh(float pause_ms, const char* dbg_reason)
|
||||
{
|
||||
if (pause_ms <= NextRefresh)
|
||||
NextRefresh = pause_ms;
|
||||
|
||||
auto* s = NextRefreshStack.Entries;
|
||||
while (s != NextRefreshStack.Entries + NextRefreshStack.Size)
|
||||
{
|
||||
if (pause_ms <= s->delay)
|
||||
break;
|
||||
++s;
|
||||
}
|
||||
|
||||
if (s < NextRefreshStack.Entries + sizeof(NextRefreshStack.Entries) / sizeof(NextRefreshStack.Entries[0]))
|
||||
{
|
||||
size_t new_size = (NextRefreshStack.Size < sizeof(NextRefreshStack.Entries) / sizeof(NextRefreshStack.Entries[0]) ? NextRefreshStack.Size + 1 : sizeof(NextRefreshStack.Entries) / sizeof(NextRefreshStack.Entries[0]));
|
||||
memmove(s + 1, s, sizeof(NextRefreshStack.Entries[0]) * (NextRefreshStack.Entries + new_size - 1 - s));
|
||||
s->delay = pause_ms;
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(s->reason, dbg_reason, sizeof(s->reason) / sizeof(char) - 1);
|
||||
#else
|
||||
strncpy(s->reason, dbg_reason, sizeof(s->reason) / sizeof(char) - 1);
|
||||
#endif
|
||||
NextRefreshStack.Size = new_size;
|
||||
}
|
||||
}
|
||||
//const char* GetNextRefreshReason() const { return NextRefresh_dbg; }
|
||||
#else
|
||||
void ResetNextRefresh() { NextRefresh = FLT_MAX; }
|
||||
void SetNextRefresh(float pause_ms, const char* /*dbg_line*/) { if (pause_ms <= NextRefresh) NextRefresh = pause_ms; }
|
||||
const char* GetNextRefreshReason() const { return ""; }
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
|
||||
|
|
|
|||
|
|
@ -757,7 +757,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|||
ClearActiveID();
|
||||
}
|
||||
if (pressed)
|
||||
{
|
||||
g.ActiveIdHasBeenPressedBefore = true;
|
||||
g.IO.SetNextRefresh(0, "button pressed");
|
||||
}
|
||||
}
|
||||
|
||||
// Activation highlight (this may be a remote activation)
|
||||
|
|
@ -1260,6 +1263,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
|||
*v = checked;
|
||||
pressed = true; // return value
|
||||
MarkItemEdited(id);
|
||||
g.IO.SetNextRefresh(0, "checkbox pressed");
|
||||
}
|
||||
|
||||
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
|
||||
|
|
@ -5576,9 +5580,24 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||
if (render_cursor)
|
||||
{
|
||||
state->CursorAnim += io.DeltaTime;
|
||||
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
|
||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||
|
||||
bool cursor_is_visible = true;
|
||||
if (g.IO.ConfigInputTextCursorBlink)
|
||||
{
|
||||
float next_refresh_time = -state->CursorAnim;
|
||||
if (state->CursorAnim > 0.0f)
|
||||
{
|
||||
float modded = ImFmod(state->CursorAnim, 1.20f);
|
||||
bool now_visible_blink_phase = modded <= 0.80f;
|
||||
state->CursorAnim = modded; //prevent fp error from accumulation
|
||||
next_refresh_time = now_visible_blink_phase ? 0.80f - modded : 1.20f - modded;
|
||||
cursor_is_visible = now_visible_blink_phase;
|
||||
}
|
||||
g.IO.SetNextRefresh( next_refresh_time, "text cursor blink");
|
||||
}
|
||||
|
||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
|
||||
|
||||
|
|
@ -9486,6 +9505,9 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||
if (menuset_is_open)
|
||||
PopItemFlag();
|
||||
|
||||
if (pressed)
|
||||
g.IO.SetNextRefresh(0,"menu item pressed");
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue