Popups have also been converted to windows
Controls using the old modal API have been replaced to use popups.
This commit is contained in:
@ -247,6 +247,9 @@ void ColorPicker::_update_color(bool p_update_sliders) {
|
||||
}
|
||||
|
||||
void ColorPicker::_update_presets() {
|
||||
return;
|
||||
//presets should be shown using buttons or something else, this method is not a good idea
|
||||
|
||||
presets_per_row = 10;
|
||||
Size2 size = bt_add_preset->get_size();
|
||||
Size2 preset_size = Size2(MIN(size.width * presets.size(), presets_per_row * size.width), size.height * (Math::ceil((float)presets.size() / presets_per_row)));
|
||||
@ -884,8 +887,32 @@ void ColorPickerButton::_modal_closed() {
|
||||
void ColorPickerButton::pressed() {
|
||||
|
||||
_update_picker();
|
||||
popup->set_position(get_screen_position() - picker->get_combined_minimum_size() * get_global_transform().get_scale());
|
||||
//popup->set_scale(get_global_transform().get_scale());
|
||||
|
||||
popup->set_as_minsize();
|
||||
|
||||
Rect2i usable_rect = popup->get_usable_parent_rect();
|
||||
//let's try different positions to see which one we can use
|
||||
|
||||
Rect2i cp_rect(Point2i(), popup->get_size());
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i > 1) {
|
||||
cp_rect.position.y = get_screen_position().y - cp_rect.size.y;
|
||||
} else {
|
||||
cp_rect.position.y = get_screen_position().y + get_size().height;
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
cp_rect.position.x = get_screen_position().x;
|
||||
} else {
|
||||
|
||||
cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - get_size().x));
|
||||
}
|
||||
|
||||
if (usable_rect.encloses(cp_rect)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
popup->set_position(cp_rect.position);
|
||||
popup->popup();
|
||||
picker->set_focus_on_line_edit();
|
||||
}
|
||||
@ -961,7 +988,9 @@ PopupPanel *ColorPickerButton::get_popup() {
|
||||
void ColorPickerButton::_update_picker() {
|
||||
if (!picker) {
|
||||
popup = memnew(PopupPanel);
|
||||
popup->set_wrap_controls(true);
|
||||
picker = memnew(ColorPicker);
|
||||
picker->set_anchors_and_margins_preset(PRESET_WIDE);
|
||||
popup->add_child(picker);
|
||||
add_child(popup);
|
||||
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
|
||||
|
||||
@ -625,7 +625,7 @@ void Control::_notification(int p_notification) {
|
||||
get_viewport()->_gui_hid_control(this);
|
||||
|
||||
//remove key focus
|
||||
//remove modalness
|
||||
|
||||
} else {
|
||||
data.minimum_size_valid = false;
|
||||
_size_changed();
|
||||
@ -2117,9 +2117,6 @@ void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_o
|
||||
|
||||
Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
|
||||
|
||||
if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated
|
||||
return;
|
||||
|
||||
if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated
|
||||
return;
|
||||
|
||||
|
||||
@ -63,6 +63,7 @@ void MenuButton::pressed() {
|
||||
|
||||
popup->set_size(Size2(size.width, 0));
|
||||
popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size()));
|
||||
popup->take_mouse_focus();
|
||||
popup->popup();
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +42,7 @@ void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
|
||||
void Popup::_parent_focused() {
|
||||
|
||||
_close_pressed();
|
||||
}
|
||||
void Popup::_notification(int p_what) {
|
||||
@ -72,6 +73,7 @@ void Popup::_notification(int p_what) {
|
||||
} break;
|
||||
case NOTIFICATION_WM_CLOSE_REQUEST: {
|
||||
_close_pressed();
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@ -101,6 +103,35 @@ void Popup::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("popup_hide"));
|
||||
}
|
||||
|
||||
Rect2i Popup::_popup_adjust_rect() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
|
||||
Rect2i parent = get_usable_parent_rect();
|
||||
|
||||
if (parent == Rect2i()) {
|
||||
return Rect2i();
|
||||
}
|
||||
|
||||
Rect2i current(get_position(), get_size());
|
||||
|
||||
if (current.position.x + current.size.x > parent.position.x + parent.size.x) {
|
||||
current.position.x = parent.position.x + parent.size.x - current.size.x;
|
||||
}
|
||||
|
||||
if (current.position.x < parent.position.x) {
|
||||
current.position.x = parent.position.x;
|
||||
}
|
||||
|
||||
if (current.position.y + current.size.y > parent.position.y + parent.size.y) {
|
||||
current.position.y = parent.position.y + parent.size.y - current.size.y;
|
||||
}
|
||||
|
||||
if (current.position.y < parent.position.y) {
|
||||
current.position.y = parent.position.y;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
Popup::Popup() {
|
||||
|
||||
parent_visible = nullptr;
|
||||
@ -166,7 +197,9 @@ void PopupPanel::_update_child_rects() {
|
||||
|
||||
void PopupPanel::_notification(int p_what) {
|
||||
|
||||
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_ENTER_TREE) {
|
||||
if (p_what == NOTIFICATION_THEME_CHANGED) {
|
||||
panel->add_theme_style_override("panel", get_theme_stylebox("panel", "PopupPanel"));
|
||||
} else if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_ENTER_TREE) {
|
||||
|
||||
panel->add_theme_style_override("panel", get_theme_stylebox("panel", "PopupPanel"));
|
||||
_update_child_rects();
|
||||
|
||||
@ -41,9 +41,11 @@ class Popup : public Window {
|
||||
|
||||
void _input_from_window(const Ref<InputEvent> &p_event);
|
||||
void _parent_focused();
|
||||
void _close_pressed();
|
||||
|
||||
protected:
|
||||
void _close_pressed();
|
||||
virtual Rect2i _popup_adjust_rect() const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
||||
@ -185,6 +185,9 @@ void PopupMenu::_activate_submenu(int over) {
|
||||
|
||||
void PopupMenu::_submenu_timeout() {
|
||||
|
||||
//if (!has_focus()) {
|
||||
// return; //do not activate if not has focus
|
||||
//}
|
||||
if (mouse_over == submenu_over)
|
||||
_activate_submenu(mouse_over);
|
||||
|
||||
@ -196,17 +199,24 @@ void PopupMenu::_scroll(float p_factor, const Point2 &p_over) {
|
||||
int vseparation = get_theme_constant("vseparation");
|
||||
Ref<Font> font = get_theme_font("font");
|
||||
|
||||
float dy = (vseparation + font->get_height()) * 3 * p_factor;
|
||||
Rect2 visible_rect = get_usable_parent_rect();
|
||||
|
||||
int dy = (vseparation + font->get_height()) * 3 * p_factor;
|
||||
if (dy > 0) {
|
||||
const float global_top = get_position().y;
|
||||
const float limit = global_top < 0 ? -global_top : 0;
|
||||
const float limit = global_top < visible_rect.position.y ? visible_rect.position.y - global_top : 0;
|
||||
dy = MIN(dy, limit);
|
||||
} else if (dy < 0) {
|
||||
const float global_bottom = get_position().y + get_size().y;
|
||||
const float viewport_height = get_parent_rect().size.y;
|
||||
const float viewport_height = visible_rect.position.y + visible_rect.size.y;
|
||||
const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0;
|
||||
dy = -MIN(-dy, limit);
|
||||
}
|
||||
|
||||
if (dy == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_position(get_position() + Vector2(0, dy));
|
||||
|
||||
Ref<InputEventMouseMotion> ie;
|
||||
@ -295,15 +305,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
case BUTTON_WHEEL_DOWN: {
|
||||
|
||||
if (get_position().y + get_size().y > get_parent_rect().size.y) {
|
||||
_scroll(-b->get_factor(), b->get_position());
|
||||
}
|
||||
_scroll(-b->get_factor(), b->get_position());
|
||||
} break;
|
||||
case BUTTON_WHEEL_UP: {
|
||||
|
||||
if (get_position().y < 0) {
|
||||
_scroll(b->get_factor(), b->get_position());
|
||||
}
|
||||
_scroll(b->get_factor(), b->get_position());
|
||||
} break;
|
||||
default: {
|
||||
// Allow activating item by releasing the LMB or any that was down when the popup appeared
|
||||
@ -355,7 +361,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
||||
for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
|
||||
|
||||
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
|
||||
call_deferred("hide");
|
||||
|
||||
_close_pressed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -382,9 +389,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventPanGesture> pan_gesture = p_event;
|
||||
if (pan_gesture.is_valid()) {
|
||||
if (get_position().y + get_size().y > get_parent_rect().size.y || get_position().y < 0) {
|
||||
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
|
||||
}
|
||||
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
|
||||
}
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
@ -578,7 +583,7 @@ void PopupMenu::_notification(int p_what) {
|
||||
} break;
|
||||
case NOTIFICATION_WM_MOUSE_ENTER: {
|
||||
|
||||
grab_focus();
|
||||
//grab_focus();
|
||||
} break;
|
||||
case NOTIFICATION_WM_MOUSE_EXIT: {
|
||||
|
||||
@ -594,6 +599,21 @@ void PopupMenu::_notification(int p_what) {
|
||||
} break;
|
||||
case NOTIFICATION_WM_SIZE_CHANGED: {
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
//only used when using operating system windows
|
||||
if (get_window_id() != DisplayServer::INVALID_WINDOW_ID && autohide_areas.size()) {
|
||||
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
|
||||
mouse_pos -= get_position();
|
||||
|
||||
for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
|
||||
|
||||
if (!Rect2(Point2(), get_size()).has_point(mouse_pos) && E->get().has_point(mouse_pos)) {
|
||||
_close_pressed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
|
||||
@ -617,6 +637,12 @@ void PopupMenu::_notification(int p_what) {
|
||||
|
||||
pm->hide();
|
||||
}
|
||||
|
||||
set_process_internal(false);
|
||||
} else {
|
||||
if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
|
||||
set_process_internal(true);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -1366,6 +1392,14 @@ void PopupMenu::clear_autohide_areas() {
|
||||
autohide_areas.clear();
|
||||
}
|
||||
|
||||
void PopupMenu::take_mouse_focus() {
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
|
||||
if (get_parent()) {
|
||||
get_parent()->get_viewport()->pass_mouse_focus_to(this, control);
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input);
|
||||
@ -1473,7 +1507,7 @@ PopupMenu::PopupMenu() {
|
||||
add_child(control);
|
||||
|
||||
control->set_anchors_and_margins_preset(Control::PRESET_WIDE);
|
||||
control->connect("gui_input", callable_mp(this, &PopupMenu::_gui_input));
|
||||
connect("window_input", callable_mp(this, &PopupMenu::_gui_input));
|
||||
control->connect("draw", callable_mp(this, &PopupMenu::_draw));
|
||||
|
||||
mouse_over = -1;
|
||||
|
||||
@ -215,6 +215,8 @@ public:
|
||||
|
||||
virtual void popup(const Rect2 &p_bounds = Rect2());
|
||||
|
||||
void take_mouse_focus();
|
||||
|
||||
PopupMenu();
|
||||
~PopupMenu();
|
||||
};
|
||||
|
||||
@ -38,6 +38,8 @@
|
||||
#include "core/project_settings.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
#include "box_container.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_scale.h"
|
||||
#endif
|
||||
@ -2056,13 +2058,12 @@ void Tree::_text_editor_modal_close() {
|
||||
if (value_editor->has_point(value_editor->get_local_mouse_position()))
|
||||
return;
|
||||
|
||||
text_editor_enter(text_editor->get_text());
|
||||
_text_editor_enter(text_editor->get_text());
|
||||
}
|
||||
|
||||
void Tree::text_editor_enter(String p_text) {
|
||||
void Tree::_text_editor_enter(String p_text) {
|
||||
|
||||
text_editor->hide();
|
||||
value_editor->hide();
|
||||
popup_editor->hide();
|
||||
|
||||
if (!popup_edited_item)
|
||||
return;
|
||||
@ -2806,22 +2807,22 @@ bool Tree::edit_selected() {
|
||||
|
||||
} else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) {
|
||||
|
||||
Rect2 popup_rect;
|
||||
|
||||
Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2);
|
||||
Point2i textedpos = get_global_position() + rect.position - ofs;
|
||||
|
||||
Point2i textedpos = get_screen_position() + rect.position - ofs;
|
||||
cache.text_editor_position = textedpos;
|
||||
text_editor->set_position(textedpos);
|
||||
text_editor->set_size(rect.size);
|
||||
popup_rect.position = textedpos;
|
||||
popup_rect.size = rect.size;
|
||||
text_editor->clear();
|
||||
text_editor->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::range_step_decimals(c.step)));
|
||||
text_editor->select_all();
|
||||
|
||||
if (c.mode == TreeItem::CELL_MODE_RANGE) {
|
||||
|
||||
value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height));
|
||||
value_editor->set_size(Size2(rect.size.width, 1));
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal no longer works, need to replace by a popup
|
||||
#endif
|
||||
popup_rect.size.y += value_editor->get_minimum_size().height;
|
||||
|
||||
value_editor->show();
|
||||
updating_value_editor = true;
|
||||
value_editor->set_min(c.min);
|
||||
@ -2830,12 +2831,17 @@ bool Tree::edit_selected() {
|
||||
value_editor->set_value(c.val);
|
||||
value_editor->set_exp_ratio(c.expr);
|
||||
updating_value_editor = false;
|
||||
} else {
|
||||
value_editor->hide();
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal no longer works, need to replace by a popup
|
||||
#endif
|
||||
text_editor->show();
|
||||
|
||||
popup_editor->set_position(popup_rect.position);
|
||||
popup_editor->set_size(popup_rect.size);
|
||||
popup_editor->popup();
|
||||
popup_editor->child_controls_changed();
|
||||
|
||||
text_editor->grab_focus();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4026,13 +4032,22 @@ Tree::Tree() {
|
||||
popup_menu->hide();
|
||||
add_child(popup_menu);
|
||||
// popup_menu->set_as_toplevel(true);
|
||||
|
||||
popup_editor = memnew(PopupPanel);
|
||||
popup_editor->set_wrap_controls(true);
|
||||
add_child(popup_editor);
|
||||
popup_editor_vb = memnew(VBoxContainer);
|
||||
popup_editor->add_child(popup_editor_vb);
|
||||
popup_editor_vb->add_theme_constant_override("separation", 0);
|
||||
popup_editor_vb->set_anchors_and_margins_preset(PRESET_WIDE);
|
||||
text_editor = memnew(LineEdit);
|
||||
add_child(text_editor);
|
||||
text_editor->set_as_toplevel(true);
|
||||
text_editor->hide();
|
||||
popup_editor_vb->add_child(text_editor);
|
||||
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
text_editor->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
value_editor = memnew(HSlider);
|
||||
add_child(value_editor);
|
||||
value_editor->set_as_toplevel(true);
|
||||
value_editor->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
value_editor->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
popup_editor_vb->add_child(value_editor);
|
||||
value_editor->hide();
|
||||
|
||||
h_scroll = memnew(HScrollBar);
|
||||
@ -4047,13 +4062,11 @@ Tree::Tree() {
|
||||
|
||||
h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
|
||||
v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
|
||||
text_editor->connect("text_entered", callable_mp(this, &Tree::text_editor_enter));
|
||||
text_editor->connect("modal_closed", callable_mp(this, &Tree::_text_editor_modal_close));
|
||||
text_editor->connect("text_entered", callable_mp(this, &Tree::_text_editor_enter));
|
||||
popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_modal_close));
|
||||
popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select));
|
||||
value_editor->connect("value_changed", callable_mp(this, &Tree::value_editor_changed));
|
||||
|
||||
value_editor->set_as_toplevel(true);
|
||||
text_editor->set_as_toplevel(true);
|
||||
set_notify_transform(true);
|
||||
|
||||
updating_value_editor = false;
|
||||
|
||||
@ -290,6 +290,8 @@ public:
|
||||
VARIANT_ENUM_CAST(TreeItem::TreeCellMode);
|
||||
VARIANT_ENUM_CAST(TreeItem::TextAlign);
|
||||
|
||||
class VBoxContainer;
|
||||
|
||||
class Tree : public Control {
|
||||
|
||||
GDCLASS(Tree, Control);
|
||||
@ -359,6 +361,10 @@ private:
|
||||
};
|
||||
|
||||
bool show_column_titles;
|
||||
|
||||
VBoxContainer *popup_editor_vb;
|
||||
|
||||
PopupPanel *popup_editor;
|
||||
LineEdit *text_editor;
|
||||
HSlider *value_editor;
|
||||
bool updating_value_editor;
|
||||
@ -379,7 +385,7 @@ private:
|
||||
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
|
||||
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = NULL, bool *r_in_range = NULL, bool p_force_deselect = false);
|
||||
int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
|
||||
void text_editor_enter(String p_text);
|
||||
void _text_editor_enter(String p_text);
|
||||
void _text_editor_modal_close();
|
||||
void value_editor_changed(double p_value);
|
||||
|
||||
|
||||
@ -191,6 +191,7 @@ Viewport::GUI::GUI() {
|
||||
|
||||
dragging = false;
|
||||
mouse_focus = NULL;
|
||||
forced_mouse_focus = false;
|
||||
mouse_click_grabber = NULL;
|
||||
mouse_focus_mask = 0;
|
||||
key_focus = NULL;
|
||||
@ -595,6 +596,7 @@ void Viewport::_notification(int p_what) {
|
||||
if (!has_mouse_event) {
|
||||
Ref<InputEventMouseMotion> mm;
|
||||
mm.instance();
|
||||
|
||||
mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
|
||||
mm->set_global_position(physics_last_mousepos);
|
||||
mm->set_position(physics_last_mousepos);
|
||||
@ -847,8 +849,7 @@ void Viewport::_notification(int p_what) {
|
||||
|
||||
_drop_physics_mouseover();
|
||||
|
||||
if (gui.mouse_focus) {
|
||||
//if mouse is being pressed, send a release event
|
||||
if (gui.mouse_focus && !gui.forced_mouse_focus) {
|
||||
_drop_mouse_focus();
|
||||
}
|
||||
} break;
|
||||
@ -1107,7 +1108,9 @@ void Viewport::_camera_set(Camera *p_camera) {
|
||||
if (camera) {
|
||||
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
|
||||
}
|
||||
|
||||
camera = p_camera;
|
||||
|
||||
if (!camera_override) {
|
||||
if (camera)
|
||||
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
|
||||
@ -1984,6 +1987,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
||||
//disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise
|
||||
if (gui.mouse_focus_mask == 0) {
|
||||
gui.mouse_focus = NULL;
|
||||
gui.forced_mouse_focus = false;
|
||||
}
|
||||
|
||||
if (mouse_focus && mouse_focus->can_process()) {
|
||||
@ -2029,6 +2033,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
||||
if (gui.drag_data.get_type() != Variant::NIL) {
|
||||
|
||||
gui.mouse_focus = NULL;
|
||||
gui.forced_mouse_focus = false;
|
||||
gui.mouse_focus_mask = 0;
|
||||
break;
|
||||
} else {
|
||||
@ -2427,6 +2432,7 @@ void Viewport::_gui_remove_control(Control *p_control) {
|
||||
|
||||
if (gui.mouse_focus == p_control) {
|
||||
gui.mouse_focus = NULL;
|
||||
gui.forced_mouse_focus = false;
|
||||
gui.mouse_focus_mask = 0;
|
||||
}
|
||||
if (gui.last_mouse_focus == p_control) {
|
||||
@ -2481,6 +2487,7 @@ void Viewport::_drop_mouse_focus() {
|
||||
Control *c = gui.mouse_focus;
|
||||
int mask = gui.mouse_focus_mask;
|
||||
gui.mouse_focus = NULL;
|
||||
gui.forced_mouse_focus = false;
|
||||
gui.mouse_focus_mask = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@ -3234,6 +3241,22 @@ bool Viewport::is_embedding_subwindows() const {
|
||||
return gui.embed_subwindows_hint;
|
||||
}
|
||||
|
||||
void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
|
||||
ERR_FAIL_NULL(p_viewport);
|
||||
ERR_FAIL_NULL(p_control);
|
||||
|
||||
if (gui.mouse_focus) {
|
||||
p_viewport->gui.mouse_focus = p_control;
|
||||
p_viewport->gui.mouse_focus_mask = gui.mouse_focus_mask;
|
||||
p_viewport->gui.key_focus = p_control;
|
||||
p_viewport->gui.forced_mouse_focus = true;
|
||||
|
||||
gui.mouse_focus = nullptr;
|
||||
gui.forced_mouse_focus = false;
|
||||
gui.mouse_focus_mask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
|
||||
@ -3465,6 +3488,7 @@ Viewport::Viewport() {
|
||||
gui.canvas_sort_index = 0;
|
||||
gui.roots_order_dirty = false;
|
||||
gui.mouse_focus = NULL;
|
||||
gui.forced_mouse_focus = false;
|
||||
gui.last_mouse_focus = NULL;
|
||||
gui.subwindow_focused = nullptr;
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
|
||||
@ -302,6 +302,7 @@ private:
|
||||
struct GUI {
|
||||
// info used when this is a window
|
||||
|
||||
bool forced_mouse_focus; //used for menu buttons
|
||||
bool key_event_accepted;
|
||||
Control *mouse_focus;
|
||||
Control *last_mouse_focus;
|
||||
@ -555,6 +556,9 @@ public:
|
||||
bool is_embedding_subwindows() const;
|
||||
|
||||
Viewport *get_parent_viewport() const;
|
||||
|
||||
void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
|
||||
|
||||
Viewport();
|
||||
~Viewport();
|
||||
};
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/resources/dynamic_font.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void Window::set_title(const String &p_title) {
|
||||
title = p_title;
|
||||
|
||||
@ -207,8 +208,8 @@ void Window::set_ime_position(const Point2i &p_pos) {
|
||||
|
||||
bool Window::is_embedded() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), false);
|
||||
Viewport *parent_vp = get_parent_viewport();
|
||||
return parent_vp && parent_vp->is_embedding_subwindows();
|
||||
|
||||
return _get_embedder() != nullptr;
|
||||
}
|
||||
|
||||
void Window::_make_window() {
|
||||
@ -1027,6 +1028,12 @@ void Window::popup(const Rect2 &p_screen_rect) {
|
||||
set_size(p_screen_rect.size);
|
||||
}
|
||||
|
||||
Rect2i adjust = _popup_adjust_rect();
|
||||
if (adjust != Rect2i()) {
|
||||
set_position(adjust.position);
|
||||
set_size(adjust.size);
|
||||
}
|
||||
|
||||
set_transient(true);
|
||||
set_visible(true);
|
||||
_post_popup();
|
||||
@ -1049,6 +1056,24 @@ bool Window::has_focus() const {
|
||||
return focused;
|
||||
}
|
||||
|
||||
Rect2i Window::get_usable_parent_rect() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
|
||||
Rect2i parent;
|
||||
if (is_embedded()) {
|
||||
parent = _get_embedder()->get_visible_rect();
|
||||
print_line("using embedded " + parent);
|
||||
} else {
|
||||
|
||||
const Window *w = is_visible() ? this : get_parent_visible_window();
|
||||
//find a parent that can contain us
|
||||
ERR_FAIL_COND_V(!w, Rect2());
|
||||
|
||||
parent = DisplayServer::get_singleton()->screen_get_usable_rect(DisplayServer::get_singleton()->window_get_current_screen(w->get_window_id()));
|
||||
print_line("using windowid " + parent);
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
void Window::add_child_notify(Node *p_child) {
|
||||
|
||||
Control *child_c = Object::cast_to<Control>(p_child);
|
||||
@ -1292,6 +1317,12 @@ void Window::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Window::has_theme_color, DEFVAL(""));
|
||||
ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Window::has_theme_constant, DEFVAL(""));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("popup", "rect"), &Window::popup, DEFVAL(Rect2i()));
|
||||
ClassDB::bind_method(D_METHOD("popup_on_parent", "parent_rect"), &Window::popup_on_parent);
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Window::popup_centered_ratio, DEFVAL(0.8));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i()));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered, DEFVAL(Size2i()), DEFVAL(0.75));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
|
||||
|
||||
@ -108,8 +108,6 @@ private:
|
||||
|
||||
void _propagate_window_notification(Node *p_node, int p_notification);
|
||||
|
||||
virtual DisplayServer::WindowID get_window_id() const;
|
||||
|
||||
void _update_window_callbacks();
|
||||
|
||||
void _clear_transient();
|
||||
@ -123,8 +121,6 @@ private:
|
||||
Control *theme_owner = nullptr;
|
||||
Window *theme_owner_window = nullptr;
|
||||
|
||||
Viewport *_get_embedder() const;
|
||||
|
||||
Viewport *embedder = nullptr;
|
||||
|
||||
friend class Viewport; //friend back, can call the methods below
|
||||
@ -136,6 +132,10 @@ private:
|
||||
void _event_callback(DisplayServer::WindowEvent p_event);
|
||||
|
||||
protected:
|
||||
Viewport *_get_embedder() const;
|
||||
|
||||
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
|
||||
|
||||
virtual void _post_popup() {}
|
||||
virtual Size2 _get_contents_minimum_size() const;
|
||||
static void _bind_methods();
|
||||
@ -234,6 +234,8 @@ public:
|
||||
void grab_focus();
|
||||
bool has_focus() const;
|
||||
|
||||
Rect2i get_usable_parent_rect() const;
|
||||
|
||||
Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
@ -249,6 +251,7 @@ public:
|
||||
bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
|
||||
Rect2i get_parent_rect() const;
|
||||
virtual DisplayServer::WindowID get_window_id() const;
|
||||
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
Reference in New Issue
Block a user