Subject: bug#18429: bug#21348: 25.0.50; Screen scaling factor >=2 causes menus, tooltips to display in the wrong place

From: Ryan Prior <[email-masked]>
Date: Mon, 12 Oct 2015 16:10:52 -0500

I wrote a patch to fix the issues from bugs #20619 and #21348 for GTK
users. When the functions to display a tooltip or menu are called, Emacs
scales coordinates using a factor from GTK. In my testing, non-GTK
tooltips and menus weren't broken, so the problem is specific to GTK and
the patch has no effect on non-GTK builds. Michael Droettboom, will you
apply this patch and verify that the menus are now placed correctly on
your system?

There's something else entirely going on with the scroll bars in bug
#21469, this patch doesn't address that at all. I had never noticed that
hidpi bug because I dont use scroll bars, but I can confirm that turning
on scroll bars causes strange behavior. It might be possible that a
similar scaling strategy for scroll bar placement could provide a fix,
so I CC'd that bug. I will investigate that more as time allows.

The final hidpi bug I looked at, #18429, I am unable to
reproduce. Perhaps it is not applicable to my platform - I'm on Ubuntu
Trusty, while the reporter is on Utopic. Anders Kaseorg, can you still
reproduce the bug?

Finally, there's the open question of why the coordinates these
functions are getting are doubled in the first place. Given my limited
familiarity with Emacs internals, I have not made any progress on that
question. Perhaps there are few enough places where these
sometimes-inflated coordinates are passed into GTK that we can just
scale them everywhere and call it good enough. Or perhaps there's a more
robust solution somewhere else - if anybody can help explain this to me,
I would be appreciative.

>From 3addec3d592b9fc81e2a1503a37ccb078f03118c Mon Sep 17 00:00:00 2001
From: Ryan Prior <[email-masked]>
Date: Fri, 2 Oct 2015 19:22:28 -0500
Subject: [PATCH] Adjust overlay position on hidpi screens

Scale the display positions of tooltips and menus according to the
window scaling factor provided by GTK3, if it is available (Bug#21348).
* src/gtkutil.h (xg_scale_x_y_with_widget):
* src/gtkutil.c (xg_scale_x_y_with_widget):
Fuction finds scaling factor and performs scaling.
(xg_show_tooltip): Divide position of tooltip by scaling factor.
* src/xmenu.c (create_and_show_popup_menu) [HAVE_GTK3]:
Divide position of native GTK3 menus by scaling factor.
---
 src/gtkutil.c | 14 ++++++++++++++
 src/gtkutil.h |  4 ++++
 src/xmenu.c   |  6 ++++++
 3 files changed, 24 insertions(+)

diff --git a/src/gtkutil.c b/src/gtkutil.c
index 34e81b5..db80b2e 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -748,6 +748,7 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y)
   if (x->ttip_window)
     {
       block_input ();
+      xg_scale_x_y_with_widget(GTK_WIDGET(x->ttip_window), &root_x, &root_y);
       gtk_window_move (x->ttip_window, root_x, root_y);
       gtk_widget_show_all (GTK_WIDGET (x->ttip_window));
       unblock_input ();
@@ -3223,6 +3224,19 @@ xg_update_submenu (GtkWidget *submenu,
   return newsub;
 }
 
+/* Scale X and Y.
+   WIDGET the gtk widget from which to get the scaling factor */
+void
+xg_scale_x_y_with_widget (GtkWidget *widget,
+                          int *x,
+                          int *y)
+{
+  gint scale_factor = gtk_widget_get_scale_factor(widget);
+  if(x) *x /= scale_factor;
+  if(y) *y /= scale_factor;
+}
+
+
 /* Update the MENUBAR.
    F is the frame the menu bar belongs to.
    VAL describes the contents of the menu bar.
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 34338db..8db063a 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -96,6 +96,10 @@ extern GtkWidget *xg_create_widget (const char *type,
                                     GCallback deactivate_cb,
                                     GCallback highlight_cb);
 
+extern void xg_scale_x_y_with_widget (GtkWidget *widget,
+                                      int *x,
+                                      int *y);
+
 extern void xg_modify_menubar_widgets (GtkWidget *menubar,
                                        struct frame *f,
                                        struct _widget_value *val,
diff --git a/src/xmenu.c b/src/xmenu.c
index 192ed89..1b7bbb5 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1229,6 +1229,12 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
 
                              /* Child of win.  */
                              &dummy_window);
+#ifdef HAVE_GTK3
+      /* Use window scaling factor to adjust position for hidpi screens. */
+      xg_scale_x_y_with_widget(GTK_WIDGET(f->output_data.x->ttip_window),
+                               &x,
+                               &y);
+#endif
       unblock_input ();
       popup_x_y.x = x;
       popup_x_y.y = y;
-- 
2.6.1