Popups have also been converted to windows

Controls using the old modal API have been replaced to use popups.
This commit is contained in:
Juan Linietsky 2020-03-19 23:32:09 -03:00
parent 09ba290364
commit b3080bc2f4
25 changed files with 326 additions and 95 deletions

View File

@ -2471,6 +2471,7 @@ void AnimationTrackEdit::_path_entered(const String &p_text) {
undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text); undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text);
undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track)); undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track));
undo_redo->commit_action(); undo_redo->commit_action();
path_popup->hide();
} }
bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const { bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const {
@ -2843,20 +2844,20 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) { if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) {
if (!path) { if (!path) {
path_popup = memnew(Popup);
path_popup->set_wrap_controls(true);
add_child(path_popup);
path = memnew(LineEdit); path = memnew(LineEdit);
add_child(path); path_popup->add_child(path);
path->set_as_toplevel(true); path->set_anchors_and_margins_preset(PRESET_WIDE);
path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered)); path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered));
} }
path->set_text(animation->track_get_path(track)); path->set_text(animation->track_get_path(track));
Vector2 theme_ofs = path->get_theme_stylebox("normal", "LineEdit")->get_offset(); Vector2 theme_ofs = path->get_theme_stylebox("normal", "LineEdit")->get_offset();
path->set_position(get_global_position() + path_rect.position - theme_ofs); path_popup->set_position(get_screen_position() + path_rect.position - theme_ofs);
path->set_size(path_rect.size); path_popup->set_size(path_rect.size);
#ifndef _MSC_VER path_popup->popup();
#warning show modal not supported any longer, need to move this to a popup
#endif
path->show();
path->grab_focus(); path->grab_focus();
path->set_cursor_position(path->get_text().length()); path->set_cursor_position(path->get_text().length());
clicking_on_name = false; clicking_on_name = false;
@ -3093,6 +3094,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
timeline = NULL; timeline = NULL;
root = NULL; root = NULL;
path = NULL; path = NULL;
path_popup = NULL;
menu = NULL; menu = NULL;
clicking_on_name = false; clicking_on_name = false;
dropping_at = 0; dropping_at = 0;

View File

@ -140,6 +140,7 @@ class AnimationTrackEdit : public Control {
}; };
AnimationTimelineEdit *timeline; AnimationTimelineEdit *timeline;
UndoRedo *undo_redo; UndoRedo *undo_redo;
Popup *path_popup;
LineEdit *path; LineEdit *path;
Node *root; Node *root;
Control *play_position; //separate control used to draw so updates for only position changed are much faster Control *play_position; //separate control used to draw so updates for only position changed are much faster

View File

@ -273,7 +273,7 @@ void EditorSpinSlider::_notification(int p_what) {
Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE); Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
draw_rect(grabber_rect, c); draw_rect(grabber_rect, c);
bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input->is_visible(); bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input_popup->is_visible();
if (grabber->is_visible() != display_grabber) { if (grabber->is_visible() != display_grabber) {
if (display_grabber) { if (display_grabber) {
grabber->show(); grabber->show();
@ -371,7 +371,7 @@ void EditorSpinSlider::_evaluate_input_text() {
//text_entered signal //text_entered signal
void EditorSpinSlider::_value_input_entered(const String &p_text) { void EditorSpinSlider::_value_input_entered(const String &p_text) {
value_input_just_closed = true; value_input_just_closed = true;
value_input->hide(); value_input_popup->hide();
} }
//modal_closed signal //modal_closed signal
@ -394,7 +394,7 @@ void EditorSpinSlider::_value_focus_exited() {
// -> modal_close was not called // -> modal_close was not called
// -> need to close/hide manually // -> need to close/hide manually
if (!value_input_just_closed) { //value_input_just_closed should do the same if (!value_input_just_closed) { //value_input_just_closed should do the same
value_input->hide(); value_input_popup->hide();
//tab was pressed //tab was pressed
} else { } else {
//enter, click, esc //enter, click, esc
@ -437,11 +437,11 @@ void EditorSpinSlider::set_custom_label_color(bool p_use_custom_label_color, Col
} }
void EditorSpinSlider::_focus_entered() { void EditorSpinSlider::_focus_entered() {
Rect2 gr = get_global_rect(); Rect2 gr = get_screen_rect();
value_input->set_text(get_text_value()); value_input->set_text(get_text_value());
value_input->set_position(gr.position); value_input_popup->set_position(gr.position);
value_input->set_size(gr.size); value_input_popup->set_size(gr.size);
value_input->call_deferred("show_modal"); value_input_popup->call_deferred("popup");
value_input->call_deferred("grab_focus"); value_input->call_deferred("grab_focus");
value_input->call_deferred("select_all"); value_input->call_deferred("select_all");
value_input->set_focus_next(find_next_valid_focus()->get_path()); value_input->set_focus_next(find_next_valid_focus()->get_path());
@ -488,11 +488,13 @@ EditorSpinSlider::EditorSpinSlider() {
mousewheel_over_grabber = false; mousewheel_over_grabber = false;
grabbing_grabber = false; grabbing_grabber = false;
grabber_range = 1; grabber_range = 1;
value_input_popup = memnew(Popup);
add_child(value_input_popup);
value_input = memnew(LineEdit); value_input = memnew(LineEdit);
add_child(value_input); value_input_popup->add_child(value_input);
value_input->set_as_toplevel(true); value_input_popup->set_wrap_controls(true);
value_input->hide(); value_input->set_anchors_and_margins_preset(PRESET_WIDE);
value_input->connect("modal_closed", callable_mp(this, &EditorSpinSlider::_value_input_closed)); value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered)); value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered));
value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited)); value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
value_input_just_closed = false; value_input_just_closed = false;

View File

@ -62,6 +62,7 @@ class EditorSpinSlider : public Range {
Vector2 grabbing_spinner_mouse_pos; Vector2 grabbing_spinner_mouse_pos;
double pre_grab_value; double pre_grab_value;
Popup *value_input_popup;
LineEdit *value_input; LineEdit *value_input;
bool value_input_just_closed; bool value_input_just_closed;

View File

@ -155,14 +155,10 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
edit_rect.position -= line_sb->get_offset(); edit_rect.position -= line_sb->get_offset();
edit_rect.size += line_sb->get_minimum_size(); edit_rect.size += line_sb->get_minimum_size();
name_edit->set_global_position(state_machine_draw->get_global_transform().xform(edit_rect.position)); name_edit_popup->set_position(state_machine_draw->get_screen_transform().xform(edit_rect.position));
name_edit->set_size(edit_rect.size); name_edit_popup->set_size(edit_rect.size);
name_edit->set_text(node_rects[i].node_name); name_edit->set_text(node_rects[i].node_name);
#ifndef _MSC_VER name_edit_popup->popup();
#warning no more show modal, so it must replaced by a popup
#endif
//name_edit->show_modal();
name_edit->show();
name_edit->grab_focus(); name_edit->grab_focus();
name_edit->select_all(); name_edit->select_all();
@ -1114,7 +1110,7 @@ void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) {
undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_do_method(this, "_update_graph");
undo_redo->add_undo_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph");
undo_redo->commit_action(); undo_redo->commit_action();
name_edit->hide(); name_edit_popup->hide();
updating = false; updating = false;
state_machine_draw->update(); state_machine_draw->update();
@ -1361,12 +1357,14 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
animations_menu->set_name("animations"); animations_menu->set_name("animations");
animations_menu->connect("index_pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_add_animation_type)); animations_menu->connect("index_pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_add_animation_type));
name_edit_popup = memnew(Popup);
add_child(name_edit_popup);
name_edit = memnew(LineEdit); name_edit = memnew(LineEdit);
state_machine_draw->add_child(name_edit); name_edit_popup->add_child(name_edit);
name_edit->hide(); name_edit->set_anchors_and_margins_preset(PRESET_WIDE);
name_edit_popup->add_child(name_edit);
name_edit->connect("text_entered", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited)); name_edit->connect("text_entered", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited));
name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out)); name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out));
name_edit->set_as_toplevel(true);
open_file = memnew(EditorFileDialog); open_file = memnew(EditorFileDialog);
add_child(open_file); add_child(open_file);

View File

@ -50,6 +50,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
ToolButton *tool_select; ToolButton *tool_select;
ToolButton *tool_create; ToolButton *tool_create;
ToolButton *tool_connect; ToolButton *tool_connect;
Popup *name_edit_popup;
LineEdit *name_edit; LineEdit *name_edit;
HBoxContainer *tool_erase_hb; HBoxContainer *tool_erase_hb;

View File

@ -563,8 +563,12 @@ Point2i DisplayServerX11::screen_get_position(int p_screen) const {
return position; return position;
} }
Size2i DisplayServerX11::screen_get_size(int p_screen) const {
Size2i DisplayServerX11::screen_get_size(int p_screen) const {
return screen_get_usable_rect(p_screen).size;
}
Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) { if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@ -574,16 +578,17 @@ Size2i DisplayServerX11::screen_get_size(int p_screen) const {
// Using Xinerama Extension // Using Xinerama Extension
int event_base, error_base; int event_base, error_base;
const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
if (!ext_okay) return Size2i(0, 0); if (!ext_okay) return Rect2i(0, 0, 0, 0);
int count; int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
if (p_screen >= count) return Size2i(0, 0); if (p_screen >= count) return Rect2i(0, 0, 0, 0);
Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height); Rect2i rect = Rect2i(xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height);
XFree(xsi); XFree(xsi);
return size; return rect;
} }
int DisplayServerX11::screen_get_dpi(int p_screen) const { int DisplayServerX11::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_

View File

@ -259,6 +259,7 @@ public:
virtual int get_screen_count() const; virtual int get_screen_count() const;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;

View File

@ -125,7 +125,10 @@ void DisplayServerWindows::mouse_warp_to_position(const Point2i &p_to) {
} }
} }
Point2i DisplayServerWindows::mouse_get_position() const { Point2i DisplayServerWindows::mouse_get_position() const {
return Point2(old_x, old_y); POINT p;
GetCursorPos(&p);
return Point2i(p.x, p.y);
//return Point2(old_x, old_y);
} }
int DisplayServerWindows::mouse_get_button_state() const { int DisplayServerWindows::mouse_get_button_state() const {
return last_button_state; return last_button_state;
@ -280,6 +283,12 @@ typedef struct {
Size2 size; Size2 size;
} EnumSizeData; } EnumSizeData;
typedef struct {
int count;
int screen;
Rect2i rect;
} EnumRectData;
static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumSizeData *data = (EnumSizeData *)dwData; EnumSizeData *data = (EnumSizeData *)dwData;
@ -301,6 +310,34 @@ Size2i DisplayServerWindows::screen_get_size(int p_screen) const {
return data.size; return data.size;
} }
static BOOL CALLBACK _MonitorEnumProcUsableSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumRectData *data = (EnumRectData *)dwData;
if (data->count == data->screen) {
MONITORINFO minfo;
zeromem(&minfo, sizeof(MONITORINFO));
minfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfoA(hMonitor, &minfo);
data->rect.position.x = minfo.rcWork.left;
data->rect.position.y = minfo.rcWork.top;
data->rect.size.x = minfo.rcWork.right - minfo.rcWork.left;
data->rect.size.y = minfo.rcWork.bottom - minfo.rcWork.top;
}
data->count++;
return TRUE;
}
Rect2i DisplayServerWindows::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumRectData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Rect2i() };
EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcUsableSize, (LPARAM)&data);
return data.rect;
}
typedef struct { typedef struct {
int count; int count;
int screen; int screen;
@ -691,6 +728,7 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
wd.width = w; wd.width = w;
wd.height = h; wd.height = h;
#if defined(VULKAN_ENABLED) #if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") { if (rendering_driver == "vulkan") {
context_vulkan->window_resize(p_window, w, h); context_vulkan->window_resize(p_window, w, h);
@ -2232,8 +2270,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_MOVE: { case WM_MOVE: {
if (!IsIconic(windows[window_id].hWnd)) { if (!IsIconic(windows[window_id].hWnd)) {
int x = LOWORD(lParam); int x = int16_t(LOWORD(lParam));
int y = HIWORD(lParam); int y = int16_t(HIWORD(lParam));
windows[window_id].last_pos = Point2(x, y); windows[window_id].last_pos = Point2(x, y);
if (!windows[window_id].rect_changed_callback.is_null()) { if (!windows[window_id].rect_changed_callback.is_null()) {

View File

@ -280,6 +280,7 @@ public:
virtual int get_screen_count() const; virtual int get_screen_count() const;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;

View File

@ -247,6 +247,9 @@ void ColorPicker::_update_color(bool p_update_sliders) {
} }
void ColorPicker::_update_presets() { 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; presets_per_row = 10;
Size2 size = bt_add_preset->get_size(); 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))); 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() { void ColorPickerButton::pressed() {
_update_picker(); _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(); popup->popup();
picker->set_focus_on_line_edit(); picker->set_focus_on_line_edit();
} }
@ -961,7 +988,9 @@ PopupPanel *ColorPickerButton::get_popup() {
void ColorPickerButton::_update_picker() { void ColorPickerButton::_update_picker() {
if (!picker) { if (!picker) {
popup = memnew(PopupPanel); popup = memnew(PopupPanel);
popup->set_wrap_controls(true);
picker = memnew(ColorPicker); picker = memnew(ColorPicker);
picker->set_anchors_and_margins_preset(PRESET_WIDE);
popup->add_child(picker); popup->add_child(picker);
add_child(popup); add_child(popup);
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed)); picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));

View File

@ -625,7 +625,7 @@ void Control::_notification(int p_notification) {
get_viewport()->_gui_hid_control(this); get_viewport()->_gui_hid_control(this);
//remove key focus //remove key focus
//remove modalness
} else { } else {
data.minimum_size_valid = false; data.minimum_size_valid = false;
_size_changed(); _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; 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 if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated
return; return;

View File

@ -63,6 +63,7 @@ void MenuButton::pressed() {
popup->set_size(Size2(size.width, 0)); popup->set_size(Size2(size.width, 0));
popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size())); popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size()));
popup->take_mouse_focus();
popup->popup(); popup->popup();
} }

View File

@ -42,6 +42,7 @@ void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
} }
void Popup::_parent_focused() { void Popup::_parent_focused() {
_close_pressed(); _close_pressed();
} }
void Popup::_notification(int p_what) { void Popup::_notification(int p_what) {
@ -72,6 +73,7 @@ void Popup::_notification(int p_what) {
} break; } break;
case NOTIFICATION_WM_CLOSE_REQUEST: { case NOTIFICATION_WM_CLOSE_REQUEST: {
_close_pressed(); _close_pressed();
} break; } break;
} }
} }
@ -101,6 +103,35 @@ void Popup::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_hide")); 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() { Popup::Popup() {
parent_visible = nullptr; parent_visible = nullptr;
@ -166,7 +197,9 @@ void PopupPanel::_update_child_rects() {
void PopupPanel::_notification(int p_what) { 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")); panel->add_theme_style_override("panel", get_theme_stylebox("panel", "PopupPanel"));
_update_child_rects(); _update_child_rects();

View File

@ -41,9 +41,11 @@ class Popup : public Window {
void _input_from_window(const Ref<InputEvent> &p_event); void _input_from_window(const Ref<InputEvent> &p_event);
void _parent_focused(); void _parent_focused();
void _close_pressed();
protected: protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const;
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();

View File

@ -185,6 +185,9 @@ void PopupMenu::_activate_submenu(int over) {
void PopupMenu::_submenu_timeout() { void PopupMenu::_submenu_timeout() {
//if (!has_focus()) {
// return; //do not activate if not has focus
//}
if (mouse_over == submenu_over) if (mouse_over == submenu_over)
_activate_submenu(mouse_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"); int vseparation = get_theme_constant("vseparation");
Ref<Font> font = get_theme_font("font"); 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) { if (dy > 0) {
const float global_top = get_position().y; 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); dy = MIN(dy, limit);
} else if (dy < 0) { } else if (dy < 0) {
const float global_bottom = get_position().y + get_size().y; 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; const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0;
dy = -MIN(-dy, limit); dy = -MIN(-dy, limit);
} }
if (dy == 0) {
return;
}
set_position(get_position() + Vector2(0, dy)); set_position(get_position() + Vector2(0, dy));
Ref<InputEventMouseMotion> ie; Ref<InputEventMouseMotion> ie;
@ -295,15 +305,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
case BUTTON_WHEEL_DOWN: { 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; } break;
case BUTTON_WHEEL_UP: { case BUTTON_WHEEL_UP: {
if (get_position().y < 0) { _scroll(b->get_factor(), b->get_position());
_scroll(b->get_factor(), b->get_position());
}
} break; } break;
default: { default: {
// Allow activating item by releasing the LMB or any that was down when the popup appeared // 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()) { 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())) { if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
call_deferred("hide");
_close_pressed();
return; return;
} }
} }
@ -382,9 +389,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventPanGesture> pan_gesture = p_event; Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) { 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; Ref<InputEventKey> k = p_event;
@ -578,7 +583,7 @@ void PopupMenu::_notification(int p_what) {
} break; } break;
case NOTIFICATION_WM_MOUSE_ENTER: { case NOTIFICATION_WM_MOUSE_ENTER: {
grab_focus(); //grab_focus();
} break; } break;
case NOTIFICATION_WM_MOUSE_EXIT: { case NOTIFICATION_WM_MOUSE_EXIT: {
@ -594,6 +599,21 @@ void PopupMenu::_notification(int p_what) {
} break; } break;
case NOTIFICATION_WM_SIZE_CHANGED: { 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; } break;
case NOTIFICATION_VISIBILITY_CHANGED: { case NOTIFICATION_VISIBILITY_CHANGED: {
@ -617,6 +637,12 @@ void PopupMenu::_notification(int p_what) {
pm->hide(); pm->hide();
} }
set_process_internal(false);
} else {
if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
set_process_internal(true);
}
} }
} break; } break;
} }
@ -1366,6 +1392,14 @@ void PopupMenu::clear_autohide_areas() {
autohide_areas.clear(); 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() { void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input); ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input);
@ -1473,7 +1507,7 @@ PopupMenu::PopupMenu() {
add_child(control); add_child(control);
control->set_anchors_and_margins_preset(Control::PRESET_WIDE); 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)); control->connect("draw", callable_mp(this, &PopupMenu::_draw));
mouse_over = -1; mouse_over = -1;

View File

@ -215,6 +215,8 @@ public:
virtual void popup(const Rect2 &p_bounds = Rect2()); virtual void popup(const Rect2 &p_bounds = Rect2());
void take_mouse_focus();
PopupMenu(); PopupMenu();
~PopupMenu(); ~PopupMenu();
}; };

View File

@ -38,6 +38,8 @@
#include "core/project_settings.h" #include "core/project_settings.h"
#include "scene/main/window.h" #include "scene/main/window.h"
#include "box_container.h"
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
#include "editor/editor_scale.h" #include "editor/editor_scale.h"
#endif #endif
@ -2056,13 +2058,12 @@ void Tree::_text_editor_modal_close() {
if (value_editor->has_point(value_editor->get_local_mouse_position())) if (value_editor->has_point(value_editor->get_local_mouse_position()))
return; 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(); popup_editor->hide();
value_editor->hide();
if (!popup_edited_item) if (!popup_edited_item)
return; return;
@ -2806,22 +2807,22 @@ bool Tree::edit_selected() {
} else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) { } 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); 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; cache.text_editor_position = textedpos;
text_editor->set_position(textedpos); popup_rect.position = textedpos;
text_editor->set_size(rect.size); popup_rect.size = rect.size;
text_editor->clear(); 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->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::range_step_decimals(c.step)));
text_editor->select_all(); text_editor->select_all();
if (c.mode == TreeItem::CELL_MODE_RANGE) { if (c.mode == TreeItem::CELL_MODE_RANGE) {
value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height)); popup_rect.size.y += value_editor->get_minimum_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
value_editor->show(); value_editor->show();
updating_value_editor = true; updating_value_editor = true;
value_editor->set_min(c.min); value_editor->set_min(c.min);
@ -2830,12 +2831,17 @@ bool Tree::edit_selected() {
value_editor->set_value(c.val); value_editor->set_value(c.val);
value_editor->set_exp_ratio(c.expr); value_editor->set_exp_ratio(c.expr);
updating_value_editor = false; updating_value_editor = false;
} else {
value_editor->hide();
} }
#ifndef _MSC_VER
#warning show modal no longer works, need to replace by a popup popup_editor->set_position(popup_rect.position);
#endif popup_editor->set_size(popup_rect.size);
text_editor->show(); popup_editor->popup();
popup_editor->child_controls_changed();
text_editor->grab_focus(); text_editor->grab_focus();
return true; return true;
} }
@ -4026,13 +4032,22 @@ Tree::Tree() {
popup_menu->hide(); popup_menu->hide();
add_child(popup_menu); add_child(popup_menu);
// popup_menu->set_as_toplevel(true); // 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); text_editor = memnew(LineEdit);
add_child(text_editor); popup_editor_vb->add_child(text_editor);
text_editor->set_as_toplevel(true); text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
text_editor->hide(); text_editor->set_h_size_flags(SIZE_EXPAND_FILL);
value_editor = memnew(HSlider); value_editor = memnew(HSlider);
add_child(value_editor); value_editor->set_v_size_flags(SIZE_EXPAND_FILL);
value_editor->set_as_toplevel(true); value_editor->set_h_size_flags(SIZE_EXPAND_FILL);
popup_editor_vb->add_child(value_editor);
value_editor->hide(); value_editor->hide();
h_scroll = memnew(HScrollBar); h_scroll = memnew(HScrollBar);
@ -4047,13 +4062,11 @@ Tree::Tree() {
h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved)); h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
v_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("text_entered", callable_mp(this, &Tree::_text_editor_enter));
text_editor->connect("modal_closed", callable_mp(this, &Tree::_text_editor_modal_close)); popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_modal_close));
popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select)); 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->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); set_notify_transform(true);
updating_value_editor = false; updating_value_editor = false;

View File

@ -290,6 +290,8 @@ public:
VARIANT_ENUM_CAST(TreeItem::TreeCellMode); VARIANT_ENUM_CAST(TreeItem::TreeCellMode);
VARIANT_ENUM_CAST(TreeItem::TextAlign); VARIANT_ENUM_CAST(TreeItem::TextAlign);
class VBoxContainer;
class Tree : public Control { class Tree : public Control {
GDCLASS(Tree, Control); GDCLASS(Tree, Control);
@ -359,6 +361,10 @@ private:
}; };
bool show_column_titles; bool show_column_titles;
VBoxContainer *popup_editor_vb;
PopupPanel *popup_editor;
LineEdit *text_editor; LineEdit *text_editor;
HSlider *value_editor; HSlider *value_editor;
bool updating_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); 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); 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); 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 _text_editor_modal_close();
void value_editor_changed(double p_value); void value_editor_changed(double p_value);

View File

@ -191,6 +191,7 @@ Viewport::GUI::GUI() {
dragging = false; dragging = false;
mouse_focus = NULL; mouse_focus = NULL;
forced_mouse_focus = false;
mouse_click_grabber = NULL; mouse_click_grabber = NULL;
mouse_focus_mask = 0; mouse_focus_mask = 0;
key_focus = NULL; key_focus = NULL;
@ -595,6 +596,7 @@ void Viewport::_notification(int p_what) {
if (!has_mouse_event) { if (!has_mouse_event) {
Ref<InputEventMouseMotion> mm; Ref<InputEventMouseMotion> mm;
mm.instance(); mm.instance();
mm->set_device(InputEvent::DEVICE_ID_INTERNAL); mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos); mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos); mm->set_position(physics_last_mousepos);
@ -847,8 +849,7 @@ void Viewport::_notification(int p_what) {
_drop_physics_mouseover(); _drop_physics_mouseover();
if (gui.mouse_focus) { if (gui.mouse_focus && !gui.forced_mouse_focus) {
//if mouse is being pressed, send a release event
_drop_mouse_focus(); _drop_mouse_focus();
} }
} break; } break;
@ -1107,7 +1108,9 @@ void Viewport::_camera_set(Camera *p_camera) {
if (camera) { if (camera) {
camera->notification(Camera::NOTIFICATION_LOST_CURRENT); camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
} }
camera = p_camera; camera = p_camera;
if (!camera_override) { if (!camera_override) {
if (camera) if (camera)
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_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 //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) { if (gui.mouse_focus_mask == 0) {
gui.mouse_focus = NULL; gui.mouse_focus = NULL;
gui.forced_mouse_focus = false;
} }
if (mouse_focus && mouse_focus->can_process()) { 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) { if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = NULL; gui.mouse_focus = NULL;
gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0; gui.mouse_focus_mask = 0;
break; break;
} else { } else {
@ -2427,6 +2432,7 @@ void Viewport::_gui_remove_control(Control *p_control) {
if (gui.mouse_focus == p_control) { if (gui.mouse_focus == p_control) {
gui.mouse_focus = NULL; gui.mouse_focus = NULL;
gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0; gui.mouse_focus_mask = 0;
} }
if (gui.last_mouse_focus == p_control) { if (gui.last_mouse_focus == p_control) {
@ -2481,6 +2487,7 @@ void Viewport::_drop_mouse_focus() {
Control *c = gui.mouse_focus; Control *c = gui.mouse_focus;
int mask = gui.mouse_focus_mask; int mask = gui.mouse_focus_mask;
gui.mouse_focus = NULL; gui.mouse_focus = NULL;
gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0; gui.mouse_focus_mask = 0;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -3234,6 +3241,22 @@ bool Viewport::is_embedding_subwindows() const {
return gui.embed_subwindows_hint; 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() { void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d); 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.canvas_sort_index = 0;
gui.roots_order_dirty = false; gui.roots_order_dirty = false;
gui.mouse_focus = NULL; gui.mouse_focus = NULL;
gui.forced_mouse_focus = false;
gui.last_mouse_focus = NULL; gui.last_mouse_focus = NULL;
gui.subwindow_focused = nullptr; gui.subwindow_focused = nullptr;
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;

View File

@ -302,6 +302,7 @@ private:
struct GUI { struct GUI {
// info used when this is a window // info used when this is a window
bool forced_mouse_focus; //used for menu buttons
bool key_event_accepted; bool key_event_accepted;
Control *mouse_focus; Control *mouse_focus;
Control *last_mouse_focus; Control *last_mouse_focus;
@ -555,6 +556,9 @@ public:
bool is_embedding_subwindows() const; bool is_embedding_subwindows() const;
Viewport *get_parent_viewport() const; Viewport *get_parent_viewport() const;
void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
Viewport(); Viewport();
~Viewport(); ~Viewport();
}; };

View File

@ -35,6 +35,7 @@
#include "scene/gui/control.h" #include "scene/gui/control.h"
#include "scene/resources/dynamic_font.h" #include "scene/resources/dynamic_font.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
void Window::set_title(const String &p_title) { void Window::set_title(const String &p_title) {
title = p_title; title = p_title;
@ -207,8 +208,8 @@ void Window::set_ime_position(const Point2i &p_pos) {
bool Window::is_embedded() const { bool Window::is_embedded() const {
ERR_FAIL_COND_V(!is_inside_tree(), false); 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() { void Window::_make_window() {
@ -1027,6 +1028,12 @@ void Window::popup(const Rect2 &p_screen_rect) {
set_size(p_screen_rect.size); 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_transient(true);
set_visible(true); set_visible(true);
_post_popup(); _post_popup();
@ -1049,6 +1056,24 @@ bool Window::has_focus() const {
return focused; 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) { void Window::add_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(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_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("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::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");

View File

@ -108,8 +108,6 @@ private:
void _propagate_window_notification(Node *p_node, int p_notification); void _propagate_window_notification(Node *p_node, int p_notification);
virtual DisplayServer::WindowID get_window_id() const;
void _update_window_callbacks(); void _update_window_callbacks();
void _clear_transient(); void _clear_transient();
@ -123,8 +121,6 @@ private:
Control *theme_owner = nullptr; Control *theme_owner = nullptr;
Window *theme_owner_window = nullptr; Window *theme_owner_window = nullptr;
Viewport *_get_embedder() const;
Viewport *embedder = nullptr; Viewport *embedder = nullptr;
friend class Viewport; //friend back, can call the methods below friend class Viewport; //friend back, can call the methods below
@ -136,6 +132,10 @@ private:
void _event_callback(DisplayServer::WindowEvent p_event); void _event_callback(DisplayServer::WindowEvent p_event);
protected: protected:
Viewport *_get_embedder() const;
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
virtual void _post_popup() {} virtual void _post_popup() {}
virtual Size2 _get_contents_minimum_size() const; virtual Size2 _get_contents_minimum_size() const;
static void _bind_methods(); static void _bind_methods();
@ -234,6 +234,8 @@ public:
void grab_focus(); void grab_focus();
bool has_focus() const; 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<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<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; 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; bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
Rect2i get_parent_rect() const; Rect2i get_parent_rect() const;
virtual DisplayServer::WindowID get_window_id() const;
Window(); Window();
~Window(); ~Window();

View File

@ -252,6 +252,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count); ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count);
ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_usable_rect", "screen"), &DisplayServer::screen_get_usable_rect, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW));

View File

@ -140,6 +140,7 @@ public:
virtual int get_screen_count() const = 0; virtual int get_screen_count() const = 0;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
enum ScreenOrientation { enum ScreenOrientation {