Xpra-org / xpra

Persistent remote applications for X11; screen sharing for X11, MacOS and MSWindows.

Home Page:https://xpra.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

task grouping not working for gtk based applications

d3matt opened this issue · comments

Describe the bug
Launching multiple seamless gtk based applications with the same binary isn't showing them as grouped

To Reproduce
Steps to reproduce the behavior:

  1. xpra start :8
  2. using a session to launch xpra with opengl off, connecting to the remote server over ssh on display 8
  3. launch multiple gvim windows, note that they're not grouped together

System Information (please complete the following information):

  • Server OS: Rocky Linux 9.3
  • Client OS: Windows 10
  • Xpra Server Version 5.0.2
  • Xpra Client Version 5.0.8

Additional context
Some QT based applications (such on konsole) and xfce based applications (such as xfce4-terminal) seem to get grouped together but not others. The terminal I launch everything from (usually konsole) was started from the xpra client taskbar start menu.

My guess is that the grouped applications use the same pid for all of their windows and the others do not.
If so, then I'm not sure that this is fixable in a sane way.

Hmm, yea... Looks like if I force a new PID to get a new window, then QT apps don't group either... Could the client optionally group things based on the /proc//exe symlink?

It should be doable here:

def get_group_leader(self, wid: int, metadata: typedict, _override_redirect: bool):
def find_gdk_window(metadata_key="transient-for"):
return self.find_gdk_window(metadata, metadata_key)
win = find_gdk_window("group-leader-wid") or find_gdk_window("transient-for") or find_gdk_window("parent")
log(f"get_group_leader(..)={win}")
if win:
return win
pid = metadata.intget("pid", -1)
leader_xid = metadata.intget("group-leader-xid", -1)
log(f"get_group_leader: leader pid={pid}, xid={leader_xid}")
reftype = "xid"
ref: str | int = leader_xid
if ref < 0:
ci = metadata.strtupleget("class-instance")
if ci:
reftype = "class"
ref = "|".join(ci)
elif pid > 0:
reftype = "pid"
ref = pid
else:
# no reference to use
return None
refkey = f"{reftype}:{ref}"
group_leader_window = self._ref_to_group_leader.get(refkey)
if group_leader_window:
log("found existing group leader window %s using ref=%s", group_leader_window, refkey)
return group_leader_window
# we need to create one:
title = "%s group leader for %s" % (self.session_name or "Xpra", pid)
# group_leader_window = Gdk.Window(None, 1, 1, Gtk.WindowType.TOPLEVEL, 0, Gdk.INPUT_ONLY, title)
# static new(parent, attributes, attributes_mask)
group_leader_window = GDKWindow(wclass=Gdk.WindowWindowClass.INPUT_ONLY, title=title)
self._ref_to_group_leader[refkey] = group_leader_window
# avoid warning on win32...
if not WIN32:
# X11 spec says window should point to itself:
group_leader_window.set_group(group_leader_window)
log("new hidden group leader window %s for ref=%s", group_leader_window, refkey)
self._group_leader_wids.setdefault(group_leader_window, []).append(wid)
return group_leader_window

I was worried that the signal watcher was going to be tied to it, but I was wrong, it only uses the wid, pid:
def assign_signal_watcher_pid(self, wid: int, pid: int, title="") -> int:

@d3matt please try 307242b or later.
The default grouping will be the first match from:

WINDOW_GROUPING = os.environ.get("XPRA_WINDOW_GROUPING", "group-leader-xid,class-instance,pid,command").split(",")

So what you want should be achievable using:

XPRA_WINDOW_GROUPING=group-leader-xid,command,pid xpra attach ...

(keeping group-leader-xid as the first option should ensure we honour applications that do request grouping themselves)