You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Merge pull request #89588 from bruvzg/status_ind_menu_direct
[StatusIndicator] Switch API to use Texture2D instead of Image, improve handling on macOS, add method to set native popup menu directly.
This commit is contained in:
@@ -58,7 +58,7 @@
|
|||||||
</method>
|
</method>
|
||||||
<method name="create_status_indicator">
|
<method name="create_status_indicator">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
<param index="0" name="icon" type="Image" />
|
<param index="0" name="icon" type="Texture2D" />
|
||||||
<param index="1" name="tooltip" type="String" />
|
<param index="1" name="tooltip" type="String" />
|
||||||
<param index="2" name="callback" type="Callable" />
|
<param index="2" name="callback" type="Callable" />
|
||||||
<description>
|
<description>
|
||||||
@@ -1178,11 +1178,22 @@
|
|||||||
<method name="status_indicator_set_icon">
|
<method name="status_indicator_set_icon">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="id" type="int" />
|
<param index="0" name="id" type="int" />
|
||||||
<param index="1" name="icon" type="Image" />
|
<param index="1" name="icon" type="Texture2D" />
|
||||||
<description>
|
<description>
|
||||||
Sets the application status indicator icon.
|
Sets the application status indicator icon.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="status_indicator_set_menu">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="id" type="int" />
|
||||||
|
<param index="1" name="menu_rid" type="RID" />
|
||||||
|
<description>
|
||||||
|
Sets the application status indicator native popup menu.
|
||||||
|
[b]Note:[/b] On macOS, the menu is activated by any mouse button. Its activation callback is [i]not[/i] triggered.
|
||||||
|
[b]Note:[/b] On Windows, the menu is activated by the right mouse button, selecting the status icon and pressing [kbd]Shift + F10[/kbd], or the applications key. The menu's activation callback for the other mouse buttons is still triggered.
|
||||||
|
[b]Note:[/b] Native popup is only supported if [NativeMenu] supports the [constant NativeMenu.FEATURE_POPUP_MENU] feature.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="status_indicator_set_tooltip">
|
<method name="status_indicator_set_tooltip">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="id" type="int" />
|
<param index="0" name="id" type="int" />
|
||||||
|
|||||||
@@ -9,9 +9,13 @@
|
|||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
<members>
|
<members>
|
||||||
<member name="icon" type="Image" setter="set_icon" getter="get_icon">
|
<member name="icon" type="Texture2D" setter="set_icon" getter="get_icon">
|
||||||
Status indicator icon.
|
Status indicator icon.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="menu" type="NodePath" setter="set_menu" getter="get_menu" default="NodePath("")">
|
||||||
|
Status indicator native popup menu. If this is set, the [signal pressed] signal is not emitted.
|
||||||
|
[b]Note:[/b] Native popup is only supported if [NativeMenu] supports [constant NativeMenu.FEATURE_POPUP_MENU] feature.
|
||||||
|
</member>
|
||||||
<member name="tooltip" type="String" setter="set_tooltip" getter="get_tooltip" default="""">
|
<member name="tooltip" type="String" setter="set_tooltip" getter="get_tooltip" default="""">
|
||||||
Status indicator tooltip.
|
Status indicator tooltip.
|
||||||
</member>
|
</member>
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ private:
|
|||||||
HashMap<WindowID, WindowData> windows;
|
HashMap<WindowID, WindowData> windows;
|
||||||
|
|
||||||
struct IndicatorData {
|
struct IndicatorData {
|
||||||
id view;
|
id delegate;
|
||||||
id item;
|
id item;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -431,9 +431,10 @@ public:
|
|||||||
virtual void set_native_icon(const String &p_filename) override;
|
virtual void set_native_icon(const String &p_filename) override;
|
||||||
virtual void set_icon(const Ref<Image> &p_icon) 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 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<Image> &p_icon) 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_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 status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override;
|
||||||
virtual void delete_status_indicator(IndicatorID p_id) override;
|
virtual void delete_status_indicator(IndicatorID p_id) override;
|
||||||
|
|
||||||
|
|||||||
@@ -3151,10 +3151,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;
|
NSImage *nsimg = nullptr;
|
||||||
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
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);
|
img->convert(Image::FORMAT_RGBA8);
|
||||||
|
|
||||||
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
|
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
|
||||||
@@ -3192,13 +3193,18 @@ DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref
|
|||||||
|
|
||||||
IndicatorData idat;
|
IndicatorData idat;
|
||||||
|
|
||||||
idat.item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
NSStatusItem *item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||||
idat.view = [[GodotStatusItemView alloc] init];
|
idat.item = item;
|
||||||
|
idat.delegate = [[GodotStatusItemDelegate alloc] init];
|
||||||
|
[idat.delegate setCallback:p_callback];
|
||||||
|
|
||||||
[idat.view setToolTip:[NSString stringWithUTF8String:p_tooltip.utf8().get_data()]];
|
item.button.image = nsimg;
|
||||||
[idat.view setImage:nsimg];
|
item.button.imagePosition = NSImageOnly;
|
||||||
[idat.view setCallback:p_callback];
|
item.button.imageScaling = NSImageScaleProportionallyUpOrDown;
|
||||||
[idat.item setView:idat.view];
|
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++;
|
IndicatorID iid = indicator_id_counter++;
|
||||||
indicators[iid] = idat;
|
indicators[iid] = idat;
|
||||||
@@ -3206,12 +3212,13 @@ DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref
|
|||||||
return iid;
|
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));
|
ERR_FAIL_COND(!indicators.has(p_id));
|
||||||
|
|
||||||
NSImage *nsimg = nullptr;
|
NSImage *nsimg = nullptr;
|
||||||
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
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);
|
img->convert(Image::FORMAT_RGBA8);
|
||||||
|
|
||||||
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
|
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
|
||||||
@@ -3247,19 +3254,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) {
|
void DisplayServerMacOS::status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) {
|
||||||
ERR_FAIL_COND(!indicators.has(p_id));
|
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) {
|
void DisplayServerMacOS::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
|
||||||
ERR_FAIL_COND(!indicators.has(p_id));
|
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) {
|
void DisplayServerMacOS::delete_status_indicator(IndicatorID p_id) {
|
||||||
|
|||||||
@@ -37,13 +37,12 @@
|
|||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface GodotStatusItemView : NSView {
|
@interface GodotStatusItemDelegate : NSObject {
|
||||||
NSImage *image;
|
|
||||||
Callable cb;
|
Callable cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index;
|
- (IBAction)click:(id)sender;
|
||||||
- (void)setImage:(NSImage *)image;
|
|
||||||
- (void)setCallback:(const Callable &)callback;
|
- (void)setCallback:(const Callable &)callback;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -32,30 +32,32 @@
|
|||||||
|
|
||||||
#include "display_server_macos.h"
|
#include "display_server_macos.h"
|
||||||
|
|
||||||
@implementation GodotStatusItemView
|
@implementation GodotStatusItemDelegate
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
image = nullptr;
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setImage:(NSImage *)newImage {
|
- (IBAction)click:(id)sender {
|
||||||
image = newImage;
|
NSEvent *current_event = [NSApp currentEvent];
|
||||||
[self setNeedsDisplayInRect:self.frame];
|
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)setCallback:(const Callable &)callback {
|
|
||||||
cb = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)rect {
|
|
||||||
if (image) {
|
|
||||||
[image drawInRect:rect];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index {
|
|
||||||
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
return;
|
return;
|
||||||
@@ -71,31 +73,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent *)event {
|
- (void)setCallback:(const Callable &)callback {
|
||||||
[super mouseDown:event];
|
cb = callback;
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ public:
|
|||||||
virtual bool has_menu(const RID &p_rid) const override;
|
virtual bool has_menu(const RID &p_rid) const override;
|
||||||
virtual void free_menu(const RID &p_rid) 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 Size2 get_size(const RID &p_rid) const override;
|
||||||
virtual void popup(const RID &p_rid, const Vector2i &p_position) override;
|
virtual void popup(const RID &p_rid, const Vector2i &p_position) override;
|
||||||
|
|
||||||
|
|||||||
@@ -248,6 +248,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 {
|
Size2 NativeMenuMacOS::get_size(const RID &p_rid) const {
|
||||||
const MenuData *md = menus.get_or_null(p_rid);
|
const MenuData *md = menus.get_or_null(p_rid);
|
||||||
ERR_FAIL_NULL_V(md, Size2());
|
ERR_FAIL_NULL_V(md, Size2());
|
||||||
|
|||||||
@@ -3171,14 +3171,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;
|
HICON hicon = nullptr;
|
||||||
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
||||||
Ref<Image> img = p_icon;
|
Ref<Image> img = p_icon->get_image();
|
||||||
if (img != icon) {
|
|
||||||
img = img->duplicate();
|
img = img->duplicate();
|
||||||
img->convert(Image::FORMAT_RGBA8);
|
img->convert(Image::FORMAT_RGBA8);
|
||||||
}
|
|
||||||
|
|
||||||
int w = img->get_width();
|
int w = img->get_width();
|
||||||
int h = img->get_height();
|
int h = img->get_height();
|
||||||
@@ -3241,16 +3239,14 @@ DisplayServer::IndicatorID DisplayServerWindows::create_status_indicator(const R
|
|||||||
return iid;
|
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));
|
ERR_FAIL_COND(!indicators.has(p_id));
|
||||||
|
|
||||||
HICON hicon = nullptr;
|
HICON hicon = nullptr;
|
||||||
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
|
||||||
Ref<Image> img = p_icon;
|
Ref<Image> img = p_icon->get_image();
|
||||||
if (img != icon) {
|
|
||||||
img = img->duplicate();
|
img = img->duplicate();
|
||||||
img->convert(Image::FORMAT_RGBA8);
|
img->convert(Image::FORMAT_RGBA8);
|
||||||
}
|
|
||||||
|
|
||||||
int w = img->get_width();
|
int w = img->get_width();
|
||||||
int h = img->get_height();
|
int h = img->get_height();
|
||||||
@@ -3317,6 +3313,12 @@ void DisplayServerWindows::status_indicator_set_tooltip(IndicatorID p_id, const
|
|||||||
Shell_NotifyIconW(NIM_MODIFY, &ndat);
|
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) {
|
void DisplayServerWindows::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
|
||||||
ERR_FAIL_COND(!indicators.has(p_id));
|
ERR_FAIL_COND(!indicators.has(p_id));
|
||||||
|
|
||||||
@@ -3838,7 +3840,19 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||||||
mb = MouseButton::MB_XBUTTON1;
|
mb = MouseButton::MB_XBUTTON1;
|
||||||
}
|
}
|
||||||
if (indicators.has(iid)) {
|
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_button = mb;
|
||||||
Variant v_pos = mouse_get_position();
|
Variant v_pos = mouse_get_position();
|
||||||
Variant *v_args[2] = { &v_button, &v_pos };
|
Variant *v_args[2] = { &v_button, &v_pos };
|
||||||
|
|||||||
@@ -464,6 +464,7 @@ class DisplayServerWindows : public DisplayServer {
|
|||||||
WNDPROC user_proc = nullptr;
|
WNDPROC user_proc = nullptr;
|
||||||
|
|
||||||
struct IndicatorData {
|
struct IndicatorData {
|
||||||
|
RID menu_rid;
|
||||||
Callable callback;
|
Callable callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -684,9 +685,10 @@ public:
|
|||||||
virtual void set_native_icon(const String &p_filename) override;
|
virtual void set_native_icon(const String &p_filename) override;
|
||||||
virtual void set_icon(const Ref<Image> &p_icon) 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 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<Image> &p_icon) 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_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 status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override;
|
||||||
virtual void delete_status_indicator(IndicatorID p_id) override;
|
virtual void delete_status_indicator(IndicatorID p_id) override;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include "status_indicator.h"
|
#include "status_indicator.h"
|
||||||
|
|
||||||
|
#include "scene/gui/popup_menu.h"
|
||||||
|
|
||||||
void StatusIndicator::_notification(int p_what) {
|
void StatusIndicator::_notification(int p_what) {
|
||||||
ERR_MAIN_THREAD_GUARD;
|
ERR_MAIN_THREAD_GUARD;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
@@ -43,12 +45,22 @@ void StatusIndicator::_notification(int p_what) {
|
|||||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
||||||
if (visible && iid == DisplayServer::INVALID_INDICATOR_ID) {
|
if (visible && iid == DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
iid = DisplayServer::get_singleton()->create_status_indicator(icon, tooltip, callable_mp(this, &StatusIndicator::_callback));
|
iid = DisplayServer::get_singleton()->create_status_indicator(icon, tooltip, callable_mp(this, &StatusIndicator::_callback));
|
||||||
|
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
RID menu_rid = pm->bind_global_menu();
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, menu_rid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
||||||
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
|
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
pm->unbind_global_menu();
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, RID());
|
||||||
|
}
|
||||||
DisplayServer::get_singleton()->delete_status_indicator(iid);
|
DisplayServer::get_singleton()->delete_status_indicator(iid);
|
||||||
iid = DisplayServer::INVALID_INDICATOR_ID;
|
iid = DisplayServer::INVALID_INDICATOR_ID;
|
||||||
}
|
}
|
||||||
@@ -66,11 +78,14 @@ void StatusIndicator::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("get_icon"), &StatusIndicator::get_icon);
|
ClassDB::bind_method(D_METHOD("get_icon"), &StatusIndicator::get_icon);
|
||||||
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &StatusIndicator::set_visible);
|
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &StatusIndicator::set_visible);
|
||||||
ClassDB::bind_method(D_METHOD("is_visible"), &StatusIndicator::is_visible);
|
ClassDB::bind_method(D_METHOD("is_visible"), &StatusIndicator::is_visible);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_menu", "menu"), &StatusIndicator::set_menu);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_menu"), &StatusIndicator::get_menu);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::INT, "mouse_button"), PropertyInfo(Variant::VECTOR2I, "mouse_position")));
|
ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::INT, "mouse_button"), PropertyInfo(Variant::VECTOR2I, "mouse_position")));
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "get_tooltip");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "get_tooltip");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_icon", "get_icon");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_icon", "get_icon");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "menu", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PopupMenu"), "set_menu", "get_menu");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +93,7 @@ void StatusIndicator::_callback(MouseButton p_index, const Point2i &p_pos) {
|
|||||||
emit_signal(SNAME("pressed"), p_index, p_pos);
|
emit_signal(SNAME("pressed"), p_index, p_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusIndicator::set_icon(const Ref<Image> &p_icon) {
|
void StatusIndicator::set_icon(const Ref<Texture2D> &p_icon) {
|
||||||
ERR_MAIN_THREAD_GUARD;
|
ERR_MAIN_THREAD_GUARD;
|
||||||
icon = p_icon;
|
icon = p_icon;
|
||||||
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
@@ -86,7 +101,7 @@ void StatusIndicator::set_icon(const Ref<Image> &p_icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image> StatusIndicator::get_icon() const {
|
Ref<Texture2D> StatusIndicator::get_icon() const {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +117,30 @@ String StatusIndicator::get_tooltip() const {
|
|||||||
return tooltip;
|
return tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatusIndicator::set_menu(const NodePath &p_menu) {
|
||||||
|
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
pm->unbind_global_menu();
|
||||||
|
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, RID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = p_menu;
|
||||||
|
|
||||||
|
pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
if (iid != DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
|
RID menu_rid = pm->bind_global_menu();
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, menu_rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath StatusIndicator::get_menu() const {
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
void StatusIndicator::set_visible(bool p_visible) {
|
void StatusIndicator::set_visible(bool p_visible) {
|
||||||
ERR_MAIN_THREAD_GUARD;
|
ERR_MAIN_THREAD_GUARD;
|
||||||
if (visible == p_visible) {
|
if (visible == p_visible) {
|
||||||
@@ -122,8 +161,18 @@ void StatusIndicator::set_visible(bool p_visible) {
|
|||||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_STATUS_INDICATOR)) {
|
||||||
if (visible && iid == DisplayServer::INVALID_INDICATOR_ID) {
|
if (visible && iid == DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
iid = DisplayServer::get_singleton()->create_status_indicator(icon, tooltip, callable_mp(this, &StatusIndicator::_callback));
|
iid = DisplayServer::get_singleton()->create_status_indicator(icon, tooltip, callable_mp(this, &StatusIndicator::_callback));
|
||||||
|
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
RID menu_rid = pm->bind_global_menu();
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, menu_rid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!visible && iid != DisplayServer::INVALID_INDICATOR_ID) {
|
if (!visible && iid != DisplayServer::INVALID_INDICATOR_ID) {
|
||||||
|
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(menu));
|
||||||
|
if (pm) {
|
||||||
|
pm->unbind_global_menu();
|
||||||
|
DisplayServer::get_singleton()->status_indicator_set_menu(iid, RID());
|
||||||
|
}
|
||||||
DisplayServer::get_singleton()->delete_status_indicator(iid);
|
DisplayServer::get_singleton()->delete_status_indicator(iid);
|
||||||
iid = DisplayServer::INVALID_INDICATOR_ID;
|
iid = DisplayServer::INVALID_INDICATOR_ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,11 @@
|
|||||||
class StatusIndicator : public Node {
|
class StatusIndicator : public Node {
|
||||||
GDCLASS(StatusIndicator, Node);
|
GDCLASS(StatusIndicator, Node);
|
||||||
|
|
||||||
Ref<Image> icon;
|
Ref<Texture2D> icon;
|
||||||
String tooltip;
|
String tooltip;
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
DisplayServer::IndicatorID iid = DisplayServer::INVALID_INDICATOR_ID;
|
DisplayServer::IndicatorID iid = DisplayServer::INVALID_INDICATOR_ID;
|
||||||
|
NodePath menu;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
@@ -49,12 +50,15 @@ protected:
|
|||||||
void _callback(MouseButton p_index, const Point2i &p_pos);
|
void _callback(MouseButton p_index, const Point2i &p_pos);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_icon(const Ref<Image> &p_icon);
|
void set_icon(const Ref<Texture2D> &p_icon);
|
||||||
Ref<Image> get_icon() const;
|
Ref<Texture2D> get_icon() const;
|
||||||
|
|
||||||
void set_tooltip(const String &p_tooltip);
|
void set_tooltip(const String &p_tooltip);
|
||||||
String get_tooltip() const;
|
String get_tooltip() const;
|
||||||
|
|
||||||
|
void set_menu(const NodePath &p_menu);
|
||||||
|
NodePath get_menu() const;
|
||||||
|
|
||||||
void set_visible(bool p_visible);
|
void set_visible(bool p_visible);
|
||||||
bool is_visible() const;
|
bool is_visible() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -709,12 +709,12 @@ void DisplayServer::set_icon(const Ref<Image> &p_icon) {
|
|||||||
WARN_PRINT("Icon not supported by this display server.");
|
WARN_PRINT("Icon not supported by this display server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayServer::IndicatorID DisplayServer::create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback) {
|
DisplayServer::IndicatorID DisplayServer::create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) {
|
||||||
WARN_PRINT("Status indicator not supported by this display server.");
|
WARN_PRINT("Status indicator not supported by this display server.");
|
||||||
return INVALID_INDICATOR_ID;
|
return INVALID_INDICATOR_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServer::status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon) {
|
void DisplayServer::status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) {
|
||||||
WARN_PRINT("Status indicator not supported by this display server.");
|
WARN_PRINT("Status indicator not supported by this display server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,6 +722,10 @@ void DisplayServer::status_indicator_set_tooltip(IndicatorID p_id, const String
|
|||||||
WARN_PRINT("Status indicator not supported by this display server.");
|
WARN_PRINT("Status indicator not supported by this display server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServer::status_indicator_set_menu(IndicatorID p_id, const RID &p_menu_rid) {
|
||||||
|
WARN_PRINT("Status indicator not supported by this display server.");
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayServer::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
|
void DisplayServer::status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) {
|
||||||
WARN_PRINT("Status indicator not supported by this display server.");
|
WARN_PRINT("Status indicator not supported by this display server.");
|
||||||
}
|
}
|
||||||
@@ -977,6 +981,7 @@ void DisplayServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("create_status_indicator", "icon", "tooltip", "callback"), &DisplayServer::create_status_indicator);
|
ClassDB::bind_method(D_METHOD("create_status_indicator", "icon", "tooltip", "callback"), &DisplayServer::create_status_indicator);
|
||||||
ClassDB::bind_method(D_METHOD("status_indicator_set_icon", "id", "icon"), &DisplayServer::status_indicator_set_icon);
|
ClassDB::bind_method(D_METHOD("status_indicator_set_icon", "id", "icon"), &DisplayServer::status_indicator_set_icon);
|
||||||
ClassDB::bind_method(D_METHOD("status_indicator_set_tooltip", "id", "tooltip"), &DisplayServer::status_indicator_set_tooltip);
|
ClassDB::bind_method(D_METHOD("status_indicator_set_tooltip", "id", "tooltip"), &DisplayServer::status_indicator_set_tooltip);
|
||||||
|
ClassDB::bind_method(D_METHOD("status_indicator_set_menu", "id", "menu_rid"), &DisplayServer::status_indicator_set_menu);
|
||||||
ClassDB::bind_method(D_METHOD("status_indicator_set_callback", "id", "callback"), &DisplayServer::status_indicator_set_callback);
|
ClassDB::bind_method(D_METHOD("status_indicator_set_callback", "id", "callback"), &DisplayServer::status_indicator_set_callback);
|
||||||
ClassDB::bind_method(D_METHOD("delete_status_indicator", "id"), &DisplayServer::delete_status_indicator);
|
ClassDB::bind_method(D_METHOD("delete_status_indicator", "id"), &DisplayServer::delete_status_indicator);
|
||||||
|
|
||||||
|
|||||||
@@ -564,9 +564,10 @@ public:
|
|||||||
virtual void set_native_icon(const String &p_filename);
|
virtual void set_native_icon(const String &p_filename);
|
||||||
virtual void set_icon(const Ref<Image> &p_icon);
|
virtual void set_icon(const Ref<Image> &p_icon);
|
||||||
|
|
||||||
virtual IndicatorID create_status_indicator(const Ref<Image> &p_icon, const String &p_tooltip, const Callable &p_callback);
|
virtual IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback);
|
||||||
virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Image> &p_icon);
|
virtual void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon);
|
||||||
virtual void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip);
|
virtual void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip);
|
||||||
|
virtual void status_indicator_set_menu(IndicatorID p_id, const RID &p_menu_rid);
|
||||||
virtual void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback);
|
virtual void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback);
|
||||||
virtual void delete_status_indicator(IndicatorID p_id);
|
virtual void delete_status_indicator(IndicatorID p_id);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user