Repository: godotengine/godot (language: cpp)

Issue:
Popup menus broken when `content_scale_mode` is bigger then 1 and subwindows are not embedded
### Tested versions

- reproducable in 4.4 beta1
- not reproducable in 4.4 dev 7 or before

### System information

Windows 10

### Issue description

Working on applications (material maker in my case) you often want to allow scaling the window using the content_scale_factor AND allow using multiple native windows (so having embed subwindows off). Unfortunately at higher factors, popup menus (and option buttons, maybe more popups idk) don't function anymore. The lower parts of the popups does not receive input/clicks. Strangely enough the hover works fine, so I really have no clue what's going on.

### Steps to reproduce

Create a popup menu or option button with a couple of items. Change the content scale factor to 2, turn embed subwindows off. Then run the game and try selecting the last popup item.

### Minimal reproduction project (MRP)

[mrp_scalemenupopupbug.zip](https://github.com/user-attachments/files/18592487/mrp_scalemenupopupbug.zip)
Hope this helps.


Discussion / hints:
Okay, looks like this one is the most likely cause, but I have no idea tbh: https://github.com/godotengine/godot/issues/54030
Btw, it seems unlikely this will get fixed for 4.4, but one can always hope :). If there is something I could help with, let me know. 

I would certainly call this a regression unfortunately.
I'll bisect this bug.
Bisected to #91333, @YeldhamDev 

![Image](https://github.com/user-attachments/assets/29956588-c83a-43e9-af9d-128d3c01a1fd)

Fix patch:
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 94d7303ae504..cbba65e0088b 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -247,8 +247,14 @@ void PopupPanel::_input_from_window(const Ref<InputEvent> &p_event) {
 
 		Ref<InputEventMouseButton> b = p_event;
 		// Hide it if the shadows have been clicked.
-		if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::LEFT && !panel->get_global_rect().has_point(b->get_position())) {
-			_close_pressed();
+		if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::LEFT) {
+			Rect2 panel_area = panel->get_global_rect();
+			float win_scale = get_content_scale_factor();
+			panel_area.position *= win_scale;
+			panel_area.size *= win_scale;
+			if (!panel_area.has_point(b->get_position())) {
+				_close_pressed();
+			}
 		}
 	} else {
 		WARN_PRINT_ONCE("PopupPanel has received an invalid InputEvent. Consider filtering out invalid events.");
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 092a12bd1486..b6dc75754690 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -327,16 +327,17 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
 		item_clickable_area.size.width -= scroll_width;
 	}
 	float win_scale = get_content_scale_factor();
-	item_clickable_area.position.y = (item_clickable_area.position.y + theme_cache.panel_style->get_margin(SIDE_TOP)) * win_scale;
+	item_clickable_area.position.x += theme_cache.panel_style->get_margin(SIDE_LEFT);
+	item_clickable_area.position.y += theme_cache.panel_style->get_margin(SIDE_TOP);
+	item_clickable_area.position *= win_scale;
 	item_clickable_area.size.y -= theme_cache.panel_style->get_margin(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_BOTTOM);
 	item_clickable_area.size *= win_scale;
 
-	if (p_over.x < item_clickable_area.position.x || p_over.x >= item_clickable_area.position.x + item_clickable_area.size.width ||
-			p_over.y < item_clickable_area.position.y || p_over.y >= item_clickable_area.position.y + item_clickable_area.size.height) {
+	if (!item_clickable_area.has_point(p_over)) {
 		return -1;
 	}
 
-	float ofs = item_clickable_area.position.y + theme_cache.v_separation * 0.5;
+	float ofs = item_clickable_area.position.y + (float)theme_cache.v_separation * win_scale * 0.5;
 	for (int i = 0; i < items.size(); i++) {
 		ofs += i > 0 ? (float)theme_cache.v_separation * win_scale : (float)theme_cache.v_separation * win_scale * 0.5;
 		ofs += _get_item_height(i) * win_scale;
@@ -430,7 +431,7 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
 			this_rect.size.x, scaled_ofs_cache + scroll_offset + theme_cache.panel_style->get_margin(SIDE_TOP) * win_scale - theme_cache.v_separation / 2));
 
 	// If there is an area below the submenu item, add an autohide area there.
-	if (scaled_ofs_cache + scaled_height_cache + scroll_offset <= control->get_size().height) {
+	if (scaled_ofs_cache + scaled_height_cache + scroll_offset <= control->get_size().height * win_scale) {
 		const int from = scaled_ofs_cache + scaled_height_cache + scroll_offset + theme_cache.v_separation / 2;
 		submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
 	}
@@ -605,9 +606,13 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
 		}
 		item_clickable_area.size.width -= scroll_width;
 	}
-	item_clickable_area.position.y = (item_clickable_area.position.y + theme_cache.panel_style->get_margin(SIDE_TOP)) * get_content_scale_factor();
+
+	float win_scale = get_content_scale_factor();
+	item_clickable_area.position.x += theme_cache.panel_style->get_margin(SIDE_LEFT);
+	item_clickable_area.position.y += theme_cache.panel_style->get_margin(SIDE_TOP);
+	item_clickable_area.position *= win_scale;
 	item_clickable_area.size.y -= theme_cache.panel_style->get_margin(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_BOTTOM);
-	item_clickable_area.size *= get_content_scale_factor();
+	item_clickable_area.size *= win_scale;
 
 	Ref<InputEventMouseButton> b = p_event;
 
@@ -622,9 +627,14 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
 				is_scrolling = is_layout_rtl() ? b->get_position().x < item_clickable_area.position.x : b->get_position().x > item_clickable_area.size.width;
 
 				// Hide it if the shadows have been clicked.
-				if (get_flag(FLAG_POPUP) && !panel->get_global_rect().has_point(b->get_position())) {
-					_close_pressed();
-					return;
+				if (get_flag(FLAG_POPUP)) {
+					Rect2 panel_area = panel->get_global_rect();
+					panel_area.position *= win_scale;
+					panel_area.size *= win_scale;
+					if (!panel_area.has_point(b->get_position())) {
+						_close_pressed();
+						return;
+					}
 				}
 
 				if (!item_clickable_area.has_point(b->get_position())) {


Test patch: