-
-
Notifications
You must be signed in to change notification settings - Fork 22.5k
Add taskbar progress and state support for Windows & macOS #106560
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
base: master
Are you sure you want to change the base?
Add taskbar progress and state support for Windows & macOS #106560
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, this is a feature I was personally missing in Godot!
While I realize the PR is still in draft, here's a few things I noticed.
Also you probably saw CI is failing because other display servers still need the methods implemented (even if they do nothing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
macOS does not have a default progress bar for the dock, but arbitrary control can be added to the icon, so it is possible to replicate the same behavior. Not sure about other platforms, probably not supported.
Co-authored-by: bruvzg <7645683+bruvzg@users.noreply.github.com>
Co-authored-by: bruvzg <7645683+bruvzg@users.noreply.github.com>
I have no mac device and I don't have any experience on macOS app development |
4f9dd3f
to
618f7cb
Compare
A taskbar is not supported on all platforms we support, so instead we - should change the terminology to For example, |
The progress bar on taskbar is what I want to implement Besides, I don't know is there another visual of progress bar in another OS |
I do not think it should be mixed with notifications (which, unlike this, can be implemented on all platforms), it's a different feature. |
For the reference, it is implementable on macOS, and Linux (not standard, but seems to be supported by multiple DEs - https://wiki.ubuntu.com/Unity/LauncherAPI#Low_level_DBus_API:_com.canonical.Unity.LauncherEntry). |
A quick POC for macOS implementation (style of process bar is questionable, but in case of macOS anything can be drawn): Patchdiff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 8d76b4b8ad..89790be158 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -66,6 +66,7 @@
@class GodotWindowDelegate;
@class GodotButtonView;
@class GodotEmbeddedView;
+@class GodotProgressView;
@class CALayerHost;
#undef BitMap
@@ -150,6 +151,8 @@ public:
List<WindowID> popup_list;
uint64_t time_since_popup = 0;
+ GodotProgressView *dock_progress = nullptr;
+
private:
#if defined(GLES3_ENABLED)
GLManagerLegacy_MacOS *gl_manager_legacy = nullptr;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index d1f9d95298..be2ac7b130 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -2902,12 +2902,98 @@ void DisplayServerMacOS::window_request_attention(WindowID p_window) {
[NSApp requestUserAttention:NSCriticalRequest];
}
+@interface GodotProgressView : NSView {
+ DisplayServer::ProgressState pr_state;
+ float pr_value;
+ float pr_offset;
+}
+- (void)setValue:(float)value;
+- (void)setState:(DisplayServer::ProgressState)state;
+@end
+
+@implementation GodotProgressView
+
+- (id)init {
+ self = [super init];
+ pr_state = DisplayServer::PROGRESS_STATE_NOPROGRESS;
+ pr_value = 0.f;
+ pr_offset = 0.f;
+ return self;
+}
+
+- (void)setValue:(float)value {
+ pr_value = value;
+}
+
+- (void)setState:(DisplayServer::ProgressState)state {
+ pr_state = state;
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+ // Icon draw.
+ [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
+ [[NSApp applicationIconImage] drawInRect:self.bounds];
+
+ if (pr_state == DisplayServer::PROGRESS_STATE_NOPROGRESS) {
+ return;
+ }
+
+ // Border draw.
+ NSRect rect = NSMakeRect(1.f, 1.f, self.bounds.size.width - 2.f, 16.f);
+ NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:8.f yRadius:8.f];
+ [bezier_path setLineWidth:2.0];
+ [[NSColor grayColor] set];
+ [bezier_path stroke];
+
+ // Fill clip path.
+ rect = NSMakeRect(2.f, 2.f, self.bounds.size.width - 4.f, 14.f);
+ bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:7.f yRadius:7.f];
+ [bezier_path setLineWidth:1.0];
+ [bezier_path addClip];
+
+ // Fill draw.
+ if (pr_state == DisplayServer::PROGRESS_STATE_INDETERMINATE) {
+ rect.size.width /= 5.0;
+ pr_offset += rect.size.width / 10.0;
+ if (pr_offset > self.bounds.size.width - rect.size.width) {
+ pr_offset = 0.f;
+ }
+ rect.origin.x += pr_offset;
+ } else {
+ rect.size.width = floor(rect.size.width * pr_value);
+ }
+ if (pr_state == DisplayServer::PROGRESS_STATE_ERROR) {
+ [[NSColor colorWithSRGBRed:1.0 green:0.2 blue:0.2 alpha:1.0] set];
+ } else if (pr_state == DisplayServer::PROGRESS_STATE_PAUSED) {
+ [[NSColor colorWithSRGBRed:1.0 green:1.0 blue:0.2 alpha:1.0] set];
+ } else {
+ [[NSColor colorWithSRGBRed:0.2 green:0.6 blue:1.0 alpha:1.0] set];
+ }
+ NSRectFill(rect);
+}
+
+@end
+
void DisplayServerMacOS::window_set_taskbar_progress_value(float p_value, WindowID p_window) {
- // Not supported.
+ ERR_FAIL_COND(p_window != MAIN_WINDOW_ID);
+
+ if (!dock_progress) {
+ dock_progress = [[GodotProgressView alloc] init];
+ [NSApp.dockTile setContentView:dock_progress];
+ }
+
+ [dock_progress setValue:p_value];
}
void DisplayServerMacOS::window_set_taskbar_progress_state(ProgressState p_state, WindowID p_window) {
- // Not supported.
+ ERR_FAIL_COND(p_window != MAIN_WINDOW_ID);
+
+ if (!dock_progress) {
+ dock_progress = [[GodotProgressView alloc] init];
+ [NSApp.dockTile setContentView:dock_progress];
+ }
+
+ [dock_progress setState:p_state];
}
void DisplayServerMacOS::window_move_to_foreground(WindowID p_window) {
@@ -3511,6 +3597,11 @@ void DisplayServerMacOS::_process_events(bool p_pump) {
}
}
+ if (dock_progress) {
+ dock_progress.needsDisplay = true;
+ [NSApp.dockTile display];
+ }
+
_THREAD_SAFE_UNLOCK_
}
Screen.Recording.2025-05-20.at.11.43.41.mov |
Thank you very much!
I am looking into this for Linux support |
I do not think you can, there's no standard |
Co-authored-by: bruvzg <7645683+bruvzg@users.noreply.github.com>
Co-Authored-By: bruvzg <7645683+bruvzg@users.noreply.github.com>
b4b1693
to
10fe2b9
Compare
All done |
Use ITaskbarList3 for Windows
Use NSView for macOS (by @bruvzg )
Fixes godotengine/godot-proposals#2414