7

This to me is VERY strange. Could someone please explain why the activate() function should want a timestamp? Wouldn't 99.9% of the time be NOW or ASAP or "At your earliest convenience"? And furthermore, if you try w.activate(0) you get this warning:

Wnck-WARNING: Received a timestamp of 0; window activation may not function properly

Every forum thread that I have read about this warning ends with no answer. But they all seem to indicate that the code does not work properly unless you actually put in the timestamp. And if you put in the (0), things don't work, and you get the warning. However, for me, if I put in a timestamp, that is when things don't work. If I use (0), the program works except that I get the Warning (only if I run it in a terminal window).

Why on earth does activate() care about 'time' anyway?

Am I the only person who thinks this is insane?

Dan D.
  • 73,243
  • 15
  • 104
  • 123
Harvey
  • 2,062
  • 2
  • 21
  • 38
  • Thanks to @Dan D. I now understand why the timestamps. Wnck still seems to be broken for me, so I have abandoned using it and have taken a different approach. – Harvey Jan 04 '15 at 19:42

3 Answers3

7

This actually has to do with X11 and serializability. The timestamp is used to order messages and to tell which ones are late and can be safely ignored. Otherwise messages from the past which should be ignored, because their effect has been overwritten by a newer message, would apply their effect incorrectly.

In this case if one message says activate window X and another activate window Y without the timestamp it is not possible to tell if the message for X happened before Y or after it.

See section 3 in Why X Is Not Our Ideal Window System for races that result from lack of timestamps and serializability in the X protocol.

Also one shouldn't use int(time.time()), which is the time on the client, in window.activate(int(time.time())) but rather the last timestamp sent from the server.

Wnck contains this function. This is needs a server round trip. Translating this into Python would work and would be reasonably an entirely another question but it is asinine that Wnck's Python binding don't export this function as it is the only function that returns the timestamp that the other functions expect as an argument:

/**
 * get_server_time:
 * @display: display from which to get the time
 * @window: a #Window, used for communication with the server.
 *          The window must have PropertyChangeMask in its
 *          events mask or a hang will result.
 * 
 * Routine to get the current X server time stamp. 
 * 
 * Return value: the time stamp.
 **/
static Time
get_server_time (Window window)
{
  unsigned char c = 'a';
  XEvent xevent;
  TimeStampInfo info;

  info.timestamp_prop_atom = _wnck_atom_get ("_TIMESTAMP_PROP");
  info.window = window;

  XChangeProperty (_wnck_get_default_display (), window,
           info.timestamp_prop_atom, info.timestamp_prop_atom,
           8, PropModeReplace, &c, 1);

  XIfEvent (_wnck_get_default_display (), &xevent,
        timestamp_predicate, (XPointer)&info);

  return xevent.xproperty.time;
}

But if the loop that processes the X events just kept track of the timestamp from messages from the server, there would be a need for a round trip. And I thought Wnck or GDK did that and had a function for getting the value.

Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • Can you show me one example that works correctly? Why is there not a default for 'now'? If the function meeds a timestamp, why can't it get one itself? How would I get 'the last timestamp sent from the server'? I just want to give focus to the window NOW, is that so hard? – Harvey Dec 12 '14 at 17:23
  • Oh, and by the way... putting in a timestamp other than 0 causes my program to fail and lock up the Alt-Tab ability to switch running applications. The only way I've been able to get it to work is with (0), but is gives me this warning. This must have been "fixed" ( ;^) ) sometime within the last 6 years, so now it is broke both ways. Please explain! – Harvey Dec 12 '14 at 17:30
  • There is no server. I am beginning to think that wnck is completely not what I want to be using. All I want to do is give keyboard focus to another application's window and send some simulated keystrokes to it. I tried searching for "focus" and came up with wnck. – Harvey Dec 12 '14 at 17:58
  • Thank you! So I'm not the only one who is seeing some insanity... "asinine" as you put it. – Harvey Dec 12 '14 at 18:07
  • Thanks for your explanation of how and why timestamps are used. I would accept this as an answer except that it appears that Wnck has a bug, and I eventually stopped using it and took another route which turned out to be more correct for my need anyway. I will upvote your answer. – Harvey Jan 04 '15 at 19:32
  • Just a note: if you use `int(time.time())` to get the timestamp, you might start to see strange problems with other applications. For example, on my system this broke copy/paste in Qt applications! Using the correct server time (with the code shown by @hazzey) fixed that. – oliver Jun 02 '22 at 10:30
5

An easy way to include a valid timestamp with python is to use the following:

now = gtk.gdk.x11_get_server_time(gtk.gdk.get_default_root_window())

w.activate(now)

This gives wnck a timestamp so that the warning isn't printed.

Community
  • 1
  • 1
hazzey
  • 1,179
  • 25
  • 29
3

I'm using this setup

import gi
gi.require_version("Wnck", "3.0")
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Wnck, GdkX11, Gdk

And so I had to use this instead

now = GdkX11.x11_get_server_time(GdkX11.X11Window.lookup_for_display(Gdk.Display.get_default(),
GdkX11.x11_get_default_root_xwindow()))
window.activate(now)