commits
There are a bunch of computations in other places on various hints
that don't cope with them being zero or negative, so discard bogus
hints early.
Our frames don't span screens anymore due to vscreens, so looking
for a frame should not consider those on other screens or vscreens.
before, off-vscreen raises were unconditionally refused. This is a
problem when using Chrome's Control-Shift-A to switch to a different
window in another vspace, as the request will always be denied, despite
being user-requested (and with no way to allow it).
With the addition of the new bit, rudeness will be consulted when window
in another vscreen requests raise, and vscreen will be switched to, if
allowed. It defaults to "off" so that:
- all old behavior is unchanged,
- old values for rudeness will have the same behavior they always
did (to deny off-vscreen raise), and
- not setting rudeness at all will keep the same value as before
Probably, other use cases would be satisfied by this patch as well...
Recent feature addition to allow EWMH window-generated raise event via
_NET_ACTIVE_WINDOW did not respect rudeness setting, but rather would
blindly raise the window. Already map_request() has rudeness handling
logic, and fortunately it only needs to take a Window rather than a
whole Xevent, so we can change the caller -- MapNotify event processing
-- and have it pass a window. Then we'll use the Window we obtained
during the recently added ClientMessage -> _NET_ACTIVE_WINDOW event
processing and use that to call map_request().
This keeps us from having to reimplement rudeness logic in a second
place, and funnels to the same code for both "raise" methods.
some applications like Chrome, in the tab selection window, if they
think the WM is EWMH-compliant[*], will send a _NET_ACTIVE_WINDOW
ClientMessage with the target window ID of the one it wants raised.
in eb58c16a support was added for _NET_ACTIVE_WINDOW but this is only a
property maintained for others to read. this patch will also support
receiving it as a ClientMessage and switching windows accordingly.
[*] works in Ratpoison without this patch, so the presumption is
_NET_SUPPORTING_WM_CHECK added to sdorfehs in 95f44a4 is used to decide
what method to use for window switch; this is not proven but nonetheless
this patch works to restore functionality
This patch adds an 'execv' command that takes an initial arg to force
which vscreen to start the new window in.
We give spawn() an extra argument for what vscreen to use, rename it
vspawn() and then wrap it with a replacement spawn() that provides the
current vscreen, leaving existing behavior unchanged, and requiring no
modification of existing callers.
This still won't force the window of an unknown process (such as those
spawned using urxvtc -- which start with pids totally unknown to the
window manager and cannot be tracked by libXRes either) to start in a
certain vscreen, because the vscreen is stored in child proc which, once
mapped, is looked up by pid.
Using this is probably incompatible with 'winaddcurvscreen' set to 1,
and experimenting with setting it *after* execv commands, did not work
for some reason, I was unable to determine.
Normally it is not possible to sequence rcfile commands that run
programs, because 'exec' forks and does not wait for completion before
moving on to the next statement in rcfile. This patch adds an 'execw'
command that will wait indefinitely for the shell to exit. User should
use timeout(1) if they don't want to hang their window manager.
The client cannot use PRINT_DEBUG because it sends to stdout, which we
cannot contaminate. We can use warn(), but don't want that to pollute
the non-DEBUG experience, and we don't want to pollute -DDEBUG, so we
add it under a new -DSENDCMD_DEBUG following the example of INPUT_DEBUG.
However, to avoid ifdefs everywhere, we'll prefer to do that in a macro.
So we just add another macro that uses stderr. It's a bit more compact
than the one that uses stdout, this one uses __VA_ARGS__ as a straight
text macro, this should compile on BSD and Linux (only latter tested).
We could not use a modification of PRINT_DEBUG because it would have
needed fprintf(file, ...) and the way the macro was written it would
require passing ((args like this)) because it had a naked "printf args"
and relied on getting first level "()" stripped in the macro expansion.
This was a bit strange. It does mean there's now inconsistency between
PRINT_DEBUG and WARNX_DEBUG usage (former needs '(())', latter '()') but
the latter macro is only used by one function anyways and only
appropriate for the client so usage will probably never expand.
This patch allows those of us with larger numbers of windows and use
"windows" format strings to print stuff to wrapper scripts, to continue
to use sdorfehs when switching from ratpoison.
Before this patch, client would read only a single up-to-1k bytes buffer
to get the entire response, resulting in truncation of the message
(windows list, etc) if it was longer than 1022 bytes. Ultimately this
was a consequence of retooling to a different IPC mechanism that
happened in a426e8b6a, the new code uses a single read of 1024 bytes to
get the response.
First thought was to just make the response buffer larger, but who knows
what uses people have? Can we predict the right size limit? This way it
can handle any sized response. Server is still the one controlling size
of result buffer, and fixed 1k is still used for the "request" buffer
sent to the server process.
Second thought was, since response already has "successfulness" as the
first byte of response (and we have to process it), we could declare an
"initial response" packet that would include some bytes that specified
the response buffer size, and then client would always make a second
second request, this time with an exact size it knew in advance. This
may have been a fine approach, but results in an extra round trip for
the common case of a single buffer. Thought a loop would be better...
So, instead we treat the first buffer specially, by continuing to strip
the successfulness response, but then also now arranging for subsequent
reads to be O_NONBLOCK. Presence of the first buffer means that
necessarily the server has prepared the full response, so we can keep
going until a blocked or closed connection to get the rest of it.
In testing, at response conclusion, sometimes the socket connection was
closed, and sometimes the end of the response would just block forever
waiting for another read. Was not able to tell what differentiates
these end-states, but also found that treating them identically (as
"command finished" signals) always seems to result in the right
behavior, so it might be ok not to know why...
Using server-maintained PID extension is a lot more reliable as it's
directly tracked by the X server and no need for client to set anything.
We still use _NET_WM_PID if it's available to retain old behavior and
allow for setting different PID than actual PID which some programs do.
Without this patch, (1) the program must be a "good" conforming client
and always set its own _NET_WM_PID which is voluntary, and (2) it must
do it before the window manager receives the CreateNotify event and
tries to look up the window. This race is frequently failing for some
applications like `st`.
As code is now, when changing vscreens, the current window is
un-fullscreened (if needed) and bar is hidden. With this patch, we
don't hide the bar if msgwait is 0. This leaves the vscreen or windows
list up if it were up already, even when changing vscreens. It gets
updated -- ie redrawn -- to the new correct windows or vscreen names and
upon switch. This lets the user keep the list of windows up and move
between either windows or vscreens, while retaining correctly updated
winlist contents.
This seems to retain functionality of fullscreen windows also. However,
it was only tested with Chrome's fullscreen, which for me worked even
before the EWMH patches.
this behavior was originally in ratpoison for msgwait 0 until 0705415,
it said in [removed] comment:
This handles the case when msgwait is 0 (the bar sticks) and the
user uses this command to toggle the bar on and off
This restores that removed behavior (solely for msgwait 0 barsticky 0)
without needing to re-teach hide_bar() to have a return value after
"trying" to hide, as it did before, instead we just look at the current
state with these convenient bar_is_raised thing and toggle it.
did not use BAR_IS_RAISED() macro because we should be ok with any
nonzero values... and also this macro wasn't available in both action.c
and bar.c
Add boolean rcvar 'winaddcurvscreen' (default 0).
In the specific case of a new window where the parent was originally
started in one vscreen, but spawns another window later when a different
vscreen is active, 'winvcur' will cause the new window to be added to
whatever the current vscreen at the time, rather than the ostensible
parent vscreen.
Default behavior (use parent's initial vscreen) is unchanged.
The original impetus for this patch was to fix use of 'urxvtc' with
'urxvtd', coming from old ratpoison "groups" and migrating to vscreens.
'urxvt' standalone already worked as expected: starting in the current
vscreen, since these are completely new processes. However 'urxvtc' are
child windows all of the same urxvtd process.
Without this, stdin will remain open to the tty used to launch X,
and will be fd 0 for forked commands, which can result in wrong
things (like thinking the shell isatty(STDIN_FILENO) even though
it's really not); it should really be duplicated from "/dev/null"
for forked commands
this helps with debugging to know which line is actually being hit
these will allow using vscreens to be used like groups were. no attempt
to implement vmerge and friends, but vnext/vother/vprev are enough at
least for basic functionality.
it seems probable that these functions -- screen_last_vscreen(),
screen_next_vscreen(), screen_prev_vscreen() -- were put there to be
called but had not yet been linked to actual commands
by having vmove work with names (prior commit) and group next/prev/other
to have replacements, basic functionality from ratpoison is retained
this makes it match intent expressed by original commit 79582a47:
> Rip out groups ... vscreens can now be referred to (by vmove, etc.)
> by their name or number.
^^^^^^^^^^^^^
and gives better hope of moving to sdorfehs if using naming feature of
Ratpoison Groups.
this makes the code obey its comment:
"Given a string, find a matching vscreen. First check if the string
exactly matches a vscreen name, then check if it is a number &
lastly check if it partially matches the name of a vscreen.
it also just makes sense to look for name first because if someone does
"vrename number" it will still work fine even if they change offsets
(imagine, eg if user likes 1-based rather than 0-based vscreen workspaces)
This is a better fix than ab12a563 since we shouldn't be redrawing
the sticky bar at all if we just turned it off.
Ref #24
I am grateful to all of the Ratpoison contributors and this file and
their individual contributions will live on in the source
repository, but this file has not been updated with contact info
changes since forking and does not reflect any new contributors to
sdorfehs.
This 20190822 version hasn't been accurate since forking from
ratpoison.
If there is a .git directory, assume we're building from git and
pass "git-XXXXXXX" as the version to help with bug reports, but to
avoid an unnecessary build dependency on git, if there is no .git,
just pass the hard-coded VERSION which will get bumped on each
release.
Otherwise the logic that determines whether to reset it is already
assuming the bar is not sticky and doesn't need a reset
See #24
xrandr might not be available or we might not have a primary screen.
screen_primary() factors in xrandr_is_primary() in its calculation
but has better logic for determining an actual primary screen.
Fixes the issue of the bar drawing over the only frame which can be
seen in Xnest.
Initializing screens -> vscreens -> frames had a weird process
because certain calls needed to be done after prior initialization
was done. This wasn't being done in response to xrandr changes and
the frame lists in a new screen's vscreens were not being
initialized properly.
Avoid that by storing a pointer to the vscreen in rp_frame to avoid
having to look it up dynamically with frames_vscreen(), which was
failing to find the vscreen during this initialization because the
prior lists hadn't been finished getting setup.
Since frames can't move between screens or vscreens, it shouldn't be
an issue storing a pointer in rp_frame.
Should fix #19
Anything using FONT_HEIGHT() to make window size calculations needs
the screen's xft_font setup first.
This isn't supported by dzen2 but it seems like a natural extension.
It allows a single string of data like a speaker icon, but multiple
commands depending on the button clicked, such as a volume up action
when button 4 is clicked (mouse wheel scrolling up), and a volume
down action when button 5 is clicked (mouse wheel scrolling down).
Defer parsing these until we get an actual click since the parsing
is a bit more complicated now and we're probably going to have many
more updates to the bar than mouse clicks.
The bar window and padding were not being taken into account, making
clicks register on the wrong text chunk.
Move vscreen initialization further down init_screen because we need
the root window set.
Otherwise some window borders can become translucent, like Firefox's
and Chrome's when using a compositor
This previously used fgcolor but now it can be something else.
Change the default gap to 10 and default padding to 20 to preserve
the previous default look.
Change default bar_in_padding to 1. Since the default padding is
also 0, this should have no effect on the default setup.
Other screens just get a transient info bar as if bar_sticky were
off.
There are a bunch of computations in other places on various hints
that don't cope with them being zero or negative, so discard bogus
hints early.
before, off-vscreen raises were unconditionally refused. This is a
problem when using Chrome's Control-Shift-A to switch to a different
window in another vspace, as the request will always be denied, despite
being user-requested (and with no way to allow it).
With the addition of the new bit, rudeness will be consulted when window
in another vscreen requests raise, and vscreen will be switched to, if
allowed. It defaults to "off" so that:
- all old behavior is unchanged,
- old values for rudeness will have the same behavior they always
did (to deny off-vscreen raise), and
- not setting rudeness at all will keep the same value as before
Probably, other use cases would be satisfied by this patch as well...
Recent feature addition to allow EWMH window-generated raise event via
_NET_ACTIVE_WINDOW did not respect rudeness setting, but rather would
blindly raise the window. Already map_request() has rudeness handling
logic, and fortunately it only needs to take a Window rather than a
whole Xevent, so we can change the caller -- MapNotify event processing
-- and have it pass a window. Then we'll use the Window we obtained
during the recently added ClientMessage -> _NET_ACTIVE_WINDOW event
processing and use that to call map_request().
This keeps us from having to reimplement rudeness logic in a second
place, and funnels to the same code for both "raise" methods.
some applications like Chrome, in the tab selection window, if they
think the WM is EWMH-compliant[*], will send a _NET_ACTIVE_WINDOW
ClientMessage with the target window ID of the one it wants raised.
in eb58c16a support was added for _NET_ACTIVE_WINDOW but this is only a
property maintained for others to read. this patch will also support
receiving it as a ClientMessage and switching windows accordingly.
[*] works in Ratpoison without this patch, so the presumption is
_NET_SUPPORTING_WM_CHECK added to sdorfehs in 95f44a4 is used to decide
what method to use for window switch; this is not proven but nonetheless
this patch works to restore functionality
This patch adds an 'execv' command that takes an initial arg to force
which vscreen to start the new window in.
We give spawn() an extra argument for what vscreen to use, rename it
vspawn() and then wrap it with a replacement spawn() that provides the
current vscreen, leaving existing behavior unchanged, and requiring no
modification of existing callers.
This still won't force the window of an unknown process (such as those
spawned using urxvtc -- which start with pids totally unknown to the
window manager and cannot be tracked by libXRes either) to start in a
certain vscreen, because the vscreen is stored in child proc which, once
mapped, is looked up by pid.
Using this is probably incompatible with 'winaddcurvscreen' set to 1,
and experimenting with setting it *after* execv commands, did not work
for some reason, I was unable to determine.
Normally it is not possible to sequence rcfile commands that run
programs, because 'exec' forks and does not wait for completion before
moving on to the next statement in rcfile. This patch adds an 'execw'
command that will wait indefinitely for the shell to exit. User should
use timeout(1) if they don't want to hang their window manager.
The client cannot use PRINT_DEBUG because it sends to stdout, which we
cannot contaminate. We can use warn(), but don't want that to pollute
the non-DEBUG experience, and we don't want to pollute -DDEBUG, so we
add it under a new -DSENDCMD_DEBUG following the example of INPUT_DEBUG.
However, to avoid ifdefs everywhere, we'll prefer to do that in a macro.
So we just add another macro that uses stderr. It's a bit more compact
than the one that uses stdout, this one uses __VA_ARGS__ as a straight
text macro, this should compile on BSD and Linux (only latter tested).
We could not use a modification of PRINT_DEBUG because it would have
needed fprintf(file, ...) and the way the macro was written it would
require passing ((args like this)) because it had a naked "printf args"
and relied on getting first level "()" stripped in the macro expansion.
This was a bit strange. It does mean there's now inconsistency between
PRINT_DEBUG and WARNX_DEBUG usage (former needs '(())', latter '()') but
the latter macro is only used by one function anyways and only
appropriate for the client so usage will probably never expand.
This patch allows those of us with larger numbers of windows and use
"windows" format strings to print stuff to wrapper scripts, to continue
to use sdorfehs when switching from ratpoison.
Before this patch, client would read only a single up-to-1k bytes buffer
to get the entire response, resulting in truncation of the message
(windows list, etc) if it was longer than 1022 bytes. Ultimately this
was a consequence of retooling to a different IPC mechanism that
happened in a426e8b6a, the new code uses a single read of 1024 bytes to
get the response.
First thought was to just make the response buffer larger, but who knows
what uses people have? Can we predict the right size limit? This way it
can handle any sized response. Server is still the one controlling size
of result buffer, and fixed 1k is still used for the "request" buffer
sent to the server process.
Second thought was, since response already has "successfulness" as the
first byte of response (and we have to process it), we could declare an
"initial response" packet that would include some bytes that specified
the response buffer size, and then client would always make a second
second request, this time with an exact size it knew in advance. This
may have been a fine approach, but results in an extra round trip for
the common case of a single buffer. Thought a loop would be better...
So, instead we treat the first buffer specially, by continuing to strip
the successfulness response, but then also now arranging for subsequent
reads to be O_NONBLOCK. Presence of the first buffer means that
necessarily the server has prepared the full response, so we can keep
going until a blocked or closed connection to get the rest of it.
In testing, at response conclusion, sometimes the socket connection was
closed, and sometimes the end of the response would just block forever
waiting for another read. Was not able to tell what differentiates
these end-states, but also found that treating them identically (as
"command finished" signals) always seems to result in the right
behavior, so it might be ok not to know why...
Using server-maintained PID extension is a lot more reliable as it's
directly tracked by the X server and no need for client to set anything.
We still use _NET_WM_PID if it's available to retain old behavior and
allow for setting different PID than actual PID which some programs do.
Without this patch, (1) the program must be a "good" conforming client
and always set its own _NET_WM_PID which is voluntary, and (2) it must
do it before the window manager receives the CreateNotify event and
tries to look up the window. This race is frequently failing for some
applications like `st`.
As code is now, when changing vscreens, the current window is
un-fullscreened (if needed) and bar is hidden. With this patch, we
don't hide the bar if msgwait is 0. This leaves the vscreen or windows
list up if it were up already, even when changing vscreens. It gets
updated -- ie redrawn -- to the new correct windows or vscreen names and
upon switch. This lets the user keep the list of windows up and move
between either windows or vscreens, while retaining correctly updated
winlist contents.
This seems to retain functionality of fullscreen windows also. However,
it was only tested with Chrome's fullscreen, which for me worked even
before the EWMH patches.
this behavior was originally in ratpoison for msgwait 0 until 0705415,
it said in [removed] comment:
This handles the case when msgwait is 0 (the bar sticks) and the
user uses this command to toggle the bar on and off
This restores that removed behavior (solely for msgwait 0 barsticky 0)
without needing to re-teach hide_bar() to have a return value after
"trying" to hide, as it did before, instead we just look at the current
state with these convenient bar_is_raised thing and toggle it.
did not use BAR_IS_RAISED() macro because we should be ok with any
nonzero values... and also this macro wasn't available in both action.c
and bar.c
Add boolean rcvar 'winaddcurvscreen' (default 0).
In the specific case of a new window where the parent was originally
started in one vscreen, but spawns another window later when a different
vscreen is active, 'winvcur' will cause the new window to be added to
whatever the current vscreen at the time, rather than the ostensible
parent vscreen.
Default behavior (use parent's initial vscreen) is unchanged.
The original impetus for this patch was to fix use of 'urxvtc' with
'urxvtd', coming from old ratpoison "groups" and migrating to vscreens.
'urxvt' standalone already worked as expected: starting in the current
vscreen, since these are completely new processes. However 'urxvtc' are
child windows all of the same urxvtd process.
these will allow using vscreens to be used like groups were. no attempt
to implement vmerge and friends, but vnext/vother/vprev are enough at
least for basic functionality.
it seems probable that these functions -- screen_last_vscreen(),
screen_next_vscreen(), screen_prev_vscreen() -- were put there to be
called but had not yet been linked to actual commands
by having vmove work with names (prior commit) and group next/prev/other
to have replacements, basic functionality from ratpoison is retained
this makes the code obey its comment:
"Given a string, find a matching vscreen. First check if the string
exactly matches a vscreen name, then check if it is a number &
lastly check if it partially matches the name of a vscreen.
it also just makes sense to look for name first because if someone does
"vrename number" it will still work fine even if they change offsets
(imagine, eg if user likes 1-based rather than 0-based vscreen workspaces)
This 20190822 version hasn't been accurate since forking from
ratpoison.
If there is a .git directory, assume we're building from git and
pass "git-XXXXXXX" as the version to help with bug reports, but to
avoid an unnecessary build dependency on git, if there is no .git,
just pass the hard-coded VERSION which will get bumped on each
release.
Initializing screens -> vscreens -> frames had a weird process
because certain calls needed to be done after prior initialization
was done. This wasn't being done in response to xrandr changes and
the frame lists in a new screen's vscreens were not being
initialized properly.
Avoid that by storing a pointer to the vscreen in rp_frame to avoid
having to look it up dynamically with frames_vscreen(), which was
failing to find the vscreen during this initialization because the
prior lists hadn't been finished getting setup.
Since frames can't move between screens or vscreens, it shouldn't be
an issue storing a pointer in rp_frame.
Should fix #19
This isn't supported by dzen2 but it seems like a natural extension.
It allows a single string of data like a speaker icon, but multiple
commands depending on the button clicked, such as a volume up action
when button 4 is clicked (mouse wheel scrolling up), and a volume
down action when button 5 is clicked (mouse wheel scrolling down).
Defer parsing these until we get an actual click since the parsing
is a bit more complicated now and we're probably going to have many
more updates to the bar than mouse clicks.