Skip to content

Commit

Permalink
Added power saving mode
Browse files Browse the repository at this point in the history
  • Loading branch information
corentin-plouet committed Sep 25, 2019
1 parent f0f5301 commit 57caec9
Show file tree
Hide file tree
Showing 18 changed files with 181 additions and 8 deletions.
3 changes: 0 additions & 3 deletions docs/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- inputs: add mouse cursor for unavailable/no? IDC_NO/SDL_SYSTEM_CURSOR_NO.
- inputs/scrolling: support for smooth scrolling (#2462, #2569)

- misc: idle: expose "woken up" boolean (set by inputs) and/or animation time (for cursor blink) for back-end to be able stop refreshing easily.
- misc: idle: if cursor blink if the _only_ visible animation, core imgui could rewrite vertex alpha to avoid CPU pass on ImGui:: calls.
- misc: idle: if cursor blink if the _only_ visible animation, could even expose a dirty rectangle that optionally can be leverage by some app to render in a smaller viewport, getting rid of much pixel shading cost.
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
Expand All @@ -363,9 +362,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- demo: add virtual scrolling example?
- demo: demonstrate Plot offset
- examples: window minimize, maximize (#583)
- examples: provide a zero frame-rate/idle example.
- examples: apple: example_apple should be using modern GL3.
- examples: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
- examples: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)
- examples: opengl: could use a single vertex buffer and glBufferSubData for uploads?
- examples: opengl: explicitly disable GL_STENCIL_TEST in bindings.
Expand Down
2 changes: 2 additions & 0 deletions examples/example_allegro5/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ int main(int, char**)
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
ImGui_ImplAllegro5_WaitForEvent(queue);
ALLEGRO_EVENT ev;
while (al_get_next_event(queue, &ev))
{
Expand Down Expand Up @@ -105,6 +106,7 @@ int main(int, char**)
ImGui::Text("counter = %d", counter);

ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Text("Frames since last input: %d", ImGui::GetIO().FrameCountSinceLastInput);
ImGui::End();
}

Expand Down
2 changes: 2 additions & 0 deletions examples/example_glfw_opengl3/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ int main(int, char**)
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
ImGui_ImplGlfw_WaitForEvent();
glfwPollEvents();

// Start the Dear ImGui frame
Expand Down Expand Up @@ -157,6 +158,7 @@ int main(int, char**)
ImGui::Text("counter = %d", counter);

ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Text("Frames since last input: %d", ImGui::GetIO().FrameCountSinceLastInput);
ImGui::End();
}

Expand Down
2 changes: 2 additions & 0 deletions examples/example_sdl_opengl3/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ int main(int, char**)
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
ImGui_ImplSDL2_WaitForEvent();
SDL_Event event;
while (SDL_PollEvent(&event))
{
Expand Down Expand Up @@ -159,6 +160,7 @@ int main(int, char**)
ImGui::Text("counter = %d", counter);

ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Text("Frames since last input: %d", ImGui::GetIO().FrameCountSinceLastInput);
ImGui::End();
}

Expand Down
11 changes: 8 additions & 3 deletions examples/example_win32_directx11/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,22 @@ int main(int, char**)
// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
bool done = false;
while (!done)
{
// Poll and handle messages (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
ImGui_ImplWin32_WaitForEvent();
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;

if (msg.message == WM_QUIT)
done = true;
}

// Start the Dear ImGui frame
Expand Down Expand Up @@ -123,6 +127,7 @@ int main(int, char**)
ImGui::Text("counter = %d", counter);

ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Text("Frames since last input: %d", ImGui::GetIO().FrameCountSinceLastInput);
ImGui::End();
}

Expand Down
21 changes: 21 additions & 0 deletions examples/imgui_impl_allegro5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include <stdint.h> // uint64_t
#include <cstring> // memcpy
#include <math.h> // isinf
#include "imgui.h"
#include "imgui_impl_allegro5.h"

Expand Down Expand Up @@ -317,6 +318,24 @@ void ImGui_ImplAllegro5_Shutdown()
g_ClipboardTextData = NULL;
}

void ImGui_ImplAllegro5_WaitForEvent(ALLEGRO_EVENT_QUEUE* queue)
{
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnablePowerSavingMode))
return;

int display_flags = al_get_display_flags(g_Display);
bool window_is_hidden = display_flags & ALLEGRO_MINIMIZED;
double waiting_time = window_is_hidden ? INFINITY : ImGui::GetEventWaitingTime();
if (waiting_time > 0.0)
{
if (isinf(waiting_time))
al_wait_for_event(queue, NULL);
else
al_wait_for_event_timed(queue, NULL, waiting_time);
}
}


// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
Expand All @@ -325,6 +344,8 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT *ev)
{
ImGuiIO& io = ImGui::GetIO();

io.FrameCountSinceLastInput = 0;

switch (ev->type)
{
case ALLEGRO_EVENT_MOUSE_AXES:
Expand Down
2 changes: 2 additions & 0 deletions examples/imgui_impl_allegro5.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
#pragma once

struct ALLEGRO_DISPLAY;
struct ALLEGRO_EVENT_QUEUE;
union ALLEGRO_EVENT;

IMGUI_IMPL_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display);
IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame();
IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API void ImGui_ImplAllegro5_WaitForEvent(ALLEGRO_EVENT_QUEUE* queue);
IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event);

// Use if you want to reset your rendering device without losing ImGui state.
Expand Down
39 changes: 39 additions & 0 deletions examples/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "imgui.h"
#include "imgui_impl_glfw.h"

#include <math.h> // isinf

// GLFW
#include <GLFW/glfw3.h>
#ifdef _WIN32
Expand Down Expand Up @@ -66,6 +68,7 @@ static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;
static GLFWscrollfun g_PrevUserCallbackScroll = NULL;
static GLFWcursorposfun g_PrevUserCallbackCursorPos = NULL;
static GLFWkeyfun g_PrevUserCallbackKey = NULL;
static GLFWcharfun g_PrevUserCallbackChar = NULL;

Expand All @@ -84,6 +87,9 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
if (g_PrevUserCallbackMousebutton != NULL)
g_PrevUserCallbackMousebutton(window, button, action, mods);

ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;

if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed))
g_MouseJustPressed[button] = true;
}
Expand All @@ -94,16 +100,31 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
g_PrevUserCallbackScroll(window, xoffset, yoffset);

ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;
io.MouseWheelH += (float)xoffset;
io.MouseWheel += (float)yoffset;
}

void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double xpos, double ypos)
{
if (g_PrevUserCallbackCursorPos != NULL)
g_PrevUserCallbackCursorPos(window, xpos, ypos);

ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;

// Here, we just take note of the event without actually processing the cursor position.
// This is done in ImGui_ImplGlfw_NewFrame() / ImGui_ImplGlfw_UpdateMousePosAndButtons().
}

void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (g_PrevUserCallbackKey != NULL)
g_PrevUserCallbackKey(window, key, scancode, action, mods);

ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;

if (action == GLFW_PRESS)
io.KeysDown[key] = true;
if (action == GLFW_RELEASE)
Expand All @@ -122,6 +143,7 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
g_PrevUserCallbackChar(window, c);

ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;
io.AddInputCharacter(c);
}

Expand Down Expand Up @@ -185,6 +207,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
{
g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
g_PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback);
g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
}
Expand Down Expand Up @@ -213,6 +236,22 @@ void ImGui_ImplGlfw_Shutdown()
g_ClientApi = GlfwClientApi_Unknown;
}

void ImGui_ImplGlfw_WaitForEvent()
{
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnablePowerSavingMode))
return;

bool window_is_hidden = !glfwGetWindowAttrib(g_Window, GLFW_VISIBLE) || glfwGetWindowAttrib(g_Window, GLFW_ICONIFIED);
double waiting_time = window_is_hidden ? INFINITY : ImGui::GetEventWaitingTime();
if (waiting_time > 0.0)
{
if (isinf(waiting_time))
glfwWaitEvents();
else
glfwWaitEventsTimeout(waiting_time);
}
}

static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
{
// Update buttons
Expand Down
1 change: 1 addition & 0 deletions examples/imgui_impl_glfw.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool in
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
IMGUI_IMPL_API void ImGui_ImplGlfw_WaitForEvent();

// InitXXX function with 'install_callbacks=true': install GLFW callbacks. They will call user's previously installed callbacks, if any.
// InitXXX function with 'install_callbacks=false': do not install GLFW callbacks. You will need to call them yourself from your own GLFW callbacks.
Expand Down
24 changes: 24 additions & 0 deletions examples/imgui_impl_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include "TargetConditionals.h"
#endif

#include <math.h> // isinf

#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)

Expand All @@ -73,6 +75,26 @@ static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
SDL_SetClipboardText(text);
}

void ImGui_ImplSDL2_WaitForEvent()
{
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnablePowerSavingMode))
return;

Uint32 window_flags = SDL_GetWindowFlags(g_Window);
bool window_is_hidden = window_flags & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED);
double waiting_time = window_is_hidden ? INFINITY : ImGui::GetEventWaitingTime();
if (waiting_time > 0.0)
{
if (isinf(waiting_time))
SDL_WaitEvent(NULL);
else
{
const int waiting_time_ms = (int)(1000.0 * ImGui::GetEventWaitingTime());
SDL_WaitEventTimeout(NULL, waiting_time_ms);
}
}
}

// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
Expand All @@ -81,6 +103,8 @@ static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
io.FrameCountSinceLastInput = 0;

switch (event->type)
{
case SDL_MOUSEWHEEL:
Expand Down
1 change: 1 addition & 0 deletions examples/imgui_impl_sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window);
IMGUI_IMPL_API void ImGui_ImplSDL2_WaitForEvent();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
18 changes: 18 additions & 0 deletions examples/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#endif
#include <windows.h>
#include <XInput.h>
#include <math.h> // isinf
#include <tchar.h>

// CHANGELOG
Expand Down Expand Up @@ -236,6 +237,20 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_UpdateGamepads();
}

void ImGui_ImplWin32_WaitForEvent()
{
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnablePowerSavingMode))
return;

BOOL window_is_hidden = !IsWindowVisible(g_hWnd) || IsIconic(g_hWnd);
double waiting_time = window_is_hidden ? INFINITE : ImGui::GetEventWaitingTime();
if (waiting_time > 0.0)
{
DWORD waiting_time_ms = isinf(waiting_time) ? INFINITE : (DWORD)(1000.0 * waiting_time);
::MsgWaitForMultipleObjectsEx(0, NULL, waiting_time_ms, QS_ALLINPUT, MWMO_INPUTAVAILABLE|MWMO_ALERTABLE);
}
}

// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
Expand All @@ -257,6 +272,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
return 0;

ImGuiIO& io = ImGui::GetIO();

io.FrameCountSinceLastInput = 0;

switch (msg)
{
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
Expand Down
1 change: 1 addition & 0 deletions examples/imgui_impl_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
IMGUI_IMPL_API void ImGui_ImplWin32_WaitForEvent();

// Handler for Win32 messages, update mouse/keyboard data.
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
Expand Down
Loading

0 comments on commit 57caec9

Please sign in to comment.