Skip to content

Commit 798af97

Browse files
committed
Improve menu positioning on Linux with DPI scaling
Menu positioning now accounts for device pixel ratio for proper DPI scaling, uses gtk_window_get_position for better Wayland support, and adjusts coordinates based on window position and frame extents. This improves accuracy of menu placement across different display configurations.
1 parent f3c4ad7 commit 798af97

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

src/platform/linux/menu_linux.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -718,8 +718,7 @@ bool Menu::Open(const PositioningStrategy& strategy, Placement placement) {
718718
GdkRectangle frame_rectangle;
719719
gdk_window_get_frame_extents(gdk_window, &frame_rectangle);
720720

721-
// Get title bar height from GtkWindow
722-
int title_bar_height = 0;
721+
// Get GtkWindow for window position and title bar
723722
GtkWindow* gtk_window = nullptr;
724723
GList* toplevels = gtk_window_list_toplevels();
725724
for (GList* l = toplevels; l != nullptr; l = l->next) {
@@ -732,15 +731,39 @@ bool Menu::Open(const PositioningStrategy& strategy, Placement placement) {
732731
}
733732
g_list_free(toplevels);
734733

734+
// Get window position using gtk_window_get_position (works better on Wayland)
735+
gint window_x = 0, window_y = 0;
736+
if (gtk_window) {
737+
gtk_window_get_position(gtk_window, &window_x, &window_y);
738+
} else {
739+
// Fallback to gdk_window_get_origin if gtk_window not found
740+
gdk_window_get_origin(gdk_window, &window_x, &window_y);
741+
}
742+
743+
// Get title bar height from GtkWindow
744+
int title_bar_height = 0;
735745
if (gtk_window) {
736746
GtkWidget* titlebar = gtk_window_get_titlebar(gtk_window);
737747
if (titlebar) {
738748
title_bar_height = gtk_widget_get_allocated_height(titlebar);
739749
}
740750
}
741751

742-
rectangle.x = static_cast<int>(position.x - frame_rectangle.x);
743-
rectangle.y = static_cast<int>(position.y - frame_rectangle.y + title_bar_height);
752+
// Get device pixel ratio for DPI scaling
753+
double device_pixel_ratio = 1.0;
754+
GdkScreen* screen = gdk_window_get_screen(gdk_window);
755+
if (screen) {
756+
// Get scale factor (typically 1.0 for standard DPI, 2.0 for HiDPI)
757+
device_pixel_ratio = gdk_screen_get_resolution(screen) / 96.0;
758+
if (device_pixel_ratio <= 0.0) {
759+
device_pixel_ratio = 1.0;
760+
}
761+
}
762+
763+
// Convert content-relative coordinates to window-relative coordinates
764+
// Apply DPI scaling, then adjust for window position and frame extents
765+
rectangle.x = static_cast<int>((position.x * device_pixel_ratio) + window_x - frame_rectangle.x);
766+
rectangle.y = static_cast<int>((position.y * device_pixel_ratio) + window_y - frame_rectangle.y + title_bar_height);
744767
} else {
745768
// Relative to rectangle (no window) - use root window coordinates
746769
rectangle.x = static_cast<int>(position.x);

0 commit comments

Comments
 (0)