summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
authorbruvzg <7645683+bruvzg@users.noreply.github.com>2024-03-16 23:14:30 +0200
committerbruvzg <7645683+bruvzg@users.noreply.github.com>2024-03-20 11:56:07 +0200
commit0587a1d217688437718eb3978915558920a637fb (patch)
tree6ce838af1d0ea4d3d8dadbef6fbbb734c933836b /platform
parentfe01776f05b1787b28b4a270d53037a3c25f4ca2 (diff)
downloadredot-engine-0587a1d217688437718eb3978915558920a637fb.tar.gz
[StatusIndicator] Switch API to use Texture2D instead of Image, improve handling on macOS, add method to set native popup menu directly.
Diffstat (limited to 'platform')
-rw-r--r--platform/macos/display_server_macos.h7
-rw-r--r--platform/macos/display_server_macos.mm47
-rw-r--r--platform/macos/godot_status_item.h7
-rw-r--r--platform/macos/godot_status_item.mm61
-rw-r--r--platform/macos/native_menu_macos.h2
-rw-r--r--platform/macos/native_menu_macos.mm7
-rw-r--r--platform/windows/display_server_windows.cpp40
-rw-r--r--platform/windows/display_server_windows.h6
8 files changed, 101 insertions, 76 deletions
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 09073a8030..1b0787c2d9 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -192,7 +192,7 @@ private:
HashMap<WindowID, WindowData> windows;
struct IndicatorData {
- id view;
+ id delegate;
id item;
};
@@ -430,9 +430,10 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
- virtual IndicatorID create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback) override;
- virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon) override;
+ virtual IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) override;
+ virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) override;
virtual void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) override;
+ virtual void status_indicator_set_menu(IndicatorID p_id, const RID &p_menu_rid) override;
virtual void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override;
virtual void delete_status_indicator(IndicatorID p_id) override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index c52ed00b3d..23b5a03baa 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3131,10 +3131,11 @@ void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) {
}
}
-DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback) {
+DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) {
NSImage *nsimg = nullptr;
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
- Ref<Image> img = p_icon->duplicate();
+ Ref<Image> img = p_icon->get_image();
+ img = img->duplicate();
img->convert(Image::FORMAT_RGBA8);
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
@@ -3172,13 +3173,18 @@ DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref
IndicatorData idat;
- idat.item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
- idat.view = [[GodotStatusItemView alloc] init];
+ NSStatusItem *item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
+ idat.item = item;
+ idat.delegate = [[GodotStatusItemDelegate alloc] init];
+ [idat.delegate setCallback:p_callback];
- [idat.view setToolTip:[NSString stringWithUTF8String:p_tooltip.utf8().get_data()]];
- [idat.view setImage:nsimg];
- [idat.view setCallback:p_callback];
- [idat.item setView:idat.view];
+ item.button.image = nsimg;
+ item.button.imagePosition = NSImageOnly;
+ item.button.imageScaling = NSImageScaleProportionallyUpOrDown;
+ item.button.target = idat.delegate;
+ item.button.action = @selector(click:);
+ [item.button sendActionOn:(NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskOtherMouseDown)];
+ item.button.toolTip = [NSString stringWithUTF8String:p_tooltip.utf8().get_data()];
IndicatorID iid = indicator_id_counter++;
indicators[iid] = idat;
@@ -3186,12 +3192,13 @@ DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref
return iid;
}
-void DisplayServerMacOS::status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon) {
+void DisplayServerMacOS::status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) {
ERR_FAIL_COND(!indicators.has(p_id));
NSImage *nsimg = nullptr;
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
- Ref<Image> img = p_icon->duplicate();
+ Ref<Image> img = p_icon->get_image();
+ img = img->duplicate();
img->convert(Image::FORMAT_RGBA8);
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
@@ -3227,19 +3234,33 @@ void DisplayServerMacOS::status_indicator_set_icon(IndicatorID p_id, const Ref<I
}
}
- [indicators[p_id].view setImage:nsimg];
+ NSStatusItem *item = indicators[p_id].item;
+ item.button.image = nsimg;
}
void DisplayServerMacOS::status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) {
ERR_FAIL_COND(!indicators.has(p_id));
- [indicators[p_id].view setToolTip:[NSString stringWithUTF8String:p_tooltip.utf8().get_data()]];
+ NSStatusItem *item = indicators[p_id].item;
+ item.button.toolTip = [NSString stringWithUTF8String:p_tooltip.utf8().get_data()];
+}
+
+void DisplayServerMacOS::status_indicator_set_menu(IndicatorID p_id, const RID &p_menu_rid) {
+ ERR_FAIL_COND(!indicators.has(p_id));
+
+ NSStatusItem *item = indicators[p_id].item;
+ if (p_menu_rid.is_valid() && native_menu->has_menu(p_menu_rid)) {
+ NSMenu *menu = native_menu->get_native_menu_handle(p_menu_rid);
+ item.menu = menu;
+ } else {
+ item.menu = nullptr;
+ }
}
void DisplayServerMacOS::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
ERR_FAIL_COND(!indicators.has(p_id));
- [indicators[p_id].view setCallback:p_callback];
+ [indicators[p_id].delegate setCallback:p_callback];
}
void DisplayServerMacOS::delete_status_indicator(IndicatorID p_id) {
diff --git a/platform/macos/godot_status_item.h b/platform/macos/godot_status_item.h
index 1827baa9bd..5bc790956e 100644
--- a/platform/macos/godot_status_item.h
+++ b/platform/macos/godot_status_item.h
@@ -37,13 +37,12 @@
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
-@interface GodotStatusItemView : NSView {
- NSImage *image;
+@interface GodotStatusItemDelegate : NSObject {
Callable cb;
}
-- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index;
-- (void)setImage:(NSImage *)image;
+- (IBAction)click:(id)sender;
+
- (void)setCallback:(const Callable &)callback;
@end
diff --git a/platform/macos/godot_status_item.mm b/platform/macos/godot_status_item.mm
index 71ed0a0f71..0990a16b2b 100644
--- a/platform/macos/godot_status_item.mm
+++ b/platform/macos/godot_status_item.mm
@@ -32,30 +32,32 @@
#include "display_server_macos.h"
-@implementation GodotStatusItemView
+@implementation GodotStatusItemDelegate
- (id)init {
self = [super init];
- image = nullptr;
return self;
}
-- (void)setImage:(NSImage *)newImage {
- image = newImage;
- [self setNeedsDisplayInRect:self.frame];
-}
-
-- (void)setCallback:(const Callable &)callback {
- cb = callback;
-}
-
-- (void)drawRect:(NSRect)rect {
- if (image) {
- [image drawInRect:rect];
+- (IBAction)click:(id)sender {
+ NSEvent *current_event = [NSApp currentEvent];
+ MouseButton index = MouseButton::LEFT;
+ if (current_event) {
+ if (current_event.type == NSEventTypeLeftMouseDown) {
+ index = MouseButton::LEFT;
+ } else if (current_event.type == NSEventTypeRightMouseDown) {
+ index = MouseButton::RIGHT;
+ } else if (current_event.type == NSEventTypeOtherMouseDown) {
+ if ((int)[current_event buttonNumber] == 2) {
+ index = MouseButton::MIDDLE;
+ } else if ((int)[current_event buttonNumber] == 3) {
+ index = MouseButton::MB_XBUTTON1;
+ } else if ((int)[current_event buttonNumber] == 4) {
+ index = MouseButton::MB_XBUTTON2;
+ }
+ }
}
-}
-- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds) {
return;
@@ -71,31 +73,8 @@
}
}
-- (void)mouseDown:(NSEvent *)event {
- [super mouseDown:event];
- if (([event modifierFlags] & NSEventModifierFlagControl)) {
- [self processMouseEvent:event index:MouseButton::RIGHT];
- } else {
- [self processMouseEvent:event index:MouseButton::LEFT];
- }
-}
-
-- (void)rightMouseDown:(NSEvent *)event {
- [super rightMouseDown:event];
-
- [self processMouseEvent:event index:MouseButton::RIGHT];
-}
-
-- (void)otherMouseDown:(NSEvent *)event {
- [super otherMouseDown:event];
-
- if ((int)[event buttonNumber] == 2) {
- [self processMouseEvent:event index:MouseButton::MIDDLE];
- } else if ((int)[event buttonNumber] == 3) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON1];
- } else if ((int)[event buttonNumber] == 4) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON2];
- }
+- (void)setCallback:(const Callable &)callback {
+ cb = callback;
}
@end
diff --git a/platform/macos/native_menu_macos.h b/platform/macos/native_menu_macos.h
index c00a510fd5..894f6912b5 100644
--- a/platform/macos/native_menu_macos.h
+++ b/platform/macos/native_menu_macos.h
@@ -85,6 +85,8 @@ public:
virtual bool has_menu(const RID &p_rid) const override;
virtual void free_menu(const RID &p_rid) override;
+ NSMenu *get_native_menu_handle(const RID &p_rid);
+
virtual Size2 get_size(const RID &p_rid) const override;
virtual void popup(const RID &p_rid, const Vector2i &p_position) override;
diff --git a/platform/macos/native_menu_macos.mm b/platform/macos/native_menu_macos.mm
index 250b64dc04..27ad5209c4 100644
--- a/platform/macos/native_menu_macos.mm
+++ b/platform/macos/native_menu_macos.mm
@@ -243,6 +243,13 @@ void NativeMenuMacOS::free_menu(const RID &p_rid) {
}
}
+NSMenu *NativeMenuMacOS::get_native_menu_handle(const RID &p_rid) {
+ MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, nullptr);
+
+ return md->menu;
+}
+
Size2 NativeMenuMacOS::get_size(const RID &p_rid) const {
const MenuData *md = menus.get_or_null(p_rid);
ERR_FAIL_NULL_V(md, Size2());
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 074d40bf4b..cde7992b29 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -3152,14 +3152,12 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
}
}
-DisplayServer::IndicatorID DisplayServerWindows::create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback) {
+DisplayServer::IndicatorID DisplayServerWindows::create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) {
HICON hicon = nullptr;
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
- Ref<Image> img = p_icon;
- if (img != icon) {
- img = img->duplicate();
- img->convert(Image::FORMAT_RGBA8);
- }
+ Ref<Image> img = p_icon->get_image();
+ img = img->duplicate();
+ img->convert(Image::FORMAT_RGBA8);
int w = img->get_width();
int h = img->get_height();
@@ -3222,16 +3220,14 @@ DisplayServer::IndicatorID DisplayServerWindows::create_status_indicator(const R
return iid;
}
-void DisplayServerWindows::status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon) {
+void DisplayServerWindows::status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) {
ERR_FAIL_COND(!indicators.has(p_id));
HICON hicon = nullptr;
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
- Ref<Image> img = p_icon;
- if (img != icon) {
- img = img->duplicate();
- img->convert(Image::FORMAT_RGBA8);
- }
+ Ref<Image> img = p_icon->get_image();
+ img = img->duplicate();
+ img->convert(Image::FORMAT_RGBA8);
int w = img->get_width();
int h = img->get_height();
@@ -3298,6 +3294,12 @@ void DisplayServerWindows::status_indicator_set_tooltip(IndicatorID p_id, const
Shell_NotifyIconW(NIM_MODIFY, &ndat);
}
+void DisplayServerWindows::status_indicator_set_menu(IndicatorID p_id, const RID &p_menu_rid) {
+ ERR_FAIL_COND(!indicators.has(p_id));
+
+ indicators[p_id].menu_rid = p_menu_rid;
+}
+
void DisplayServerWindows::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
ERR_FAIL_COND(!indicators.has(p_id));
@@ -3850,7 +3852,19 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mb = MouseButton::MB_XBUTTON1;
}
if (indicators.has(iid)) {
- if (indicators[iid].callback.is_valid()) {
+ if (lParam == WM_RBUTTONDOWN && indicators[iid].menu_rid.is_valid() && native_menu->has_menu(indicators[iid].menu_rid)) {
+ NOTIFYICONIDENTIFIER nid;
+ ZeroMemory(&nid, sizeof(NOTIFYICONIDENTIFIER));
+ nid.cbSize = sizeof(NOTIFYICONIDENTIFIER);
+ nid.hWnd = windows[MAIN_WINDOW_ID].hWnd;
+ nid.uID = iid;
+ nid.guidItem = GUID_NULL;
+
+ RECT rect;
+ if (Shell_NotifyIconGetRect(&nid, &rect) == S_OK) {
+ native_menu->popup(indicators[iid].menu_rid, Vector2i((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2));
+ }
+ } else if (indicators[iid].callback.is_valid()) {
Variant v_button = mb;
Variant v_pos = mouse_get_position();
Variant *v_args[2] = { &v_button, &v_pos };
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 1191f22968..1b2a9a2090 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -465,6 +465,7 @@ class DisplayServerWindows : public DisplayServer {
WNDPROC user_proc = nullptr;
struct IndicatorData {
+ RID menu_rid;
Callable callback;
};
@@ -686,9 +687,10 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
- virtual IndicatorID create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback) override;
- virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon) override;
+ virtual IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) override;
+ virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) override;
virtual void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) override;
+ virtual void status_indicator_set_menu(IndicatorID p_id, const RID &p_rid) override;
virtual void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override;
virtual void delete_status_indicator(IndicatorID p_id) override;