You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This looks at the feasibility of implementing _NET_WM_USER_TIME in dwm.
i3 has support for this and they use xcb_get_property_reply to get the property. Apparently they avoid focusing the new client if the user time comes through as 0.
if (set_focus) {
DLOG("Checking con = %p for _NET_WM_USER_TIME.\n", nc);
uint32_t*wm_user_time;
xcb_get_property_reply_t*wm_user_time_reply=xcb_get_property_reply(conn, wm_user_time_cookie, NULL);
if (wm_user_time_reply!=NULL&&xcb_get_property_value_length(wm_user_time_reply) !=0&&
(wm_user_time=xcb_get_property_value(wm_user_time_reply)) &&wm_user_time[0] ==0) {
DLOG("_NET_WM_USER_TIME set to 0, not focusing con = %p.\n", nc);
set_focus= false;
}
FREE(wm_user_time_reply);
} else {
xcb_discard_reply(conn, wm_user_time_cookie.sequence);
}
In dwm's case we get a notification through propertynotify and we are processing an XPropertyEvent, the struct of which is:
typedefstruct {
inttype; /* PropertyNotify */unsigned longserial; /* # of last request processed by server */Boolsend_event; /* true if this came from a SendEvent request */Display*display; /* Display the event was read from */Windowwindow;
Atomatom;
Timetime;
intstate; /* PropertyNewValue or PropertyDelete */
} XPropertyEvent;
As far as I can see the only part of the event that could be used in this context is the time field.
The way I imagined that this would work is that:
a _NET_WM_USER_TIME property notification comes in
we update c->usertime with the time of the event
when the manage function gets a new window to process we compare the current time with the usertime of the currently selected client, and if this is within a certain threshold then the new client will not be focused (i.e. focus remains where it was)
This in principle sounded feasible.
If this is how _NET_WM_USER_TIME is intended to be used I am not sure though.
Trying this out led to a few complications. The first was that the ev->time had a large value (2359545324) and it was not clear what this represented. The documentation did not provide any hints other than that it was the X server time.
Eventually, by comparing the delta between events, I worked out that this value was the time in milliseconds since X started, great. Storing the ev->time as-is would have been a quick win had it not been for the issue that it is not straightforward to obtain the server time when handling a new event. I believe that it is possible, but you would have to query the X server for this info as far as I understood.
In the maprequest function (that calls manage) we are processing an XMapRequestEvent event and this does not provide the X server time either.
A feasible workaround was to use time(NULL) instead, which gives you the number of seconds since epoch. This is fine as the times can be easily compared when a new client is processed, but it would have been nice to have the fidelity of the milliseconds.
I came up with a sort of compromise by deducing the X server time based on the time when a _NET_WM_USER_TIME property was received.
x_server_start_time=time(NULL) *1000-ev->time;
Which ends up like this in propertynotify:
elseif (ev->atom==netatom[NetWMUserTime]) {
if (x_server_start_time==0) // set X server start time for referencex_server_start_time=time(NULL) *1000-ev->time;
c->usertime=ev->time;
}
The X server time could then be taken into account when managing a new client, something along these lines:
if (c->mon->sel&& (time(NULL) *1000-x_server_start_time-c->mon->sel->usertime) <2000)
focusclient=0;
where the 2000 (ms) would be configurable of course.
That focusclient variable would then be used in key locations later on to avoid the new client stealing the show:
if (focusclient)
attachstack(c);
else {
c->snext=c->mon->sel->snext;
c->mon->sel->snext=c;
}
...
if (focusclient)
c->mon->sel=c;
...
if (focusclient)
focus(NULL);
OK, so this actually worked in that new clients did not receive focus if you are actively typing in a browser, for example.
Where it all fell apart is that applications that do send these _NET_WM_USER_TIME property notifications do so on every keypress - also when you hit modifier keys... This means that when you hit whatever keybinding to open a new terminal or whatever such applications will always keep focus rather than the one you just launched.
In conclusion I don't see how integrating _NET_WM_USER_TIME in dwm would add any practical benefit. Nor have I found any situations where knowing when the last time the user hit any buttons on a client to be of any particular use.
_NET_WM_USER_TIME CARDINAL/32
This property contains the XServer time at which last user activity in this window took place.
Clients should set this property on every new toplevel window (or on the window pointed out by the _NET_WM_USER_TIME_WINDOW property), before mapping the window, to the timestamp of the user interaction that caused the window to appear. A client that only deals with core events, might, for example, use the timestamp of the last KeyPress or ButtonPress event. ButtonRelease and KeyRelease events should not generally be considered to be user interaction, because an application may receive KeyRelease events from global keybindings, and generally release events may have later timestamp than actions that were triggered by the matching press events. Clients can obtain the timestamp that caused its first window to appear from the DESKTOP_STARTUP_ID environment variable, if the app was launched with startup notification. If the client does not know the timestamp of the user interaction that caused the first window to appear (e.g. because it was not launched with startup notification), then it should not set the property for that window. The special value of zero on a newly mapped window can be used to request that the window not be initially focused when it is mapped.
If the client has the active window, it should also update this property on the window whenever there's user activity.
Rationale: This property allows a Window Manager to alter the focus, stacking, and/or placement behavior of windows when they are mapped depending on whether the new window was created by a user action or is a "pop-up" window activated by a timer or some other event.
_NET_WM_USER_TIME_WINDOW WINDOW/32
This property contains the XID of a window on which the client sets the _NET_WM_USER_TIME property. Clients should check whether the window manager supports _NET_WM_USER_TIME_WINDOW and fall back to setting the _NET_WM_USER_TIME property on the toplevel window if it doesn't.
Rationale: Storing the frequently changing _NET_WM_USER_TIME property on the toplevel window itself causes every application that is interested in any of the properties of that window to be woken up on every keypress, which is particularly bad for laptops running on battery power.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
This looks at the feasibility of implementing _NET_WM_USER_TIME in dwm.
i3 has support for this and they use xcb_get_property_reply to get the property. Apparently they avoid focusing the new client if the user time comes through as 0.
In dwm's case we get a notification through
propertynotify
and we are processing an XPropertyEvent, the struct of which is:As far as I can see the only part of the event that could be used in this context is the
time
field.The way I imagined that this would work is that:
c->usertime
with the time of the eventmanage
function gets a new window to process we compare the current time with theusertime
of the currently selected client, and if this is within a certain threshold then the new client will not be focused (i.e. focus remains where it was)This in principle sounded feasible.
If this is how _NET_WM_USER_TIME is intended to be used I am not sure though.
Trying this out led to a few complications. The first was that the
ev->time
had a large value (2359545324) and it was not clear what this represented. The documentation did not provide any hints other than that it was the X server time.Eventually, by comparing the delta between events, I worked out that this value was the time in milliseconds since X started, great. Storing the
ev->time
as-is would have been a quick win had it not been for the issue that it is not straightforward to obtain the server time when handling a new event. I believe that it is possible, but you would have to query the X server for this info as far as I understood.In the
maprequest
function (that callsmanage
) we are processing an XMapRequestEvent event and this does not provide the X server time either.A feasible workaround was to use
time(NULL)
instead, which gives you the number of seconds since epoch. This is fine as the times can be easily compared when a new client is processed, but it would have been nice to have the fidelity of the milliseconds.I came up with a sort of compromise by deducing the X server time based on the time when a _NET_WM_USER_TIME property was received.
Which ends up like this in
propertynotify
:The X server time could then be taken into account when managing a new client, something along these lines:
where the 2000 (ms) would be configurable of course.
That
focusclient
variable would then be used in key locations later on to avoid the new client stealing the show:OK, so this actually worked in that new clients did not receive focus if you are actively typing in a browser, for example.
Where it all fell apart is that applications that do send these _NET_WM_USER_TIME property notifications do so on every keypress - also when you hit modifier keys... This means that when you hit whatever keybinding to open a new terminal or whatever such applications will always keep focus rather than the one you just launched.
In conclusion I don't see how integrating _NET_WM_USER_TIME in dwm would add any practical benefit. Nor have I found any situations where knowing when the last time the user hit any buttons on a client to be of any particular use.
Ref. https://specifications.freedesktop.org/wm-spec/latest/ar01s05.html:
Beta Was this translation helpful? Give feedback.
All reactions