From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Tobias Bading Newsgroups: gmane.emacs.devel Subject: The rabbit hole that is HiDPI... (empty menus / bug#31223 et al) Date: Tue, 26 Nov 2019 20:13:21 +0100 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="257689"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.1.2 To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Nov 26 20:22:28 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iZgPs-0014hg-2U for ged-emacs-devel@m.gmane.org; Tue, 26 Nov 2019 20:22:28 +0100 Original-Received: from localhost ([::1]:58272 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZgPq-0001ms-DD for ged-emacs-devel@m.gmane.org; Tue, 26 Nov 2019 14:22:26 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33336) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZgHD-0000E9-Jx for emacs-devel@gnu.org; Tue, 26 Nov 2019 14:13:34 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iZgH9-0002eM-Nr for emacs-devel@gnu.org; Tue, 26 Nov 2019 14:13:29 -0500 Original-Received: from mout.web.de ([212.227.15.4]:37549) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iZgH6-0002c5-JQ for emacs-devel@gnu.org; Tue, 26 Nov 2019 14:13:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1574795602; bh=0tbG10EghYVKtj3khnJTlAyYqTLVNngHw9oJkUdi3FU=; h=X-UI-Sender-Class:To:From:Subject:Date; b=mBs3XLiMdy7Sg83f6uZp1wAq+ENRXbvlkgCPmFYNYt0J5TxXhlh6RKWHB+58cBUVb STGz/0OEpbq9xy2vcPfEmQ9pF9Q/9v9qJzelhWKynGHJ7xJN4Fa0VsATFe8FI7I/Co ln24XXF/GPdTbPvFo+X3IFoeXSAPFWnqbezGIbt4= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Original-Received: from [192.168.2.103] ([84.143.156.184]) by smtp.web.de (mrweb003 [213.165.67.108]) with ESMTPSA (Nemesis) id 0MIN5j-1iWeXW3cZL-0049qw for ; Tue, 26 Nov 2019 20:13:21 +0100 Content-Language: en-US X-Provags-ID: V03:K1:nNMLR49hzp07esaXt9YIA8Zop5n1GclkDzLWmWg1tw1X20Nj/xv lMcjGQCX6rAIHZ+RTlCrEajFF3Nj2IjF1HHYQLiz4vPZPYvY6X8nLebCTU9gtLxfChvH707 OYEPTO19lgNhMUYjJkJ7t1JTK1TeBWFNG/FaATcbCrMfSiG3ZyzhhsEKTAcybwTtHx8ktkz /hlDaPBj9W1VUTlFSvqiw== X-UI-Out-Filterresults: notjunk:1;V03:K0:+M3GmBwNm10=:k9vrFRKNHoA+27ufvDUdi8 7PyL08gW0XVheouWkZruWZyNjgSqpQtcNS5AUOtaXoDarke0llmKz16uKTkQKukAvuyUK/OiT 2PdhGAJy0mRyOtP+i4LKKRTe5EH6xBqVDV7Q55hIviNU3fj/EGJbhdPTNR+/DS8IQ3/9cqnC3 bVz7ch3T1OpNsQDh2nIDyMHjtfCPyUTziuUCmZIATXMIYvPwZ29PImLe2bpzr2oKHYdExz8FK V/wiEVHhQTNfcfBqTgBm+qcpQI7ir9WHj4ukMWoqthNuoqAmcoaZXN3jNJ+Tukydh5hjjPme3 245Aksys4xGjOcaW6lna5xPKsM3+HoMtYoT0gF2aXt3qCm3XHU0Xi5ZEENxfBYnOeUk7uWn7+ /3zomkeUGErlewnw33gVaEcI0uZguBwwIcje2SZOZF1Wu1iZfL8chguAesa5hNQcmriOOR3U2 2O146uvm2MHyjSIo+TEgUK3vfIwlqQ0WvPX1EKSTObl0n4cOv3XDhQHKGoLR8OozYkPMDONbr ktJwYO8Xcu/rI+zeGwO+JU5y/ZuuHvGyXdP+2Bta71pKylzQBYDu6vau/NzNbpsb6nKfN6hx2 wlC21NNgYcGhqkqFrmE+EpW7+A3RoicH9SuyBTwtAQ4lHonxKL+XolmWzN22OHv4eO3ibqhNE 1SFu93qIqv21nI4mVwbA1sw073EoFHNxkHltrLfRJ1mFJrhM9mV1V2SrBL2H1WaGwEc5ot49o 0iOjOcyE+vHvbprZzU4FGS7EFC5AlKVBx9L+6KLdu2tyZHL68XasEJPqCtwyw2EUJJnxgstb X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.4 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:242745 Archived-At: Hi-ho. A few days ago I built Emacs on a new GNU/Linux box at home, based on the emacs-26 branch that works fine at the office. Unfortunately, the new Emacs at home shows a bug I haven't seen before, but others have by the looks of it: there's bug#31223 (merged with bug#23672 and bug#28106) as well as Ubuntu bug https://bugs.launchpad.net/ubuntu/+source/emacs25/+bug/1695228. Short summary of the bug: Sometimes menus of the menu bar are completely empty if a menu is opened by a mouse click. The 'Buffers' menu may be incorrect as well. (When the menu bar is opened by pressing the F10 key, all menus are fine and stay that way for a while.) For me an easy recipe to reproduce this is (with GTK3 on a 4K monitor): - emacs -Q - C-x C-f RET - Now you're in dired-mode. The menus 'Mark', 'Regexp', 'Immediate' and 'Subdir' are empty when opened with the mouse. (OTOH, F10 opens the first menu and all menus are fine afterwards.) What I've figured out so far: Switching to the dired buffer calls set_frame_menubar() in xmenu.c with deep_p =3D=3D false, which calls xg_modify_menubar_widgets(). Due to the deep_p =3D=3D false the latter doesn't (re)build the entire GTK menu tree, just the top level items in the menu bar itself, with empty menus for new items. When a menu bar item is then clicked, nothing fills the menus prior to GTK popping them up, which of course explains the bug. If you press F10 on the other hand, x-menu-bar-open-internal() calls set_frame_menubar() with deep_p =3D=3D true and all is good in the world. = So an easy fix is to ignore argument deep_p and always "go deep" in set_frame_menubar(). That indeed seems to work fine, but doesn't answer why the heck this bug never bit me at work, but some people out there already got bitten, some even years ago it seems. So I dug a little deeper... When a menu item is clicked, handle_one_xevent() is trying to figure out whether the ButtonPress was meant for the menu bar by calling x_menubar_window_to_frame(dpyinfo, event), which calls xg_event_is_for_menubar() for every frame, which performs its "magic" trying to determine whether the event's mouse coordinates are within the bounding rectangle of a child of the GTK menu bar widget. If everything goes according to plan (i.e. xg_event_is_for_menubar() returns true and x_menubar_window_to_frame() in turn the frame containing the menu bar) handle_one_xevent() saves the ButtonPress X11 event in the frame's output_data.x->saved_menu_event, relays a MENU_BAR_ACTIVATE_EVENT to kbd_buffer_store_buffered_event() and lastly drops the ButtonPress event for the time being. A bit later kbd_buffer_get_event() picks up the MENU_BAR_ACTIVATE_EVENT and calls x_activate_menubar(), which calls set_frame_menubar() with deep_p =3D=3D true and thus rebuilds the entire GTK menu bar. The final step is a XPutBackEvent() for the saved_menu_event so that the (hopefully correct) menu may pop up asap. This entire plan hinges on the "magic" in xg_event_is_for_menubar(), and that's where the shit starts to hit the fan when HiDPI comes into play. On my GNU/Linux system with a MATE desktop, a 4K monitor and the 'window scaling factor' set to 'HiDPI' (2x) in the 'MATE Tweak' tool, FRAME_MENUBAR_HEIGHT(f) seems to return only half of the actual menu bar height in pixel. So the first way to lose your magic is to click into the lower half of a menu item. If you click into the upper half, no luck either, because now gtk_widget_intersect() fails due to bounding rectangles (GtkAllocation) which seem to have halved sizes as well. And then there's the next "event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)" in handle_one_xevent() just around the corner... After all that digging, the initial easy "always go deep" fix in set_frame_menubar() doesn't look so bad anymore... ;-) But seriously... what would be the proper way to deal with HiDPI in Emacs? Has anyone done any work on this? I don't have much experience with GTK or HiDPI solutions on GNU/Linux in general. From what I've debugged so far it seems that GTK works similar to CSS, with some form of abstract pixels, which are mapped to 2x2 device pixels in my case. Since the low-level X11 APIs and events still seem to use actual device pixels, would it make sense to look for the source of the halved values returned by FRAME_MENUBAR_HEIGHT(f) et al and multiply these by two in my case? I'll keep digging in the Emacs sources and the GTK documentation (or sources) to learn a bit more... See you around, Tobias