Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why python Wnck window.activate(int(time.time()))

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?

like image 785
Harvey Avatar asked Dec 12 '14 16:12

Harvey


3 Answers

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.

like image 72
Dan D. Avatar answered Oct 31 '22 21:10

Dan D.


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.

like image 45
hazzey Avatar answered Oct 31 '22 22:10

hazzey


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)
like image 39
user2958425 Avatar answered Oct 31 '22 20:10

user2958425