raboof / notion

Tiling tabbed window manager
https://notionwm.net/
GNU Lesser General Public License v2.1
268 stars 63 forks source link

In Android Studio 4, top dropdown menus and context menu covers horizontally across the screen. #321

Open robinchew opened 3 years ago

robinchew commented 3 years ago

Here's a video of the behaviour. https://youtu.be/TbYoW7vxvpM

  1. The menus are all anchored at the bottom of the screen.
  2. The menus takes up the whole width of the screen, with all the extra width in black background colour.
  3. The context menu options are still selectable because the menu remains on mouse up. 3b. The top menus are not selectable because the menu disappears on mouse up.
  4. I cannot run xprop on the menu, you can see the output of xprop on the main window in video.
  5. Tried to add to cfg_kludges.lua the following, but has no effect:
    defwinprop{ 
    class = "jetbrains-studio", 
    acrobatic = true,
    transient_mode = "current"
    }
    defwinprop{ 
    class = "sun-awt-X11-XFramePeer", 
    acrobatic = true,
    transient_mode = "current"
    }

    It makes Android Studio 4 unusable unfortunately.

wilhelmy commented 3 years ago

I'm wondering if it's possible to use xdotool to obtain more information about these transient windows:

#!/usr/bin/env bash

pid=$(pgrep firefox) # insert pid of android studio here
ws=$(xdotool search --pid $pid)
while true; do
    wstmp=$(xdotool search --pid $pid)
    wsnew=$(diff <(echo "$ws") <(echo "$wstmp") | awk '/^>/ {print $2}')
    echo found windows: $wsnew
    for win in $wsnew; do
        xprop -id $win
    done
    ws=$wstmp
    sleep 0.5
done
robinchew commented 3 years ago

Hi your script fails because just running xdotool search --pid $pid of android studio will give no outputs, whereas there were outputs if it was a pid of firefox instead.

wilhelmy commented 3 years ago

That's odd. Does that mean that Android Studio starts submenus in a different process? I have no idea how to search for Android Studio windows since I don't use it myself. Feel free to play around with the xdotool arguments, if this doesn't work: xdotool search --onlyvisible '' 2>/dev/null In theory this should find all visible windows.

#!/usr/bin/env bash

search() {
    xdotool search --onlyvisible '' 2>/dev/null
}
ws=$(search)
while true; do
    wstmp=$(search)
    wsnew=$(diff <(echo "$ws") <(echo "$wstmp") | awk '/^>/ {print $2}')
    echo found windows: $wsnew
    for win in $wsnew; do
        xprop -id $win
    done
    ws=$wstmp
    sleep 0.5
done

It finds some false positives (such as notion's own WGroupWS), but better too many than too few...

robinchew commented 3 years ago

Awesome, I've modified your script as such:

#!/usr/bin/env bash

ws=$(xdotool search --onlyvisible --class 'jetbrains-studio')
while true; do
    wstmp=$(xdotool search --onlyvisible --class 'jetbrains-studio')
    wsnew=$(diff <(echo "$ws") <(echo "$wstmp") | awk '/^>/ {print $2}')
    echo found windows: $wsnew
    for win in $wsnew; do
        xprop -id $win
    done
    ws=$wstmp
    sleep 0.5
done

And I caught the following when I open a file menu or context menu.

WM_STATE(WM_STATE):
        window state: Normal
        icon window: 0x0
_NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 0, 0
_NET_WM_ALLOWED_ACTIONS(ATOM) = 
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG
_NET_WM_STATE(ATOM) = 
WM_HINTS(WM_HINTS):
        Client accepts input or input focus: False
        window id # of group leader: 0x220004e
WM_TRANSIENT_FOR(WINDOW): window id # 0x220004e
_NET_WM_PID(CARDINAL) = 70508
WM_CLIENT_MACHINE(STRING) = "silverstone"
WM_PROTOCOLS(ATOM): protocols  
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x3, 0x0, 0x0, 0x0, 0x0
WM_NORMAL_HINTS(WM_SIZE_HINTS):
        program specified location: 1081, 401
        program specified size: 305 by 434
        window gravity: NorthWest
WM_CLASS(STRING) = "sun-awt-X11-XWindowPeer", "jetbrains-studio"
WM_CLIENT_LEADER(WINDOW): window id # 0x220002f
_NET_WM_NAME(UTF8_STRING) = "win35"
WM_NAME(STRING) = "win35"
wilhelmy commented 3 years ago

Just wondering, does it work? When you opened the issue you mentioned class = "sun-awt-X11-XFramePeer", but this one has WM_CLASS(STRING) = "sun-awt-X11-XWindowPeer",

robinchew commented 3 years ago

You mean use kludges to fix it? I added the following:

defwinprop{ 
    class = "jetbrains-studio", 
    acrobatic = true,
    transient_mode = "current"
}
defwinprop{ 
    class = "sun-awt-X11-XFramePeer", 
    acrobatic = true,
    transient_mode = "current"
}

defwinprop{
    class = "sun-awt-X11-XWindowPeer",
    acrobatic = true,
    transient_mode = "current"
}

But there has been no change.

wilhelmy commented 3 years ago

After inspecting the source, there is a special case for _NET_WM_WINDOW_TYPE_DIALOG in cfg_notion.lua which seemingly defaults to false (at least it's set to false here but I don't remember setting it) and according to the comment might help and is commented out as true. You can inspect with notionflux(1) or the Lua prompt by evaluating print(ioncore.get()["window_dialog_float"]). Edit: I checked the code, it is initialized to ioncore_g.window_dialog_float=FALSE in C. Firefox's menus are _NET_WM_WINDOW_TYPE_POPUP_MENU. Whether or not globally handling that information is a good idea or should rather be a kludge ...not sure. The mysterious world of X11.

raboof commented 3 years ago

The menus are all anchored at the bottom of the screen. The menus takes up the whole width of the screen, with all the extra width in black background colour.

I can reproduce that

The context menu options are still selectable because the menu remains on mouse up. 3b. The top menus are not selectable because the menu disappears on mouse up.

Interesting, the top menus don't disappear on mouse up for me. But it obviously doesn't work well.

I'm wondering if it's possible to use xdotool to obtain more information about these transient windows

Neat! A trick I sometimes use is to save the output of xwininfo -root -tree and one with sleep 5 && xwininfo -root -tree to catch one with the dialog open, and then compare with vimdiff. This indeed suggests the dialog is ("sun-awt-X11-XWindowPeer" "jetbrains-studio")

AFAIK Android Studio is based in a large part on IntelliJ IDEA, which I use a lot and mostly works fine. For IntelliJ we do have some winprops, but I just tried without them and think they might no longer be relevant.

Looking at the IntelliJ IDEA menu's with xwinprop, however, they are ("jetbrains-idea-ce" "jetbrains-idea-ce") rather than sun-awt-X11-XWindowPeer - so apparently they are different in this regard - even though the winprops look pretty similar:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG
_NET_WM_STATE(ATOM) = _NET_WM_STATE_SKIP_TASKBAR
WM_HINTS(WM_HINTS):
        Client accepts input or input focus: False
        window id # of group leader: 0x2a00042
WM_TRANSIENT_FOR(WINDOW): window id # 0x2a00042
_NET_WM_PID(CARDINAL) = 2521983
WM_CLIENT_MACHINE(STRING) = "rigter"
WM_PROTOCOLS(ATOM): protocols  
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x3, 0x0, 0x0, 0x0, 0x0
WM_NORMAL_HINTS(WM_SIZE_HINTS):
        program specified location: 2272, 893
        program specified size: 607 by 782
        window gravity: NorthWest
WM_CLASS(STRING) = "jetbrains-idea-ce", "jetbrains-idea-ce"
WM_CLIENT_LEADER(WINDOW): window id # 0x2a00023
_NET_WM_NAME(UTF8_STRING) = "win10"
WM_NAME(STRING) = "win10"
wilhelmy commented 3 years ago

@raboof window_dialog_float = true in cfg_notion.lua makes no difference?

raboof commented 3 years ago

@raboof window_dialog_float = true in cfg_notion.lua makes no difference?

Ha, I didn't get that far into this thread, sorry :).

I can confirm setting window_dialog_float = true makes this work much more like it was intended, though it doesn't seem to work well in multi-monitor configurations...

Whether or not globally handling that information is a good idea or should rather be a kludge ...not sure.

I agree perhaps we should make this overridable at the kludge level... or lobby for android studio to take the same approach as IntelliJ IDEA ;).

robinchew commented 3 years ago

I have a 3 monitor setup. Setting the following in ~/.notion/default-session--0/cfg_notion.lua made no difference for me.

ioncore.set{
    window_dialog_float = true,
}
wilhelmy commented 3 years ago

FTR, [16:41] < Robin> Yes notion works fine with android studio 3

robinchew commented 3 years ago

Today I noticed my Android Studio 4's menus are all anchored to the top left. I'm assuming it's because of:

-- cfg_notion.lua
ioncore.set{
    window_dialog_float = true,
}

and I don't know why this has happened now instead of 2 days ago when I made the config change. That time I restarted Xorg and notion, and the menus were still taking up the whole width demonstrated in the video.

Although this change is an improvement, it's still a pain. For example clicking on File anchors the menu on the top left, then selecting New anchors the sub menu somewhere to the right. See screenshot

wilhelmy commented 3 years ago

@raboof Just wondering, in IntelliJ, are menus _NET_WM_WINDOW_TYPE_DIALOG or _NET_WM_WINDOW_TYPE_POPUP_MENU?

Firefox "Do you want to quit?" dialog has the same type as Android Studio's dropdown menus, just to confirm that this is what a dialog is in usual terms — which indicates to me that Android Studio really seems to be off here:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG

For illustration, here's some other software and values their dropdown menus have: Firefox:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_POPUP_MENU

Gimp:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DROPDOWN_MENU

GVim:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_POPUP_MENU

Libreoffice: my script fails to obtain information besides the window id. Oops :)

Qt software: VirtualBox, quasselclient-qt5, OpenSCAD (iirc those were buggy but I can't remember details):

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DROPDOWN_MENU, _NET_WM_WINDOW_TYPE_POPUP_MENU, _NET_WM_WINDOW_TYPE_NORMAL

Ultimaker Cura (PyQt5) — menu positions here also seem off:

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL

Seems like there is no consensus between toolkits/implementations on this issue, either, and we can't fix every single package that has a different way of rendering popups. Maybe honoring the window position these programs explicitly request through size hints is the way to go? Taking a wild guess here that we don't already, I know very little about how notion handles any of this.

WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
WM_NORMAL_HINTS(WM_SIZE_HINTS):
        user specified location: 1324, 92
        user specified size: 275 by 190
        window gravity: Static
raboof commented 3 years ago

@raboof Just wondering, in IntelliJ, are menus _NET_WM_WINDOW_TYPE_DIALOG or _NET_WM_WINDOW_TYPE_POPUP_MENU?

Just checked and it's really (though indeed oddly) _NET_WM_WINDOW_TYPE_DIALOG

wilhelmy commented 3 years ago

dwm seems to deal with it by always setting dialogs floating: https://git.suckless.org/dwm/file/dwm.c.html#l2015 Haven't checked what other tiling WM's do.

robinchew commented 3 years ago

So the problem came back again after messing with cfg_kludges.lua. So I don't know what combination of the following will cause what behaviour. But in any case, they are all difficult to work with:

-- cfg_kludges.lua
defwinprop{ 
    class = "jetbrains-studio", 
    acrobatic = true,
    transient_mode = "current"
}
defwinprop{ 
    class = "sun-awt-X11-XFramePeer", 
    acrobatic = true,
    transient_mode = "current"
}
defwinprop{
    class = "sun-awt-X11-XWindowPeer",
    acrobatic = true,
    transient_mode = "current"
}
-- cfg_notion.lua
ioncore.set{
    window_dialog_float = true,
}