1
0
Эх сурвалжийг харах

WindowProgressState API getters and fixes (#12629)

Rémy Tassoux 3 долоо хоног өмнө
parent
commit
6cc00a31b6

+ 0 - 2
include/SDL3/SDL_test_common.h

@@ -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;

+ 28 - 5
include/SDL3/SDL_video.h

@@ -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;
 
 /**
@@ -2835,13 +2836,22 @@ 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);
 
+/**
+* Get the state of the progress bar for the given window’s taskbar icon.
+*
+* \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 window’s 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 whose progress value is to be modified.
  * \param value the progress value (0.0f - start, 1.0f - end). If the value is
  *              outside the valid range, it gets clamped.
@@ -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 window’s 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.
  *

+ 2 - 0
src/dynapi/SDL_dynapi.sym

@@ -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: *;
 };

+ 2 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -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

+ 2 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -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)

+ 11 - 8
src/test/SDL_test_common.c

@@ -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;

+ 2 - 0
src/video/SDL_sysvideo.h

@@ -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);
 

+ 24 - 0
src/video/SDL_video.c

@@ -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

+ 3 - 1
src/video/windows/SDL_windowsevents.c

@@ -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
 

+ 2 - 1
src/video/windows/SDL_windowsvideo.c

@@ -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;

+ 0 - 1
src/video/windows/SDL_windowsvideo.h

@@ -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
 };

+ 49 - 19
src/video/windows/SDL_windowswindow.c

@@ -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
 }
 

+ 6 - 0
src/video/windows/SDL_windowswindow.h

@@ -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);