xpra icon
Bug tracker and wiki

Opened 6 months ago

Closed 7 weeks ago

Last modified 5 days ago

#2539 closed enhancement (fixed)

use header bar for window controls

Reported by: Antoine Martin Owned by: Antoine Martin
Priority: blocker Milestone: 4.1
Component: client Version: 3.0.x
Keywords: Cc:

Description (last modified by Antoine Martin)

As in the example here: browser/xpra/trunk/src/xpra/client/gtk_base/example/header_bar.py, we can add our own window widgets to the header bar without changing its geometry.
Either using a pancake menu or a few buttons.
Things we can do with this:

  • window info dialog
  • actions: refresh, re-init, etc
  • tweak encoding settings: bandwidth limit, speed, quality, content-type, etc
  • suspend / resume
  • modify state: fullscreen, modal, etc..
  • screenshot, debug, etc

Attachments (6)

strip-client.patch (128.4 KB) - added by Antoine Martin 2 months ago.
strip the client window class to the bare minimum to show pixels
header_bar_bug.py (1.2 KB) - added by Antoine Martin 2 months ago.
reproduce the bug using a fake client
strip-client-v2.patch (131.1 KB) - added by Antoine Martin 2 months ago.
strip even more
pancake-menu.png (21.2 KB) - added by Antoine Martin 8 weeks ago.
pancake menu shown on an xterm
window-info.png (77.7 KB) - added by Antoine Martin 8 weeks ago.
window info for xterm
xpra-2359-2020-05-28_10-32-30.mp4 (96.4 KB) - added by stdedos 6 weeks ago.

Download all attachments as: .zip

Change History (25)

comment:1 Changed 6 months ago by Antoine Martin

Description: modified (diff)
Status: newassigned

comment:2 Changed 6 months ago by Antoine Martin

Milestone: 4.04.1

This is going to cause more problems with CSD, window geometry 'app-paintable' flag, etc..
Best to wait for the next release?

comment:3 Changed 2 months ago by Antoine Martin

Priority: majorcritical

Could be very useful, raising.

Changed 2 months ago by Antoine Martin

Attachment: strip-client.patch added

strip the client window class to the bare minimum to show pixels

Changed 2 months ago by Antoine Martin

Attachment: header_bar_bug.py added

reproduce the bug using a fake client

Changed 2 months ago by Antoine Martin

Attachment: strip-client-v2.patch added

strip even more

comment:4 Changed 2 months ago by Antoine Martin

Doh, turns out that we need to call Gtk.Widget.show_all and not Gtk.Widget.show to make this work.

r26319 adds a basic menu, requires XPRA_WINDOW_MENU=1 to show it.

Also needed r26314 for better window geometry handling.

TODO:

  • testing on all platforms (especially win32 and macos)
  • more useful menu items: toggle opengl per window? toggle modal? content-type? av-sync?
  • window info dialog: show geometry, attributes, state, etc..
  • add the full xpra menu (same as systray) - only for desktops that don't have the systray one? (impossible to tell thanks to the horrid gnome-shell / appindicator / statusicon clusterf####?)
  • add option to show window icon (gnome shell hides those now??)

comment:5 Changed 2 months ago by Antoine Martin

Improvements:

  • r26322 + r26323: show window info (also via ShortcutKey+Shift+F5).
  • r26324 tweaks and show window icon
  • r26328 enable by default (tested OK on win32, r26333: disabled on macos)
  • r26330 cleanup
  • r26331 more window info: backing render geometry
  • r26332 show global menu if we're running in gnome-shell
Last edited 8 weeks ago by Antoine Martin (previous) (diff)

Changed 8 weeks ago by Antoine Martin

Attachment: pancake-menu.png added

pancake menu shown on an xterm

Changed 8 weeks ago by Antoine Martin

Attachment: window-info.png added

window info for xterm

comment:6 Changed 8 weeks ago by Antoine Martin

The pancake menu:
pancake menu shown on an xterm

And the window info for this xterm:
window info for xterm

comment:7 Changed 7 weeks ago by Antoine Martin

Priority: criticalblocker

More details about regressions in #2762.

We had lost transparency support, r26403 restores that.

New regression on Linux: non-transparent windows just don't work any more (needs --opengl=force to trigger opengl on all windows to see it with xterm):

2020-05-19 11:58:51,839 glXMakeCurrent: xid=0x3a0510d, context=<OpenGL.raw.GLX._types.LP_struct___GLXcontextRec object at 0x7fffdc33f050>
2020-05-19 11:58:51,840 XError: <class 'Exception'>, glXMakeCurrent failed
Traceback (most recent call last):
  File "/usr/lib64/python3.7/site-packages/xpra/platform/xposix/gl_context.py", line 69, in __enter__
    raise Exception("glXMakeCurrent failed")
Exception: glXMakeCurrent failed

Looks like the visual doesn't match the one we requested?

comment:8 Changed 7 weeks ago by Antoine Martin

More UI improvements: r26444 + r26445 + r26446.

Added some debug and found no difference between the transparent window and non-transparent ones, in both cases:

  • parent window:
    'geometry': (0, 0, 250, 250, 0), 'depth': 32,
    'visual': {'visual-id': 130, 'red-mask': 16711680, 'green-mask': 65280, 'blue-mask': 255, 'bits-per-rgb': 8, 'map_entries': 256},
    'bit-gravity': 1, 'win-gravity': 1, 'backing-store': 0, 'backing-planes': 4294967295, 'backing-pixel': 0,
    'save-under': False, 'map-installed': 0, 'map-state': 0,
    'all-events-mask': 4423680, 'your_event_mask': 4423680, 'do-not-propagate-mask': 0, 'override-redirect': 0
    
  • drawing area widget:
    'geometry': (0, 0, 250, 250, 0), 'depth': 32,
    'visual': {'visual-id': 130, 'red-mask': 16711680, 'green-mask': 65280, 'blue-mask': 255, 'bits-per-rgb': 8, 'map_entries': 256},
    'bit-gravity': 1, 'win-gravity': 1, 'backing-store': 0, 'backing-planes': 4294967295, 'backing-pixel': 0,
    'save-under': False, 'map-installed': 0, 'map-state': 0,
    'all-events-mask': 4423680, 'your_event_mask': 4423680, 'do-not-propagate-mask': 0, 'override-redirect': 0
    

The map-state changes, it starts as 1 / 0 (IsUnviewable / IsUnmapped) then moves to Viewable 2 / 2.

The fix is in r26449: I'm not sure why but we have to be very careful on which widget we set the visual: even though the GTK window with a header bar already uses transparency, we can't ask for an RGBA visual... because that breaks.
But we do have to ask for one to use transparency, and we do have to do the same thing for the drawing area widget.

comment:9 Changed 7 weeks ago by Antoine Martin

Resolution: fixed
Status: assignedclosed

r26452: adds a "fullscreen" menu item and greys out "maximize" if it can't be used

This will do for now. Works OK on Linux and Windows - not available on MacOS.

comment:10 Changed 6 weeks ago by stdedos

Can you add "Always On Top" boolean?

If it makes any difference whether it is server-side or client-side set, both?

Is the "modal" a separate option, or is it an Attribute?

comment:11 Changed 6 weeks ago by Antoine Martin

Can you add "Always On Top" boolean?

Done in r26468.
Beware that we can't add too many entries to this menu, or it will get messy.

If it makes any difference whether it is server-side or client-side set, both?

The client will honour whatever setting applications request server-side, the client menu entry just provides an override.

Is the "modal" a separate option, or is it an Attribute?

"modal" is separate:

Modal would also be complicated by the fact that we have the --modal-windows=yes|no option.
"Modal" normally keeps the window on top of other windows from the same PID (ie: all windows forwarded from the same xpra session), not other applications.

comment:12 Changed 6 weeks ago by stdedos

I meant to add the "Always On Top" boolean on the Windows Information window, not necessarily as a client-toggleable option :-D

But don't take it out 😂. However:

  • There is no indication on the menu if it is set or not
  • The size of the Always On Top entry is weird compared to the other ones, I am assuming because all the other entries contain an icon. Can you add a dummy-sized icon?

Changed 6 weeks ago by stdedos

comment:13 Changed 6 weeks ago by stdedos

Also: Add a "Copy to clipboard" button (in any format you'd like - useful for #2783)

It could even be table format for WikiFormatting ;-)

Last edited 6 weeks ago by stdedos (previous) (diff)

comment:14 Changed 6 weeks ago by Antoine Martin

I meant to add the "Always On Top" boolean on the Windows Information window, not necessarily as a client-toggleable option :-D

It was already there, but very few applications actually request it so you're unlikely to see it.
It is part of _NET_WM_STATE, which is shown as State on the window-info window.
You can see it in action using the "States" tool from the xpra toolbox. (click on "Keep Above", aka stay-on-top)

There is no indication on the menu if it is set or not

I believe this is a theme issue, likely the same problem as reported in #2782.
It's missing some assets, it was working previously, so maybe I trimmed too much in r26475. This CSS stuff is a nightmare to debug.
It's also likely that when I re-add those assets, the headerbar will become bigger again... and maybe too big.

The size of the Always On Top entry is weird compared to the other ones, I am assuming because all the other entries contain an icon. Can you add a dummy-sized icon?

Now using a custom icon for showing the "ticked" state rather than a CheckMenuItem drawn by GTK and CSS: r26491.

Also: Add a "Copy to clipboard" button (in any format you'd like - useful for #2783)

Done in r26492.

comment:15 Changed 8 days ago by Antoine Martin

r26845 adds a command line option for controlling the headerbar:

  • xpra attach --headerbar=yes is the default (except on macos)
  • xpra attach --headerbar=force will enable it even when the window uses size-constraints (which may cause problems since we can't honour it: #2824)

comment:16 Changed 6 days ago by Antoine Martin

Best description I have found so far of the problem with GTK, size constraints and CSD: Maximize or fullscreen back-n-forth shrinks the terminal : gtk size negotiation nightmares: When creating a window you can't just call vte_terminal_set_size and let the system fit the window around that. You have to use gtk_window_set_default_size instead. But you need to know the difference in size between the window and the vte widget, and you can't measure that until after allocating a size to the window and realizing it and all its widgets. Things are further complicated because gtk_window_set_default_size seems to exclude the borders, but allocation and geometry hints include borders (and shadows).

Further down that ticket: This atomicity is something Wayland, Mutter, GTK etc. folks (I'm not sure who exactly) have to figure out.

GTK bug examples: https://gitlab.gnome.org/GNOME/gnome-terminal/-/issues/129#note_654131


Maybe we could just not enforce size-constraints client side and leave it to the server instead?
Use a temporarily fixed-sized drawing area (only until the window is mapped) to get GTK to honour the window size we actually want.

comment:17 Changed 6 days ago by Antoine Martin

As of r26860, we can use the headerbar in more cases: we use the drawingarea's size-request to ensure the min-size is still honoured when the headerbar is used.

comment:18 in reply to:  17 Changed 6 days ago by stdedos

Replying to Antoine Martin:

Best description I have found so far of the problem with GTK, size constraints and CSD: [...]

Sounds something like should be fat-stamped somewhere

Does the workaround proposed in the ticket (dconf write /org/gnome/terminal/legacy/headerbar '@mb false') work? Can it be applied only on XPRA-side? 😕

Replying to Antoine Martin:

As of r26860, we can use the headerbar in more cases: we use the drawingarea's size-request to ensure the min-size is still honoured when the headerbar is used.

Do I hear headerbar fixes ... or more issues?

comment:19 Changed 5 days ago by Antoine Martin

Does the workaround proposed in the ticket (dconf write /org/gnome/terminal/legacy/headerbar '@mb false') work?

Depends what you're trying to do.

Can it be applied only on XPRA-side? 😕

The xpra client has its own command line option now: --headerbar=on|off|force, on the server you can do what you want.

Do I hear headerbar fixes ... or more issues?

Fixes that allow CSD to be used and get GTK to create a window of the size that we request.

Note: See TracTickets for help on using tickets.