Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WM_TAKE_FOCUS messages can have wrong timestamp #4484

Closed
luke-jr opened this issue Jan 24, 2025 · 1 comment
Closed

WM_TAKE_FOCUS messages can have wrong timestamp #4484

luke-jr opened this issue Jan 24, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@luke-jr
Copy link

luke-jr commented Jan 24, 2025

Describe the bug
Somehow xpra is sending applications WM_TAKE_FOCUS with the wrong timestamp. This confuses Qt and causes copy-to-clipboard to fail with qt.qpa.clipboard: QXcbClipboard::setMimeData: Cannot set X11 selection owner

It usually only happens after several weeks of uptime. Restarting xpra doesn't seem to help.

To Reproduce
Steps to reproduce the behavior:

  1. Wait several weeks. In my most recent occurrence, it began causing issues after 37 days.
  2. Open kwrite or some other Qt application with copy-to-clipboard functionality
  3. Attempt to copy to clipboard.

System Information (please complete the following information):

  • Server OS: Linux
  • Client OS: Linux
  • Xpra Server Version: 5.0.10
  • Xpra Client Version: 6.0.1

Additional context
Add any other context about the problem here.
Please see "reporting bugs" in the wiki section.

@luke-jr luke-jr added the bug Something isn't working label Jan 24, 2025
totaam added a commit that referenced this issue Jan 25, 2025
what we want is unsigned long, so have to use 'long' which gets translated correctly to:
__Pyx_PyInt_From_unsigned_long(__pyx_v_xevent.xproperty.time);
@totaam
Copy link
Collaborator

totaam commented Jan 25, 2025

Looks like the same issue as #4439

The helpful hint was the 37 days:

round(2**32/1000/60/60/24)
50

I think that this is a regression caused by fef8b55 in v5.

The actual code setting the focus is here:

def do_give_client_focus(self) -> None:
protocols = self.get_property("protocols")
focuslog("Giving focus to %#x, input_field=%s, FORCE_XSETINPUTFOCUS=%s, protocols=%s",
self.xid, self._input_field, FORCE_XSETINPUTFOCUS, protocols)
# Have to fetch the time, not just use CurrentTime, both because ICCCM
# says that WM_TAKE_FOCUS must use a real time and because there are
# genuine race conditions here (e.g. suppose the client does not
# actually get around to requesting the focus until after we have
# already changed our mind and decided to give it to someone else).
now = X11Window.get_server_time(self.corral_xid)
# ICCCM 4.1.7 *claims* to describe how we are supposed to give focus
# to a window, but it is completely opaque. From reading the
# metacity, kwin, gtk+, and qt code, it appears that the actual rules
# for giving focus are:
# -- the WM_HINTS input field determines whether the WM should call
# XSetInputFocus
# -- independently, the WM_TAKE_FOCUS protocol determines whether
# the WM should send a WM_TAKE_FOCUS ClientMessage.
# If both are set, both methods MUST be used together. For example,
# GTK+ apps respect WM_TAKE_FOCUS alone, but I'm not sure they handle
# XSetInputFocus well, while Qt apps ignore (!!!) WM_TAKE_FOCUS
# (unless they have a modal window), and just expect to get focus from
# the WM's XSetInputFocus.
if bool(self._input_field) or FORCE_XSETINPUTFOCUS:
focuslog("... using XSetInputFocus")
X11Window.XSetInputFocus(self.xid, now)
if "WM_TAKE_FOCUS" in protocols:
focuslog("... using WM_TAKE_FOCUS")
send_wm_take_focus(self.xid, now)
self.set_active()

And the server time is obtained from here:
def get_server_time(self, Window xwindow) -> long:
cdef unsigned char c = b"a"
cdef Atom timestamp_prop = self.str_to_atom("XPRA_TIMESTAMP_PROP")
XChangeProperty(self.display, xwindow, timestamp_prop,
timestamp_prop,
8, PropModeReplace, &c, 1)
cdef XEvent xevent
cdef xifevent_timestamp et
et.window = xwindow
et.atom = timestamp_prop
XIfEvent(self.display, &xevent, <void*> &timestamp_predicate, <XPointer> &et)
return xevent.xproperty.time

By inspecting the generated C code, I believe that 3e25ef4 should fix this.
Though it may take up to ~50 days to confirm!

totaam added a commit that referenced this issue Jan 25, 2025
what we want is unsigned long, so have to use 'long' which gets translated correctly to:
__Pyx_PyInt_From_unsigned_long(__pyx_v_xevent.xproperty.time);
totaam added a commit that referenced this issue Jan 25, 2025
what we want is unsigned long, so have to use 'long' which gets translated correctly to:
__Pyx_PyInt_From_unsigned_long(__pyx_v_xevent.xproperty.time);
totaam added a commit that referenced this issue Jan 25, 2025
what we want is unsigned long, so have to use 'long' which gets translated correctly to:
__Pyx_PyInt_From_unsigned_long(__pyx_v_xevent.xproperty.time);
@totaam totaam closed this as completed Jan 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants