mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-25 14:09:10 +00:00
Add progress bar support for Windows (#12530)
This commit is contained in:
parent
6b13d69105
commit
7a10fcdccc
19 changed files with 239 additions and 2 deletions
|
@ -1979,6 +1979,7 @@ elseif(WINDOWS)
|
|||
check_include_file(audioclient.h HAVE_AUDIOCLIENT_H)
|
||||
check_include_file(sensorsapi.h HAVE_SENSORSAPI_H)
|
||||
check_include_file(shellscalingapi.h HAVE_SHELLSCALINGAPI_H)
|
||||
check_include_file(shobjidl_core.h HAVE_SHOBJIDL_CORE_H)
|
||||
check_c_source_compiles("
|
||||
#include <windows.h>
|
||||
#include <mfapi.h>
|
||||
|
|
|
@ -15,6 +15,7 @@ if(MSVC)
|
|||
set(HAVE_MMDEVICEAPI_H "1" CACHE INTERNAL "Have include mmdeviceapi.h")
|
||||
set(HAVE_SENSORSAPI_H "1" CACHE INTERNAL "Have include sensorsapi.h")
|
||||
set(HAVE_SHELLSCALINGAPI_H "1" CACHE INTERNAL "Have include shellscalingapi.h")
|
||||
set(HAVE_SHOBJIDL_CORE_H "1" CACHE INTERNAL "Have include shobjidl_core.h")
|
||||
set(HAVE_TPCSHRD_H "1" CACHE INTERNAL "Have include tpcshrd.h")
|
||||
set(HAVE_WIN32_CC "1" CACHE INTERNAL "Test HAVE_WIN32_CC")
|
||||
set(HAVE_XINPUT_H "1" CACHE INTERNAL "Test HAVE_XINPUT_H")
|
||||
|
|
|
@ -87,6 +87,8 @@ typedef struct
|
|||
const char *window_icon;
|
||||
SDL_WindowFlags window_flags;
|
||||
bool flash_on_focus_loss;
|
||||
SDL_ProgressState progress_state;
|
||||
float progress_value;
|
||||
int window_x;
|
||||
int window_y;
|
||||
int window_w;
|
||||
|
|
|
@ -307,6 +307,20 @@ typedef enum SDL_FlashOperation
|
|||
SDL_FLASH_UNTIL_FOCUSED /**< Flash the window until it gets focus */
|
||||
} SDL_FlashOperation;
|
||||
|
||||
/**
|
||||
* Window progress state
|
||||
*
|
||||
* \since This enum is available since SDL 3.2.8.
|
||||
*/
|
||||
typedef enum SDL_ProgressState
|
||||
{
|
||||
SDL_PROGRESS_STATE_NONE, /**< No progress bar is shown */
|
||||
SDL_PROGRESS_STATE_INDETERMINATE, /**< The progress bar is shown in a indeterminate state */
|
||||
SDL_PROGRESS_STATE_NORMAL, /**< The progress bar is shown in a normal state */
|
||||
SDL_PROGRESS_STATE_PAUSED, /**< The progress bar is shown in a paused state */
|
||||
SDL_PROGRESS_STATE_ERROR /**< The progress bar is shown in an error state */
|
||||
} SDL_ProgressState;
|
||||
|
||||
/**
|
||||
* An opaque handle to an OpenGL context.
|
||||
*
|
||||
|
@ -2806,6 +2820,34 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowShape(SDL_Window *window, SDL_Surf
|
|||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation);
|
||||
|
||||
/**
|
||||
* Sets the state of the progress bar for the given window’s taskbar icon.
|
||||
*
|
||||
* \param window the window whose progress state is to be modified.
|
||||
* \param state the progress state.
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
*
|
||||
* \threadsafety This function should only be called on the main thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.2.8.
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressState(SDL_Window *window, SDL_ProgressState state);
|
||||
|
||||
/**
|
||||
* Sets the value of the progress bar for the given window’s taskbar icon.
|
||||
*
|
||||
* \param window the window whose progress value is to be modified.
|
||||
* \param value the progress value (0.0f - start, 1.0f - end).
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
*
|
||||
* \threadsafety This function should only be called on the main thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.2.8.
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressValue(SDL_Window *window, float value);
|
||||
|
||||
/**
|
||||
* Destroy a window.
|
||||
*
|
||||
|
|
|
@ -225,6 +225,7 @@
|
|||
#cmakedefine HAVE_TPCSHRD_H 1
|
||||
#cmakedefine HAVE_ROAPI_H 1
|
||||
#cmakedefine HAVE_SHELLSCALINGAPI_H 1
|
||||
#cmakedefine HAVE_SHOBJIDL_CORE_H 1
|
||||
|
||||
#cmakedefine USE_POSIX_SPAWN 1
|
||||
|
||||
|
|
|
@ -95,6 +95,9 @@ typedef unsigned int uintptr_t;
|
|||
#if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0603 /* Windows 8.1 SDK */
|
||||
#define HAVE_SHELLSCALINGAPI_H 1
|
||||
#endif
|
||||
#if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0601 /* Windows 7 SDK */
|
||||
#define HAVE_SHOBJIDL_CORE_H 1
|
||||
#endif
|
||||
#define HAVE_MMDEVICEAPI_H 1
|
||||
#define HAVE_AUDIOCLIENT_H 1
|
||||
#define HAVE_TPCSHRD_H 1
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#define HAVE_D3D11_H 1
|
||||
#define HAVE_ROAPI_H 1
|
||||
#define HAVE_SHELLSCALINGAPI_H 1
|
||||
#define HAVE_SHOBJIDL_CORE_H 1
|
||||
#define HAVE_MMDEVICEAPI_H 1
|
||||
#define HAVE_AUDIOCLIENT_H 1
|
||||
#define HAVE_TPCSHRD_H 1
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
/*#define HAVE_WINDOWS_GAMING_INPUT_H 1*/
|
||||
/*#define HAVE_ROAPI_H 1*/
|
||||
/*#define HAVE_SHELLSCALINGAPI_H 1*/
|
||||
/*#define HAVE_SHOBJIDL_CORE_H 1*/
|
||||
#define HAVE_MMDEVICEAPI_H 1
|
||||
#define HAVE_AUDIOCLIENT_H 1
|
||||
/*#define HAVE_TPCSHRD_H 1*/
|
||||
|
|
|
@ -1242,6 +1242,8 @@ SDL3_0.0.0 {
|
|||
SDL_SetGPURenderStateFragmentUniforms;
|
||||
SDL_SetRenderGPUState;
|
||||
SDL_DestroyGPURenderState;
|
||||
SDL_SetWindowProgressState;
|
||||
SDL_SetWindowProgressValue;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
|
|
@ -1267,3 +1267,5 @@
|
|||
#define SDL_SetGPURenderStateFragmentUniforms SDL_SetGPURenderStateFragmentUniforms_REAL
|
||||
#define SDL_SetRenderGPUState SDL_SetRenderGPUState_REAL
|
||||
#define SDL_DestroyGPURenderState SDL_DestroyGPURenderState_REAL
|
||||
#define SDL_SetWindowProgressState SDL_SetWindowProgressState_REAL
|
||||
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
|
||||
|
|
|
@ -1275,3 +1275,5 @@ SDL_DYNAPI_PROC(SDL_GPURenderState*,SDL_CreateGPURenderState,(SDL_Renderer *a,SD
|
|||
SDL_DYNAPI_PROC(bool,SDL_SetGPURenderStateFragmentUniforms,(SDL_GPURenderState *a,Uint32 b,const void *c,Uint32 d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_SetRenderGPUState,(SDL_Renderer *a,SDL_GPURenderState *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_DestroyGPURenderState,(SDL_GPURenderState *a),(a),)
|
||||
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressState,(SDL_Window *a,SDL_ProgressState b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return)
|
||||
|
|
|
@ -2455,6 +2455,31 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
|
|||
}
|
||||
}
|
||||
break;
|
||||
case SDLK_P:
|
||||
if (withAlt) {
|
||||
/* Ctrl-P Cycle through progress states */
|
||||
SDL_Window *window = SDL_GetWindowFromEvent(event);
|
||||
if (window) {
|
||||
state->progress_state += 1;
|
||||
if (state->progress_state > SDL_PROGRESS_STATE_ERROR) {
|
||||
state->progress_state = SDL_PROGRESS_STATE_NONE;
|
||||
}
|
||||
SDL_SetWindowProgressState(window, state->progress_state);
|
||||
}
|
||||
}
|
||||
else if (withControl)
|
||||
{
|
||||
/* Alt-P Increase progress value */
|
||||
SDL_Window *window = SDL_GetWindowFromEvent(event);
|
||||
if (window) {
|
||||
state->progress_value += 0.1f;
|
||||
if (state->progress_value > 1.f) {
|
||||
state->progress_value = 0.f;
|
||||
}
|
||||
SDL_SetWindowProgressValue(window, state->progress_value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDLK_G:
|
||||
if (withControl) {
|
||||
/* Ctrl-G toggle mouse grab */
|
||||
|
|
|
@ -303,6 +303,8 @@ struct SDL_VideoDevice
|
|||
void (*OnWindowEnter)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
bool (*UpdateWindowShape)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *shape);
|
||||
bool (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
bool (*SetWindowProgressState)(SDL_VideoDevice *_this, SDL_Window *window, SDL_ProgressState state);
|
||||
bool (*SetWindowProgressValue)(SDL_VideoDevice *_this, SDL_Window *window, float value);
|
||||
bool (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
|
||||
bool (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
|
|
|
@ -3921,6 +3921,30 @@ bool SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation)
|
|||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SetWindowProgressState(SDL_Window *window, SDL_ProgressState state)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, false);
|
||||
CHECK_WINDOW_NOT_POPUP(window, false);
|
||||
|
||||
if (_this->SetWindowProgressState) {
|
||||
return _this->SetWindowProgressState(_this, window, state);
|
||||
}
|
||||
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SetWindowProgressValue(SDL_Window *window, float value)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, false);
|
||||
CHECK_WINDOW_NOT_POPUP(window, false);
|
||||
|
||||
if (_this->SetWindowProgressValue) {
|
||||
return _this->SetWindowProgressValue(_this, window, value);
|
||||
}
|
||||
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
void SDL_OnWindowShown(SDL_Window *window)
|
||||
{
|
||||
// Set window state if we have pending window flags cached
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
#include "wmmsg.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
#include <shobjidl_core.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDL_PLATFORM_GDK
|
||||
#include "../../core/gdk/SDL_gdk.h"
|
||||
#endif
|
||||
|
@ -2431,6 +2435,12 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
if (msg == data->videodata->WM_TASKBAR_BUTTON_CREATED) {
|
||||
data->videodata->taskbar_button_created = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If there's a window proc, assume it's going to handle messages
|
||||
if (data->wndproc) {
|
||||
return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "SDL_windowsrawinput.h"
|
||||
#include "SDL_windowsvulkan.h"
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
#include <shobjidl_core.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDL_GDK_TEXTINPUT
|
||||
#include "../gdk/SDL_gdktextinput.h"
|
||||
#endif
|
||||
|
@ -268,6 +272,8 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
|
|||
device->SetWindowHitTest = WIN_SetWindowHitTest;
|
||||
device->AcceptDragAndDrop = WIN_AcceptDragAndDrop;
|
||||
device->FlashWindow = WIN_FlashWindow;
|
||||
device->SetWindowProgressState = WIN_SetWindowProgressState;
|
||||
device->SetWindowProgressValue = WIN_SetWindowProgressValue;
|
||||
device->ShowWindowSystemMenu = WIN_ShowWindowSystemMenu;
|
||||
device->SetWindowFocusable = WIN_SetWindowFocusable;
|
||||
device->UpdateWindowShape = WIN_UpdateWindowShape;
|
||||
|
@ -552,6 +558,9 @@ static bool WIN_VideoInit(SDL_VideoDevice *_this)
|
|||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
data->_SDL_WAKEUP = RegisterWindowMessageA("_SDL_WAKEUP");
|
||||
#endif
|
||||
#if defined(HAVE_SHOBJIDL_CORE_H)
|
||||
data->WM_TASKBAR_BUTTON_CREATED = RegisterWindowMessageA("TaskbarButtonCreated");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -581,6 +590,14 @@ void WIN_VideoQuit(SDL_VideoDevice *_this)
|
|||
}
|
||||
#endif // !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
||||
|
||||
#if defined(HAVE_SHOBJIDL_CORE_H)
|
||||
data->taskbar_button_created = false;
|
||||
if (data->taskbar_list) {
|
||||
IUnknown_Release(data->taskbar_list);
|
||||
data->taskbar_list = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data->coinitialized) {
|
||||
WIN_CoUninitialize();
|
||||
data->coinitialized = false;
|
||||
|
|
|
@ -308,6 +308,8 @@ typedef enum PROCESS_DPI_AWARENESS
|
|||
#include <shellscalingapi.h>
|
||||
#endif
|
||||
|
||||
typedef struct ITaskbarList3 ITaskbarList3;
|
||||
|
||||
#ifndef _DPI_AWARENESS_CONTEXTS_
|
||||
|
||||
typedef enum DPI_AWARENESS
|
||||
|
@ -536,6 +538,12 @@ struct SDL_VideoData
|
|||
|
||||
BYTE pre_hook_key_state[256];
|
||||
UINT _SDL_WAKEUP;
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
UINT WM_TASKBAR_BUTTON_CREATED;
|
||||
bool taskbar_button_created;
|
||||
ITaskbarList3 *taskbar_list;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern bool g_WindowsEnableMessageLoop;
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
// Dropfile support
|
||||
#include <shellapi.h>
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
#include <shobjidl_core.h>
|
||||
#endif
|
||||
|
||||
// Dark mode support
|
||||
typedef enum {
|
||||
UXTHEME_APPMODE_DEFAULT,
|
||||
|
@ -180,6 +184,33 @@ static DWORD GetWindowStyleEx(SDL_Window *window)
|
|||
return style;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHOBJIDL_CORE_H
|
||||
static ITaskbarList3 *GetTaskbarList(SDL_Window* window)
|
||||
{
|
||||
const SDL_WindowData *data = window->internal;
|
||||
if (!data->videodata->taskbar_button_created) {
|
||||
WIN_SetError("Missing taskbar button");
|
||||
return NULL;
|
||||
}
|
||||
if (!data->videodata->taskbar_list) {
|
||||
HRESULT ret = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_ALL, &IID_ITaskbarList3, (LPVOID *)&data->videodata->taskbar_list);
|
||||
if (FAILED(ret)) {
|
||||
WIN_SetError("Unable to create taskbar list");
|
||||
return NULL;
|
||||
}
|
||||
ITaskbarList3 *taskbarlist = data->videodata->taskbar_list;
|
||||
ret = taskbarlist->lpVtbl->HrInit(taskbarlist);
|
||||
if (FAILED(ret)) {
|
||||
taskbarlist->lpVtbl->Release(taskbarlist);
|
||||
data->videodata->taskbar_list = NULL;
|
||||
WIN_SetError("Unable to initialize taskbar list");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return data->videodata->taskbar_list;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns arguments to pass to SetWindowPos - the window rect, including frame, in Windows coordinates.
|
||||
* Can be called before we have a HWND.
|
||||
|
@ -2217,6 +2248,66 @@ bool WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperat
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WIN_SetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window, SDL_ProgressState state)
|
||||
{
|
||||
#ifndef HAVE_SHOBJIDL_CORE_H
|
||||
return false;
|
||||
#else
|
||||
ITaskbarList3 *taskbar_list = GetTaskbarList(window);
|
||||
if (!taskbar_list) {
|
||||
return false;
|
||||
};
|
||||
|
||||
TBPFLAG tbpFlags;
|
||||
switch (state) {
|
||||
case SDL_PROGRESS_STATE_NONE:
|
||||
tbpFlags = TBPF_NOPROGRESS;
|
||||
break;
|
||||
case SDL_PROGRESS_STATE_INDETERMINATE:
|
||||
tbpFlags = TBPF_INDETERMINATE;
|
||||
break;
|
||||
case SDL_PROGRESS_STATE_NORMAL:
|
||||
tbpFlags = TBPF_NORMAL;
|
||||
break;
|
||||
case SDL_PROGRESS_STATE_PAUSED:
|
||||
tbpFlags = TBPF_PAUSED;
|
||||
break;
|
||||
case SDL_PROGRESS_STATE_ERROR:
|
||||
tbpFlags = TBPF_ERROR;
|
||||
break;
|
||||
default:
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
HRESULT ret = taskbar_list->lpVtbl->SetProgressState(taskbar_list, window->internal->hwnd, tbpFlags);
|
||||
if (FAILED(ret)) {
|
||||
return WIN_SetErrorFromHRESULT("ITaskbarList3::SetProgressState()", ret);
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // HAVE_SHOBJIDL_CORE_H
|
||||
}
|
||||
|
||||
bool WIN_SetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window, float value)
|
||||
{
|
||||
#ifndef HAVE_SHOBJIDL_CORE_H
|
||||
return false;
|
||||
#else
|
||||
ITaskbarList3 *taskbar_list = GetTaskbarList(window);
|
||||
if (!taskbar_list) {
|
||||
return false;
|
||||
};
|
||||
|
||||
SDL_clamp(value, 0.0f, 1.f);
|
||||
HRESULT ret = taskbar_list->lpVtbl->SetProgressValue(taskbar_list, window->internal->hwnd, (ULONGLONG)(value * 10000.f), 10000);
|
||||
if (FAILED(ret)) {
|
||||
return WIN_SetErrorFromHRESULT("ITaskbarList3::SetProgressValue()", ret);
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // HAVE_SHOBJIDL_CORE_H
|
||||
}
|
||||
|
||||
void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
|
||||
{
|
||||
const SDL_WindowData *data = window->internal;
|
||||
|
|
|
@ -133,6 +133,8 @@ extern void WIN_UnclipCursorForWindow(SDL_Window *window);
|
|||
extern bool WIN_SetWindowHitTest(SDL_Window *window, bool enabled);
|
||||
extern void WIN_AcceptDragAndDrop(SDL_Window *window, bool accept);
|
||||
extern bool WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
extern bool WIN_SetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window, SDL_ProgressState state);
|
||||
extern bool WIN_SetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window, float value);
|
||||
extern void WIN_UpdateDarkModeForHWND(HWND hwnd);
|
||||
extern bool WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type);
|
||||
extern void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue