commits
We didn't want to leak the initial startup stdin -- which is the tty
where X started -- to all child procs, so we opened /dev/null and
duplicated it onto fd 1. but then we forgot to close the temporary fd
so it leaks to child procs.
All the exec'ed processes would get copies of the control socket
descriptors, because of the default UNIX semantics of fd inherit across
execv(). This was easily seen on my system where an 'lsof' revealed
that all my terminals and shells had a copy.
To fix this we add the SOCK_CLOEXEC flag whilst opening the listener
socket(), avoiding this problem. We also need to set CLOEXEC on the
socket returned by accept():
"accept() ... extracts the first connection request on the queue of
pending connections ... creates a new connected socket, and returns a
new file descriptor"
The new descriptor does not inherit CLOEXEC flag from the listener.
The "bar" descriptor already handles this by setting O_CLOEXEC in its
own open() call on the FIFO.
Both send_message() and receive_message() use writes: the former to send
to the latter, and then a reply is sent back from the latter to the
former. Both of them expected a single write to work unconditionally
without being able to tolerate any transient issues.
This commit factors out the writes into a common function called
send_unix() which serves as the companion to the recently added
recv_unix(). The send call is modified to handle both partial writes
and interrupted writes. Especially the latter is not that unlikely: it
can happen when we're in the middle of writing a message and then we get
interrupted by a SIGCHLD. This is not a difficult thing to happen
during the ordinary course of operations because the native 'exec' is
asynchronous. It was observed to happen during testing.
Partial writes might also be possible if some of the buffer was sent and
then got interrupted by a signal, but this probably can't happen at
the small BUFSZ we use. Nonetheless it will make the code more robust
to support the possibility of partial writes.
Any error besides EINTR is considered a fatal error for send_message()
because this is only called by a "client" invocation, ie "sdorfehs -c".
The "server" (ie receve_message()) only issues a warning and then aborts
processing the signal. Otherwise, it would die. This matches the
existing use of err() and warn() that was used after a mismatch in
written and wrote buffer sizes in the respective writers, prior to this
patch.
There are some transient conditions which are normal, such as an
interrupted system call, which can happen if sdorfehs received a signal
during processing, such as SIGCHLD when a forked process exited (a
completely normal situation). Of course, we should retry the syscall in
that case
. We can retry these after a small sleep of
200ms
both send_message() and receive_message()
This re-uses the code factored out from send_command() to receive the
sent command in multiple chunks into a dynamic heap buffer. Now we are
able to receive arbitrarily sized commands that span multiple BUFSZs.
This restores a regression from the original Ratpoison.
Example: 'sdorfehs -c "echo $(ncal 2024)"' will print the full year's
calendar as a message, it's over 2k bytes, so it will span 3 buffer
quanta (BUFSZ == 1024 at time of writing).
Here we make a new function recv_unix() that encapsulates the logic of
receiving a message from a unix domain socket (ie our control socket)
and copying it into a dynamically-sized heap buffer for disposition by
the caller. This will let us use it from other functions, in particular
from receive_command(), which is currently using a single buffer and
reading from the socket one character at a time. Since the logic for
doing this robustly was already implemented in send_command(), we can
just factor it out and use in both places.
Previously, we used a newline to mark the end of the message sent from
send_command(), which restricted the characters we could send across
(ie, we couldn't send a newline). This was a new limitation of sdorfehs
that was not present in ratpoison. In particular, "ratpoison -c echo"
was instrumented to be able to handle newlines in the message and draw
variable-height windows to show them (for example, "ratpoison -c
$(ncal)".
After the sdorfehs change and switch to unix domain socket, sdorfehs now
uses a newline to mark the end of the command, and will therefore
silently truncate the sent message at the first newline.
This limitation can be removed; it's safe enough to go until we see a
NULL because it's always there:
- there's only one caller of send_command(), ie main() coming from
"sdorfehs -c" processing; since that comes from the program's
argument vector, we know it will always terminated by a NULL itself
- our buffer was fully cleared at entry, so a small read will be
terminated by the trailing initialized bytes
- if the sender exceeds our buffer size, it's already handled in the
code by checking that we reached the end and aborting with a
"bogus command length" message (this was verified by stepping
through with gdb using 'sdorfehs -c "$(ncal 2024)"')
Note that the end of buffer content comes before we might expect it
because the full command string is included: the "interactive" byte, the
command word itself, and the entire argument string.
Note also that code on both ends (sender and receiver) has to take
special care with the first byte, because it determines if the command
is interactive.
While this patch removes the newline limitation, this receiver code is
still limited by being able to use only a single buffer, and doing
character-at-a-time reads therefrom. To be addressed in following
commits.
Rather than process one buffer at a time and do partial outputs each
loop on every partial response (sent to us from receive_command()), we
make a buffer on the heap and keep growing it as long as there's still
data coming in the response. So we get the whole message before
attempting to process it.
As before, we go until either the other end closes (as it does at the
end of the transmission), or there's no more data to read (ie, another
read would block). The latter happens when we received the whole
response buffer, but the receiver hasn't yet finished closing the client
socket. Either of these scenarios means we're at the end of the
message.
The reason for separating receipt and disposition is so that processing
of the response buffer's contents becomes independent, out-of-band from
filling the buffer itself. This way, we can make the message-receive
loop into a utility function of its own, and re-use it in
receive_command() so it can be made to process arbitrarily sized
send_command() messages; it's currently limited to a single BUFSZ buffer
and is read one character at a time. Already, we are *sending* the
complete command argument (eg, from "sdorfehs -c"), but it will get
truncated by receive_command() if it exceeds the buffer size on the
other side. (Actually, we try to send the whole thing in a single
write() and will bail the whole WM on failure, which we probably need to
fix as well...)
probably the intention here was to support characters with values > 127
(ie iso_8859_1 chars), but there's no reason to use unsigned for this:
in C the string functions work just fine as their default type (char)
and don't require casting to support high-ascii characters.
of course, it still won't work with chars > 255, as before.
this change was tested with "sdorfehs -c $'echo \uab'" which correctly
shows the double-arrow, "left-pointing double angle quotation mark"
This is just an internal variable change, nothing user-facing.
growing the number (set vscreens N) at runtime would always grow one
extra: new set of vscreens had the last one indexed at N, rather than
N-1. this meant there was always one extra when we grew the vscreen
count. the end must be shifted by one left.
conversely, shrinking already worked correctly: the new set of vscreens
would have the last one indexed at N-1
Seems to help fix the annoying flashing that can happen in the input
bar when typing
Fixes an -fsanitize=address error (#58)
Fixes a use after free (#59)
libXft can't find the freetype headers on void linux, so add it to the
PKGLIBS.
Linux prefers $PREFIX/share/man/... for man files, so make that
easy to override during installation.
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.
All the exec'ed processes would get copies of the control socket
descriptors, because of the default UNIX semantics of fd inherit across
execv(). This was easily seen on my system where an 'lsof' revealed
that all my terminals and shells had a copy.
To fix this we add the SOCK_CLOEXEC flag whilst opening the listener
socket(), avoiding this problem. We also need to set CLOEXEC on the
socket returned by accept():
"accept() ... extracts the first connection request on the queue of
pending connections ... creates a new connected socket, and returns a
new file descriptor"
The new descriptor does not inherit CLOEXEC flag from the listener.
The "bar" descriptor already handles this by setting O_CLOEXEC in its
own open() call on the FIFO.
Both send_message() and receive_message() use writes: the former to send
to the latter, and then a reply is sent back from the latter to the
former. Both of them expected a single write to work unconditionally
without being able to tolerate any transient issues.
This commit factors out the writes into a common function called
send_unix() which serves as the companion to the recently added
recv_unix(). The send call is modified to handle both partial writes
and interrupted writes. Especially the latter is not that unlikely: it
can happen when we're in the middle of writing a message and then we get
interrupted by a SIGCHLD. This is not a difficult thing to happen
during the ordinary course of operations because the native 'exec' is
asynchronous. It was observed to happen during testing.
Partial writes might also be possible if some of the buffer was sent and
then got interrupted by a signal, but this probably can't happen at
the small BUFSZ we use. Nonetheless it will make the code more robust
to support the possibility of partial writes.
Any error besides EINTR is considered a fatal error for send_message()
because this is only called by a "client" invocation, ie "sdorfehs -c".
The "server" (ie receve_message()) only issues a warning and then aborts
processing the signal. Otherwise, it would die. This matches the
existing use of err() and warn() that was used after a mismatch in
written and wrote buffer sizes in the respective writers, prior to this
patch.
There are some transient conditions which are normal, such as an
interrupted system call, which can happen if sdorfehs received a signal
during processing, such as SIGCHLD when a forked process exited (a
completely normal situation). Of course, we should retry the syscall in
that case
. We can retry these after a small sleep of
200ms
both send_message() and receive_message()
This re-uses the code factored out from send_command() to receive the
sent command in multiple chunks into a dynamic heap buffer. Now we are
able to receive arbitrarily sized commands that span multiple BUFSZs.
This restores a regression from the original Ratpoison.
Example: 'sdorfehs -c "echo $(ncal 2024)"' will print the full year's
calendar as a message, it's over 2k bytes, so it will span 3 buffer
quanta (BUFSZ == 1024 at time of writing).
Here we make a new function recv_unix() that encapsulates the logic of
receiving a message from a unix domain socket (ie our control socket)
and copying it into a dynamically-sized heap buffer for disposition by
the caller. This will let us use it from other functions, in particular
from receive_command(), which is currently using a single buffer and
reading from the socket one character at a time. Since the logic for
doing this robustly was already implemented in send_command(), we can
just factor it out and use in both places.
Previously, we used a newline to mark the end of the message sent from
send_command(), which restricted the characters we could send across
(ie, we couldn't send a newline). This was a new limitation of sdorfehs
that was not present in ratpoison. In particular, "ratpoison -c echo"
was instrumented to be able to handle newlines in the message and draw
variable-height windows to show them (for example, "ratpoison -c
$(ncal)".
After the sdorfehs change and switch to unix domain socket, sdorfehs now
uses a newline to mark the end of the command, and will therefore
silently truncate the sent message at the first newline.
This limitation can be removed; it's safe enough to go until we see a
NULL because it's always there:
- there's only one caller of send_command(), ie main() coming from
"sdorfehs -c" processing; since that comes from the program's
argument vector, we know it will always terminated by a NULL itself
- our buffer was fully cleared at entry, so a small read will be
terminated by the trailing initialized bytes
- if the sender exceeds our buffer size, it's already handled in the
code by checking that we reached the end and aborting with a
"bogus command length" message (this was verified by stepping
through with gdb using 'sdorfehs -c "$(ncal 2024)"')
Note that the end of buffer content comes before we might expect it
because the full command string is included: the "interactive" byte, the
command word itself, and the entire argument string.
Note also that code on both ends (sender and receiver) has to take
special care with the first byte, because it determines if the command
is interactive.
While this patch removes the newline limitation, this receiver code is
still limited by being able to use only a single buffer, and doing
character-at-a-time reads therefrom. To be addressed in following
commits.
Rather than process one buffer at a time and do partial outputs each
loop on every partial response (sent to us from receive_command()), we
make a buffer on the heap and keep growing it as long as there's still
data coming in the response. So we get the whole message before
attempting to process it.
As before, we go until either the other end closes (as it does at the
end of the transmission), or there's no more data to read (ie, another
read would block). The latter happens when we received the whole
response buffer, but the receiver hasn't yet finished closing the client
socket. Either of these scenarios means we're at the end of the
message.
The reason for separating receipt and disposition is so that processing
of the response buffer's contents becomes independent, out-of-band from
filling the buffer itself. This way, we can make the message-receive
loop into a utility function of its own, and re-use it in
receive_command() so it can be made to process arbitrarily sized
send_command() messages; it's currently limited to a single BUFSZ buffer
and is read one character at a time. Already, we are *sending* the
complete command argument (eg, from "sdorfehs -c"), but it will get
truncated by receive_command() if it exceeds the buffer size on the
other side. (Actually, we try to send the whole thing in a single
write() and will bail the whole WM on failure, which we probably need to
fix as well...)
probably the intention here was to support characters with values > 127
(ie iso_8859_1 chars), but there's no reason to use unsigned for this:
in C the string functions work just fine as their default type (char)
and don't require casting to support high-ascii characters.
of course, it still won't work with chars > 255, as before.
this change was tested with "sdorfehs -c $'echo \uab'" which correctly
shows the double-arrow, "left-pointing double angle quotation mark"
growing the number (set vscreens N) at runtime would always grow one
extra: new set of vscreens had the last one indexed at N, rather than
N-1. this meant there was always one extra when we grew the vscreen
count. the end must be shifted by one left.
conversely, shrinking already worked correctly: the new set of vscreens
would have the last one indexed at N-1
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.