Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows taskbar progress support #264

Merged
merged 9 commits into from
Feb 20, 2021
Merged

Windows taskbar progress support #264

merged 9 commits into from
Feb 20, 2021

Conversation

krzysdz
Copy link
Contributor

@krzysdz krzysdz commented Feb 14, 2021

This PR adds support for taskbar progress (#176) on Windows (7+). It should be also possible to implement it for some Linux systems using libxapp, but I did not find Rust bindings for it.

However, there are some problems to solve and things to improve:

  • Taskbar progress is not available before Windows 7 and I have no idea what will happen on earlier versions. Runtime version checks could be added (using VerifyVersionInfoA) if the GUI is supposed to run on older Windows versions.
  • If error and pause states will not be used (not supported in XApp anyway), setting the normal progress state is not necessary (setting value changes the state to normal from indeterminate and no progress).
  • IMPORTANT: The struct is never dropped and COM is not uninitialised properly. It looks like the clones of GuiData and Rc<TaskbarProgress> moved to closures used as signal handlers or spawned in the main context are not dropped.

Comments and suggestions are welcome.

It turns out winapi exposes IIDs through a `uuidof()` function of interfaces, so the copied one can be removed.
Now the `TaskbarProgress` functions fail silently.
The `TaskbarProgress` struct now will always be created (even in case of errors in initialisation), but it won't do anything.
A progress update was received after the stop event.
Also `as_ref()` was removed in many places (I don't even know why it was there).
It's already called by the `glib_stop_receiver` receiver.
@alexislefebvre
Copy link
Contributor

Taskbar progress is not available before Windows 7 and I have no idea what will happen on earlier versions

Windows XP and Vista are not supported anymore, I think it's acceptable to not support these outdated versions.

@krzysdz krzysdz changed the title Windows taskbar progress support [WIP] Windows taskbar progress support Feb 14, 2021
Because objects moved to closures used as fallbacks in GTK have [static lifetimes](https://gtk-rs.org/docs-src/tutorial/closures#closures), the `TaskbarProgress` will never be dropped.
To workaround this problem a `release` function is called when the main window is closed. This function behaves like `drop`, but sets the struct in a valid "empty" state, so that calling `release`/`drop` again won't cause problems.
@qarmin qarmin added the enhancement New feature or request label Feb 16, 2021
Because only NOPROGRESS and INDETERMINATE states are used, there is no need to set the NORMAL state when changing the progress value.

Now `set_progress_value` will also change the `TaskbarProgress::current_state` if such situation occurs.

> Unless [SetProgressState](https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate)
> has set a blocking state (TBPF_ERROR or TBPF_PAUSED) for the window, a call to **SetProgressValue** assumes the TBPF_NORMAL
> state even if it is not explicitly set. A call to **SetProgressValue** overrides and clears the TBPF_INDETERMINATE state.

See the [SetProgressValue documentation](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressvalue#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group)
@krzysdz
Copy link
Contributor Author

krzysdz commented Feb 17, 2021

I have also some tests in krzysdz#1, which I can add if you want, but I think this PR is now ready for review.

@krzysdz krzysdz marked this pull request as ready for review February 17, 2021 19:10
@krzysdz krzysdz changed the title [WIP] Windows taskbar progress support Windows taskbar progress support Feb 17, 2021
@qarmin qarmin merged commit 4c205ce into qarmin:master Feb 20, 2021
@qarmin
Copy link
Owner

qarmin commented Feb 20, 2021

Thanks!
Changes looks good, progress bar works, I don't see any crashes etc.

LJason77 pushed a commit to LJason77/czkawka that referenced this pull request Feb 20, 2021
* Initial Windows taskbar progress support

* Changes to COM (un)init

It turns out winapi exposes IIDs through a `uuidof()` function of interfaces, so the copied one can be removed.

* Don't return error codes

Now the `TaskbarProgress` functions fail silently.
The `TaskbarProgress` struct now will always be created (even in case of errors in initialisation), but it won't do anything.

* Fix builds for other systems

* Formatted code

* Fix progress shown after the operation finished

A progress update was received after the stop event.
Also `as_ref()` was removed in many places (I don't even know why it was there).

* Remove redundant call to hide

It's already called by the `glib_stop_receiver` receiver.

* Release the ITaskbarList3 and call CoUninitialize at exit

Because objects moved to closures used as fallbacks in GTK have [static lifetimes](https://gtk-rs.org/docs-src/tutorial/closures#closures), the `TaskbarProgress` will never be dropped.
To workaround this problem a `release` function is called when the main window is closed. This function behaves like `drop`, but sets the struct in a valid "empty" state, so that calling `release`/`drop` again won't cause problems.

* Don't set the NORMAL state manually

Because only NOPROGRESS and INDETERMINATE states are used, there is no need to set the NORMAL state when changing the progress value.

Now `set_progress_value` will also change the `TaskbarProgress::current_state` if such situation occurs.

> Unless [SetProgressState](https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate)
> has set a blocking state (TBPF_ERROR or TBPF_PAUSED) for the window, a call to **SetProgressValue** assumes the TBPF_NORMAL
> state even if it is not explicitly set. A call to **SetProgressValue** overrides and clears the TBPF_INDETERMINATE state.

See the [SetProgressValue documentation](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressvalue#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group)
@krzysdz krzysdz deleted the master branch February 20, 2021 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants