0

I ran two similar experiments. First one works, second one doesn't. What am I doing wrong? Setup for both experiments: I have two terminal windows (urxvt) side by side (i3 wm, ubuntu 18.04.4 LTS)

Experiment 1:

Type in left window:

$ wmctrl -r :ACTIVE: -T test                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

This changes left window title to 'test'.
Type in right window:

$ wmctrl -a test                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

This activates (changes focus) back to left window.
SUCCESS!

Experiment 2:

I want to do same thing, but using window id rather than window title. So...
Type in left window:

$ echo $WINDOWID                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
31457300                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

Type in right window:

$ wmctrl -i -a 31457300                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

Nothing happens.
FAILURE!

OK that's just an experiment. Here is what I really want to do:

I have several bash scripts, each of which runs until I kill it or reboot, each in its own window, on an alternate desktop I rarely look at. On rare occasion when script requires my attention, I want it to figure out what window it is running in and raise that window to the fore. "Figure out what window it is running in" I think is trivial - it's $WINDOWID. Using wmctrl to raise a window of known window ID should also be trivial, but I can't get it to work, as you see in experiment 2.

Alternate statement of problem:

I'd also be happy raising window by title rather than ID. Using wmctrl to raise a window by title is easy (wmctrl -a <title-or-fragment-thereof>). But I don't know how my bash script can discover the title of its window. There's no environment variable for that.

There is one solution I know about, and that works for me, but I don't like it. I know how to set the window title from bash, so hey I don't need to "discover" it, right? I could just set it instead (wmctrl -r :ACTIVE: -T SomeUniqueWindowTitle). Why don't I like this? Because I lose the original window title.

Here's another solution I don't like: each of the several bash scripts sets its window title already, and so the shared procedure could require a second argument - the window title. I could do that, but ... just wondering if there's a better, simpler way.

Thanks in advance!

10
  • Appears I have a typo. Command I use to raise window by title is "wmctrl -a xxx" where "xxx" is window title or fragment thereof. – Ken Apr 17 '20 at 15:51
  • If you made a typo, you can edit the post to correct it. Also, please use code formatting to format commands and output (askubuntu.com/editing-help#code) – muru Apr 17 '20 at 15:57
  • Are you sure the $WINDOWID variable is reliable? what does wmctrl -l say? – steeldriver Apr 17 '20 at 16:18
  • @steeldriver - Great question! wmctrl -l gives a different window ID. When I repeat experiment 2 using window ID from wmctrl -l ... SUCCESS! But there's a problem. wmctrl -l lists ALL windows ... how can a bash script (and my "shared procedure" is just another bash script) know which one is the one it is running in? – Ken Apr 17 '20 at 19:27
  • wmctrl -l gives same output regardless of from which window it is run. No way to know which one is 'me'. – Ken Apr 17 '20 at 20:31
0

I figured out how to do it. I apologize for my code, because (a) it's a mix of perl and bash, and (b) I'm no guru and I'm sure there's a better, simpler, more elegant way to do this. Anyway, this works for me. Your mileage may vary.

Bash command to raise to the fore the window in which it is running:

wmctrl -i -a $( my-window-id.pl )

my-window-id.pl should be executable and in your shell's search path. Or, if that's too much trouble, you could say instead:

wmctrl -i -a $( perl /path/to/my-window-id.pl )

and here is the source code for my-window-id.pl:

#!/usr/bin/perl
use warnings;
use strict;

# Print window ID of the window in which this script is running
# and exit with exit status 0.
# If it is not running in a window, print a message to stderr and
# exit with exit status 1.

# Determine my window ID based on "pstree -ps $$" and "wmctrl -lp".
# The pstree gives process ID of me and all my ancestors.
# One of those ancestors is my window (the window in which I am running).
# The wmctrl command gives a table of info on each active window,
# including each window's window ID and process ID.
# So if there exists a process ID that appears in output of both
# commands, then bingo that's my window's process ID, and the wmctrl
# table allows me to map that to a window ID.

my %pid_to_winid = ();
foreach my $raw_window_line ( split /\n/, `wmctrl -lp` ) {
    my ( $winid, undef, $pid ) = split /\s+/, $raw_window_line;
    $pid_to_winid{$pid} = $winid;
}

my $raw_pstree_out = `pstree -ps $$`;
my @pstree_pids    = $raw_pstree_out =~ m{ \( ( \d+ ) \) }gx;
foreach my $pid ( @pstree_pids ) {
    my $winid = $pid_to_winid{$pid};
    if ( $winid ) {
        print "$winid\n";
        exit 0;
    }
}

print STDERR "No window ID found for this process.\n";
exit 1;
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.