WindowProgressState API getters and fixes (#12629)

This commit is contained in:
Rémy Tassoux 2025-03-25 16:03:32 +01:00 committed by GitHub
parent b520cde18f
commit 6cc00a31b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 131 additions and 37 deletions

View file

@ -87,8 +87,6 @@ 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;

View file

@ -314,11 +314,12 @@ typedef enum SDL_FlashOperation
*/
typedef enum SDL_ProgressState
{
SDL_PROGRESS_STATE_INVALID = -1, /**< An invalid progress state indicating an error; check SDL_GetError() */
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_PROGRESS_STATE_ERROR /**< The progress bar is shown in a state indicating the application had an error */
} SDL_ProgressState;
/**
@ -2836,11 +2837,20 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOp
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressState(SDL_Window *window, SDL_ProgressState state);
/**
* Sets the value of the progress bar for the given windows taskbar icon.
* Get the state of the progress bar for the given windows taskbar icon.
*
* If the state is `SDL_PROGRESS_STATE_NONE` or
* `SDL_PROGRESS_STATE_INDETERMINATE`, it gets changed to
* `SDL_PROGRESS_STATE_NORMAL`.
* \param window the window to get the current progress state from.
* \returns the progress state, or SDL_PROGRESS_STATE_INVALID 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.4.0.
*/
extern SDL_DECLSPEC SDL_ProgressState SDLCALL SDL_GetWindowProgressState(SDL_Window *window);
/**
* Sets the value of the progress bar for the given windows taskbar icon.
*
* \param window the window whose progress value is to be modified.
* \param value the progress value (0.0f - start, 1.0f - end). If the value is
@ -2854,6 +2864,19 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressState(SDL_Window *window,
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressValue(SDL_Window *window, float value);
/**
* Get the value of the progress bar for the given windows taskbar icon.
*
* \param window the window to get the current progress value from.
* \returns the progress value in the range of [0.0 - 1.0], or -1 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.4.0.
*/
extern SDL_DECLSPEC float SDLCALL SDL_GetWindowProgressValue(SDL_Window *window);
/**
* Destroy a window.
*

View file

@ -1244,6 +1244,8 @@ SDL3_0.0.0 {
SDL_DestroyGPURenderState;
SDL_SetWindowProgressState;
SDL_SetWindowProgressValue;
SDL_GetWindowProgressState;
SDL_GetWindowProgressValue;
# extra symbols go here (don't modify this line)
local: *;
};

View file

@ -1269,3 +1269,5 @@
#define SDL_DestroyGPURenderState SDL_DestroyGPURenderState_REAL
#define SDL_SetWindowProgressState SDL_SetWindowProgressState_REAL
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
#define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL
#define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL

View file

@ -1277,3 +1277,5 @@ SDL_DYNAPI_PROC(bool,SDL_SetRenderGPUState,(SDL_Renderer *a,SDL_GPURenderState *
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)
SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return)

View file

@ -2460,11 +2460,12 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
/* 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;
float progress_state = SDL_GetWindowProgressState(window);
progress_state += 1;
if (progress_state > SDL_PROGRESS_STATE_ERROR) {
progress_state = SDL_PROGRESS_STATE_NONE;
}
SDL_SetWindowProgressState(window, state->progress_state);
SDL_SetWindowProgressState(window, progress_state);
}
}
else if (withControl)
@ -2472,11 +2473,13 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
/* 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;
float progress_value = SDL_GetWindowProgressValue(window);
if (withShift) {
progress_value -= 0.1f;
} else {
progress_value += 0.1f;
}
SDL_SetWindowProgressValue(window, state->progress_value);
SDL_SetWindowProgressValue(window, progress_value);
}
}
break;

View file

@ -304,7 +304,9 @@ struct SDL_VideoDevice
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);
SDL_ProgressState (*GetWindowProgressState)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*SetWindowProgressValue)(SDL_VideoDevice *_this, SDL_Window *window, float value);
float (*GetWindowProgressValue)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
bool (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);

View file

@ -3937,6 +3937,18 @@ bool SDL_SetWindowProgressState(SDL_Window *window, SDL_ProgressState state)
return SDL_Unsupported();
}
SDL_ProgressState SDL_GetWindowProgressState(SDL_Window *window)
{
CHECK_WINDOW_MAGIC(window, false);
CHECK_WINDOW_NOT_POPUP(window, false);
if (_this->GetWindowProgressState) {
return _this->GetWindowProgressState(_this, window);
}
return SDL_Unsupported();
}
bool SDL_SetWindowProgressValue(SDL_Window *window, float value)
{
CHECK_WINDOW_MAGIC(window, false);
@ -3951,6 +3963,18 @@ bool SDL_SetWindowProgressValue(SDL_Window *window, float value)
return SDL_Unsupported();
}
float SDL_GetWindowProgressValue(SDL_Window *window)
{
CHECK_WINDOW_MAGIC(window, false);
CHECK_WINDOW_NOT_POPUP(window, false);
if (_this->GetWindowProgressValue) {
return _this->GetWindowProgressValue(_this, window);
}
return SDL_Unsupported();
}
void SDL_OnWindowShown(SDL_Window *window)
{
// Set window state if we have pending window flags cached

View file

@ -2437,7 +2437,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
#ifdef HAVE_SHOBJIDL_CORE_H
if (msg == data->videodata->WM_TASKBAR_BUTTON_CREATED) {
data->videodata->taskbar_button_created = true;
SDL_Window *window = data->window;
window->internal->taskbar_button_created = true;
WIN_ApplyWindowProgress(window);
}
#endif

View file

@ -273,7 +273,9 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
device->AcceptDragAndDrop = WIN_AcceptDragAndDrop;
device->FlashWindow = WIN_FlashWindow;
device->SetWindowProgressState = WIN_SetWindowProgressState;
device->GetWindowProgressState = WIN_GetWindowProgressState;
device->SetWindowProgressValue = WIN_SetWindowProgressValue;
device->GetWindowProgressValue = WIN_GetWindowProgressValue;
device->ShowWindowSystemMenu = WIN_ShowWindowSystemMenu;
device->SetWindowFocusable = WIN_SetWindowFocusable;
device->UpdateWindowShape = WIN_UpdateWindowShape;
@ -591,7 +593,6 @@ 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;

View file

@ -541,7 +541,6 @@ struct SDL_VideoData
#ifdef HAVE_SHOBJIDL_CORE_H
UINT WM_TASKBAR_BUTTON_CREATED;
bool taskbar_button_created;
ITaskbarList3 *taskbar_list;
#endif
};

View file

@ -188,10 +188,7 @@ static DWORD GetWindowStyleEx(SDL_Window *window)
static ITaskbarList3 *GetTaskbarList(SDL_Window* window)
{
const SDL_WindowData *data = window->internal;
if (!data->videodata->taskbar_button_created) {
SDL_SetError("Missing taskbar button");
return NULL;
}
SDL_assert(data->taskbar_button_created);
if (!data->videodata->taskbar_list) {
HRESULT ret = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_ALL, &IID_ITaskbarList3, (LPVOID *)&data->videodata->taskbar_list);
if (FAILED(ret)) {
@ -2248,18 +2245,23 @@ 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)
bool WIN_ApplyWindowProgress(SDL_Window* window)
{
#ifndef HAVE_SHOBJIDL_CORE_H
return false;
#else
SDL_WindowData *data = window->internal;
if (!data->taskbar_button_created) {
return true;
}
ITaskbarList3 *taskbar_list = GetTaskbarList(window);
if (!taskbar_list) {
return false;
};
}
TBPFLAG tbpFlags;
switch (state) {
switch (data->progress_state) {
case SDL_PROGRESS_STATE_NONE:
tbpFlags = TBPF_NOPROGRESS;
break;
@ -2279,31 +2281,59 @@ bool WIN_SetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window, SDL_
return SDL_SetError("Parameter 'state' is not supported");
}
HRESULT ret = taskbar_list->lpVtbl->SetProgressState(taskbar_list, window->internal->hwnd, tbpFlags);
HRESULT ret = taskbar_list->lpVtbl->SetProgressState(taskbar_list, data->hwnd, tbpFlags);
if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("ITaskbarList3::SetProgressState()", ret);
}
if (data->progress_state >= SDL_PROGRESS_STATE_NORMAL) {
ret = taskbar_list->lpVtbl->SetProgressValue(taskbar_list, data->hwnd, (ULONGLONG)(data->progress_value * 10000.f), 10000);
if (FAILED(ret)) {
return WIN_SetErrorFromHRESULT("ITaskbarList3::SetProgressValue()", ret);
}
}
return true;
#endif
}
bool WIN_SetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window, SDL_ProgressState state)
{
#ifndef HAVE_SHOBJIDL_CORE_H
return SDL_Unsupported();
#else
window->internal->progress_state = state;
return WIN_ApplyWindowProgress(window);
#endif
}
SDL_ProgressState WIN_GetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window)
{
#ifndef HAVE_SHOBJIDL_CORE_H
SDL_Unsupported();
return SDL_PROGRESS_STATE_INVALID;
#else
return window->internal->progress_state;
#endif // HAVE_SHOBJIDL_CORE_H
}
bool WIN_SetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window, float value)
{
#ifndef HAVE_SHOBJIDL_CORE_H
return false;
return SDL_Unsupported();
#else
ITaskbarList3 *taskbar_list = GetTaskbarList(window);
if (!taskbar_list) {
return false;
};
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);
window->internal->progress_value = value;
return WIN_ApplyWindowProgress(window);
#endif
}
return true;
float WIN_GetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window)
{
#ifndef HAVE_SHOBJIDL_CORE_H
SDL_Unsupported();
return -1.0f;
#else
return window->internal->progress_value;
#endif // HAVE_SHOBJIDL_CORE_H
}

View file

@ -93,6 +93,9 @@ struct SDL_WindowData
WCHAR *ICMFileName;
SDL_Window *keyboard_focus;
SDL_WindowEraseBackgroundMode hint_erase_background_mode;
bool taskbar_button_created;
SDL_ProgressState progress_state;
float progress_value;
struct SDL_VideoData *videodata;
#ifdef SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
@ -133,8 +136,11 @@ 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_ApplyWindowProgress(SDL_Window *window);
extern bool WIN_SetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window, SDL_ProgressState state);
extern SDL_ProgressState WIN_GetWindowProgressState(SDL_VideoDevice *_this, SDL_Window *window);
extern bool WIN_SetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window, float value);
extern float WIN_GetWindowProgressValue(SDL_VideoDevice *_this, SDL_Window *window);
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);