Fix connecting a signal with a double click is too difficult
This commit is contained in:
parent
3978628c6c
commit
f2dfa65b07
|
@ -899,9 +899,7 @@ Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorHelpBit *help_bit = memnew(EditorHelpBit(p_text));
|
return EditorHelpBitTooltip::show_tooltip(p_text, const_cast<ConnectionsDockTree *>(this));
|
||||||
EditorHelpBitTooltip::show_tooltip(help_bit, const_cast<ConnectionsDockTree *>(this));
|
|
||||||
return memnew(Control); // Make the standard tooltip invisible.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _ConnectionsDockMethodInfoSort {
|
struct _ConnectionsDockMethodInfoSort {
|
||||||
|
|
|
@ -116,6 +116,8 @@ const Vector<String> packed_array_types = {
|
||||||
DocTools *EditorHelp::doc = nullptr;
|
DocTools *EditorHelp::doc = nullptr;
|
||||||
DocTools *EditorHelp::ext_doc = nullptr;
|
DocTools *EditorHelp::ext_doc = nullptr;
|
||||||
|
|
||||||
|
bool EditorHelpBitTooltip::_is_tooltip_visible = false;
|
||||||
|
|
||||||
static bool _attempt_doc_load(const String &p_class) {
|
static bool _attempt_doc_load(const String &p_class) {
|
||||||
// Docgen always happens in the outer-most class: it also generates docs for inner classes.
|
// Docgen always happens in the outer-most class: it also generates docs for inner classes.
|
||||||
String outer_class = p_class.get_slice(".", 0);
|
String outer_class = p_class.get_slice(".", 0);
|
||||||
|
@ -3778,6 +3780,14 @@ void EditorHelpBitTooltip::_safe_queue_free() {
|
||||||
void EditorHelpBitTooltip::_target_gui_input(const Ref<InputEvent> &p_event) {
|
void EditorHelpBitTooltip::_target_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
const Ref<InputEventMouse> mouse_event = p_event;
|
const Ref<InputEventMouse> mouse_event = p_event;
|
||||||
if (mouse_event.is_valid()) {
|
if (mouse_event.is_valid()) {
|
||||||
|
// For some unknown reason, we receive mouse motion of zero when the tooltip
|
||||||
|
// is opened even if the mouse is not moving on Windows now that the toolip
|
||||||
|
// FLAG_POPUP is false.
|
||||||
|
Ref<InputEventMouseMotion> mm = p_event;
|
||||||
|
if (mm.is_valid() && mm->get_relative().is_zero_approx()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_start_timer();
|
_start_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3790,6 +3800,9 @@ void EditorHelpBitTooltip::_notification(int p_what) {
|
||||||
case NOTIFICATION_WM_MOUSE_EXIT:
|
case NOTIFICATION_WM_MOUSE_EXIT:
|
||||||
_start_timer();
|
_start_timer();
|
||||||
break;
|
break;
|
||||||
|
case NOTIFICATION_EXIT_TREE:
|
||||||
|
_is_tooltip_visible = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3811,14 +3824,36 @@ void EditorHelpBitTooltip::_input_from_window(const Ref<InputEvent> &p_event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorHelpBitTooltip::show_tooltip(EditorHelpBit *p_help_bit, Control *p_target) {
|
Control *EditorHelpBitTooltip::show_tooltip(const String &p_symbol, Control *p_target, const String &p_description) {
|
||||||
ERR_FAIL_NULL(p_help_bit);
|
// Show the custom tooltip only if it is not already visible.
|
||||||
|
// The Viewport will retrigger make_custom_tooltip every few seconds
|
||||||
|
// because the return control is not visible even if the custom tooltip is displayed.
|
||||||
|
if (_is_tooltip_visible) {
|
||||||
|
return _make_invisible_control();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorHelpBit *help_bit = memnew(EditorHelpBit(p_symbol));
|
||||||
|
if (!p_description.is_empty()) {
|
||||||
|
help_bit->set_description(p_description);
|
||||||
|
}
|
||||||
EditorHelpBitTooltip *tooltip = memnew(EditorHelpBitTooltip(p_target));
|
EditorHelpBitTooltip *tooltip = memnew(EditorHelpBitTooltip(p_target));
|
||||||
p_help_bit->connect("request_hide", callable_mp(tooltip, &EditorHelpBitTooltip::_safe_queue_free));
|
help_bit->connect("request_hide", callable_mp(tooltip, &EditorHelpBitTooltip::_safe_queue_free));
|
||||||
tooltip->add_child(p_help_bit);
|
tooltip->add_child(help_bit);
|
||||||
p_target->get_viewport()->add_child(tooltip);
|
p_target->get_viewport()->add_child(tooltip);
|
||||||
p_help_bit->update_content_height();
|
help_bit->update_content_height();
|
||||||
|
// When FLAG_POPUP is false, it prevents the editor from losing focus when displaying the tooltip.
|
||||||
|
// This way, clicks and double-clicks are still available outside the tooltip.
|
||||||
|
tooltip->set_flag(Window::FLAG_POPUP, false);
|
||||||
tooltip->popup_under_cursor();
|
tooltip->popup_under_cursor();
|
||||||
|
_is_tooltip_visible = true;
|
||||||
|
|
||||||
|
return _make_invisible_control();
|
||||||
|
}
|
||||||
|
|
||||||
|
Control *EditorHelpBitTooltip::_make_invisible_control() {
|
||||||
|
Control *control = memnew(Control);
|
||||||
|
control->set_visible(false);
|
||||||
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy-paste from `Viewport::_gui_show_tooltip()`.
|
// Copy-paste from `Viewport::_gui_show_tooltip()`.
|
||||||
|
|
|
@ -325,6 +325,7 @@ public:
|
||||||
class EditorHelpBitTooltip : public PopupPanel {
|
class EditorHelpBitTooltip : public PopupPanel {
|
||||||
GDCLASS(EditorHelpBitTooltip, PopupPanel);
|
GDCLASS(EditorHelpBitTooltip, PopupPanel);
|
||||||
|
|
||||||
|
static bool _is_tooltip_visible;
|
||||||
Timer *timer = nullptr;
|
Timer *timer = nullptr;
|
||||||
int _pushing_input = 0;
|
int _pushing_input = 0;
|
||||||
bool _need_free = false;
|
bool _need_free = false;
|
||||||
|
@ -332,13 +333,14 @@ class EditorHelpBitTooltip : public PopupPanel {
|
||||||
void _start_timer();
|
void _start_timer();
|
||||||
void _safe_queue_free();
|
void _safe_queue_free();
|
||||||
void _target_gui_input(const Ref<InputEvent> &p_event);
|
void _target_gui_input(const Ref<InputEvent> &p_event);
|
||||||
|
static Control *_make_invisible_control();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
|
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void show_tooltip(EditorHelpBit *p_help_bit, Control *p_target);
|
static Control *show_tooltip(const String &p_symbol, Control *p_target, const String &p_description = String());
|
||||||
|
|
||||||
void popup_under_cursor();
|
void popup_under_cursor();
|
||||||
|
|
||||||
|
|
|
@ -991,30 +991,30 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_doc_tooltip || !custom_warning.is_empty()) {
|
if (has_doc_tooltip || !custom_warning.is_empty()) {
|
||||||
EditorHelpBit *help_bit = memnew(EditorHelpBit);
|
String symbol;
|
||||||
|
String description;
|
||||||
if (has_doc_tooltip) {
|
if (has_doc_tooltip) {
|
||||||
help_bit->parse_symbol(p_text);
|
symbol = p_text;
|
||||||
|
|
||||||
const EditorInspector *inspector = get_parent_inspector();
|
const EditorInspector *inspector = get_parent_inspector();
|
||||||
if (inspector) {
|
if (inspector) {
|
||||||
const String custom_description = inspector->get_custom_property_description(p_text);
|
const String custom_description = inspector->get_custom_property_description(p_text);
|
||||||
if (!custom_description.is_empty()) {
|
if (!custom_description.is_empty()) {
|
||||||
help_bit->set_description(custom_description);
|
description = custom_description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!custom_warning.is_empty()) {
|
if (!custom_warning.is_empty()) {
|
||||||
String description = "[b][color=" + get_theme_color(SNAME("warning_color")).to_html(false) + "]" + custom_warning + "[/color][/b]";
|
const String custom_warning_description = "[b][color=" + get_theme_color(SNAME("warning_color")).to_html(false) + "]" + custom_warning + "[/color][/b]";
|
||||||
if (!help_bit->get_description().is_empty()) {
|
if (description.is_empty()) {
|
||||||
description += "\n" + help_bit->get_description();
|
description = custom_warning_description;
|
||||||
|
} else {
|
||||||
|
description = custom_warning_description + "\n" + description;
|
||||||
}
|
}
|
||||||
help_bit->set_description(description);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorHelpBitTooltip::show_tooltip(help_bit, const_cast<EditorProperty *>(this));
|
return EditorHelpBitTooltip::show_tooltip(symbol, const_cast<EditorProperty *>(this), description);
|
||||||
return memnew(Control); // Make the standard tooltip invisible.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1270,9 +1270,7 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorHelpBit *help_bit = memnew(EditorHelpBit(p_text));
|
return EditorHelpBitTooltip::show_tooltip(p_text, const_cast<EditorInspectorCategory *>(this));
|
||||||
EditorHelpBitTooltip::show_tooltip(help_bit, const_cast<EditorInspectorCategory *>(this));
|
|
||||||
return memnew(Control); // Make the standard tooltip invisible.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2 EditorInspectorCategory::get_minimum_size() const {
|
Size2 EditorInspectorCategory::get_minimum_size() const {
|
||||||
|
|
|
@ -2267,9 +2267,7 @@ ThemeTypeDialog::ThemeTypeDialog() {
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
||||||
Control *ThemeItemLabel::make_custom_tooltip(const String &p_text) const {
|
Control *ThemeItemLabel::make_custom_tooltip(const String &p_text) const {
|
||||||
EditorHelpBit *help_bit = memnew(EditorHelpBit(p_text));
|
return EditorHelpBitTooltip::show_tooltip(p_text, const_cast<ThemeItemLabel *>(this));
|
||||||
EditorHelpBitTooltip::show_tooltip(help_bit, const_cast<ThemeItemLabel *>(this));
|
|
||||||
return memnew(Control); // Make the standard tooltip invisible.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
|
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
|
||||||
|
|
|
@ -4840,14 +4840,7 @@ void DisplayServerX11::process_events() {
|
||||||
|
|
||||||
WindowID window_id_other = INVALID_WINDOW_ID;
|
WindowID window_id_other = INVALID_WINDOW_ID;
|
||||||
Window wd_other_x11_window;
|
Window wd_other_x11_window;
|
||||||
if (wd.focused) {
|
if (!wd.focused) {
|
||||||
// Handle cases where an unfocused popup is open that needs to receive button-up events.
|
|
||||||
WindowID popup_id = _get_focused_window_or_popup();
|
|
||||||
if (popup_id != INVALID_WINDOW_ID && popup_id != window_id) {
|
|
||||||
window_id_other = popup_id;
|
|
||||||
wd_other_x11_window = windows[popup_id].x11_window;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Propagate the event to the focused window,
|
// Propagate the event to the focused window,
|
||||||
// because it's received only on the topmost window.
|
// because it's received only on the topmost window.
|
||||||
// Note: This is needed for drag & drop to work between windows,
|
// Note: This is needed for drag & drop to work between windows,
|
||||||
|
@ -4970,6 +4963,23 @@ void DisplayServerX11::process_events() {
|
||||||
pos = Point2i(windows[focused_window_id].size.width / 2, windows[focused_window_id].size.height / 2);
|
pos = Point2i(windows[focused_window_id].size.width / 2, windows[focused_window_id].size.height / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitField<MouseButtonMask> last_button_state = 0;
|
||||||
|
if (event.xmotion.state & Button1Mask) {
|
||||||
|
last_button_state.set_flag(MouseButtonMask::LEFT);
|
||||||
|
}
|
||||||
|
if (event.xmotion.state & Button2Mask) {
|
||||||
|
last_button_state.set_flag(MouseButtonMask::MIDDLE);
|
||||||
|
}
|
||||||
|
if (event.xmotion.state & Button3Mask) {
|
||||||
|
last_button_state.set_flag(MouseButtonMask::RIGHT);
|
||||||
|
}
|
||||||
|
if (event.xmotion.state & Button4Mask) {
|
||||||
|
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
|
||||||
|
}
|
||||||
|
if (event.xmotion.state & Button5Mask) {
|
||||||
|
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
|
||||||
|
}
|
||||||
|
|
||||||
Ref<InputEventMouseMotion> mm;
|
Ref<InputEventMouseMotion> mm;
|
||||||
mm.instantiate();
|
mm.instantiate();
|
||||||
|
|
||||||
|
@ -4977,13 +4987,13 @@ void DisplayServerX11::process_events() {
|
||||||
if (xi.pressure_supported) {
|
if (xi.pressure_supported) {
|
||||||
mm->set_pressure(xi.pressure);
|
mm->set_pressure(xi.pressure);
|
||||||
} else {
|
} else {
|
||||||
mm->set_pressure(bool(mouse_get_button_state().has_flag(MouseButtonMask::LEFT)) ? 1.0f : 0.0f);
|
mm->set_pressure(bool(last_button_state.has_flag(MouseButtonMask::LEFT)) ? 1.0f : 0.0f);
|
||||||
}
|
}
|
||||||
mm->set_tilt(xi.tilt);
|
mm->set_tilt(xi.tilt);
|
||||||
mm->set_pen_inverted(xi.pen_inverted);
|
mm->set_pen_inverted(xi.pen_inverted);
|
||||||
|
|
||||||
_get_key_modifier_state(event.xmotion.state, mm);
|
_get_key_modifier_state(event.xmotion.state, mm);
|
||||||
mm->set_button_mask(mouse_get_button_state());
|
mm->set_button_mask(last_button_state);
|
||||||
mm->set_position(pos);
|
mm->set_position(pos);
|
||||||
mm->set_global_position(pos);
|
mm->set_global_position(pos);
|
||||||
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
|
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
|
||||||
|
|
|
@ -1457,6 +1457,17 @@ void Viewport::_gui_show_tooltip() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Controls can implement `make_custom_tooltip` to provide their own tooltip.
|
||||||
|
// This should be a Control node which will be added as child to a TooltipPanel.
|
||||||
|
Control *base_tooltip = tooltip_owner->make_custom_tooltip(gui.tooltip_text);
|
||||||
|
|
||||||
|
// When the custom control is not visible, don't show any tooltip.
|
||||||
|
// This way, the custom tooltip from ConnectionsDockTree can create
|
||||||
|
// its own tooltip without conflicting with the default one, even an empty tooltip.
|
||||||
|
if (base_tooltip && !base_tooltip->is_visible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Popup window which houses the tooltip content.
|
// Popup window which houses the tooltip content.
|
||||||
PopupPanel *panel = memnew(PopupPanel);
|
PopupPanel *panel = memnew(PopupPanel);
|
||||||
panel->set_theme_type_variation(SNAME("TooltipPanel"));
|
panel->set_theme_type_variation(SNAME("TooltipPanel"));
|
||||||
|
@ -1464,10 +1475,6 @@ void Viewport::_gui_show_tooltip() {
|
||||||
// Ensure no opaque background behind the panel as its StyleBox can be partially transparent (e.g. corners).
|
// Ensure no opaque background behind the panel as its StyleBox can be partially transparent (e.g. corners).
|
||||||
panel->set_transparent_background(true);
|
panel->set_transparent_background(true);
|
||||||
|
|
||||||
// Controls can implement `make_custom_tooltip` to provide their own tooltip.
|
|
||||||
// This should be a Control node which will be added as child to a TooltipPanel.
|
|
||||||
Control *base_tooltip = tooltip_owner->make_custom_tooltip(gui.tooltip_text);
|
|
||||||
|
|
||||||
// If no custom tooltip is given, use a default implementation.
|
// If no custom tooltip is given, use a default implementation.
|
||||||
if (!base_tooltip) {
|
if (!base_tooltip) {
|
||||||
gui.tooltip_label = memnew(Label);
|
gui.tooltip_label = memnew(Label);
|
||||||
|
|
Loading…
Reference in New Issue