1a5ae21e4Smrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: setpos.pl,v 1.18 2019/05/26 23:19:29 tom Exp $ 3a5ae21e4Smrg# ----------------------------------------------------------------------------- 4a5ae21e4Smrg# Copyright 2019 by Thomas E. Dickey 5a5ae21e4Smrg# 6a5ae21e4Smrg# All Rights Reserved 7a5ae21e4Smrg# 8a5ae21e4Smrg# Permission is hereby granted, free of charge, to any person obtaining a 9a5ae21e4Smrg# copy of this software and associated documentation files (the 10a5ae21e4Smrg# "Software"), to deal in the Software without restriction, including 11a5ae21e4Smrg# without limitation the rights to use, copy, modify, merge, publish, 12a5ae21e4Smrg# distribute, sublicense, and/or sell copies of the Software, and to 13a5ae21e4Smrg# permit persons to whom the Software is furnished to do so, subject to 14a5ae21e4Smrg# the following conditions: 15a5ae21e4Smrg# 16a5ae21e4Smrg# The above copyright notice and this permission notice shall be included 17a5ae21e4Smrg# in all copies or substantial portions of the Software. 18a5ae21e4Smrg# 19a5ae21e4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20a5ae21e4Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21a5ae21e4Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22a5ae21e4Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23a5ae21e4Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24a5ae21e4Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25a5ae21e4Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26a5ae21e4Smrg# 27a5ae21e4Smrg# Except as contained in this notice, the name(s) of the above copyright 28a5ae21e4Smrg# holders shall not be used in advertising or otherwise to promote the 29a5ae21e4Smrg# sale, use or other dealings in this Software without prior written 30a5ae21e4Smrg# authorization. 31a5ae21e4Smrg# ----------------------------------------------------------------------------- 32a5ae21e4Smrg# Exercise CSI 3/13 t which set/get the window position. 33a5ae21e4Smrg 34a5ae21e4Smrguse strict; 35a5ae21e4Smrg 36a5ae21e4Smrguse Getopt::Std; 37a5ae21e4Smrguse IO::Handle; 38a5ae21e4Smrg 39a5ae21e4Smrg$| = 1; 40a5ae21e4Smrg 41a5ae21e4Smrgour ( $opt_a, $opt_n, $opt_p, $opt_v, $opt_x, $opt_8 ); 42a5ae21e4Smrgour $default_y = 100; 43a5ae21e4Smrgour $default_x = 150; 44a5ae21e4Smrg 45a5ae21e4Smrgsub main::HELP_MESSAGE() { 46a5ae21e4Smrg printf STDERR <<EOF 47a5ae21e4SmrgUsage: $0 [options] 48a5ae21e4SmrgOptions: 49a5ae21e4Smrg -8 use 8-bit controls 50a5ae21e4Smrg -a test position/report for middle and four corners 51a5ae21e4Smrg -n N repeat unless -a option used (default: 3) 52a5ae21e4Smrg -p Y,X use this position rather than $default_y,$default_x 53a5ae21e4Smrg -v verbose 54a5ae21e4Smrg -x report xwininfo's position for \$WINDOWID 55a5ae21e4SmrgEOF 56a5ae21e4Smrg ; 57a5ae21e4Smrg exit 1; 58a5ae21e4Smrg} 59a5ae21e4Smrg 60a5ae21e4Smrg$Getopt::Std::STANDARD_HELP_VERSION = 1; 61a5ae21e4Smrg&getopts('an:p:vx8') || &main::HELP_MESSAGE; 62a5ae21e4Smrg 63a5ae21e4Smrgour $repeat = 3; 64a5ae21e4Smrg$repeat = $opt_n if ($opt_n); 65a5ae21e4Smrg&main::HELP_MESSAGE unless ( $repeat =~ /^\d+$/ ); 66a5ae21e4Smrg 67a5ae21e4Smrgour $CSI = "\x1b\["; 68a5ae21e4Smrg$CSI = "\x9b" if ($opt_8); 69a5ae21e4Smrg 70a5ae21e4Smrgif ($opt_p) { 71a5ae21e4Smrg &main::HELP_MESSAGE unless ( $opt_p =~ /^[-]?\d+,[-]?\d+$/ ); 72a5ae21e4Smrg my @coord = split /,/, $opt_p; 73a5ae21e4Smrg $default_y = $coord[0]; 74a5ae21e4Smrg $default_x = $coord[1]; 75a5ae21e4Smrg} 76a5ae21e4Smrg 77a5ae21e4Smrgour $wm_name = "unknown"; 78a5ae21e4Smrgour @extents; 79a5ae21e4Smrg 80a5ae21e4Smrgsub no_reply($) { 81a5ae21e4Smrg open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n"); 82a5ae21e4Smrg autoflush TTY 1; 83a5ae21e4Smrg my $old = `stty -g`; 84a5ae21e4Smrg system "stty raw -echo min 0 time 5"; 85a5ae21e4Smrg 86a5ae21e4Smrg print TTY @_; 87a5ae21e4Smrg close TTY; 88a5ae21e4Smrg system "stty $old"; 89a5ae21e4Smrg} 90a5ae21e4Smrg 91a5ae21e4Smrgsub get_reply($) { 92a5ae21e4Smrg open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n"); 93a5ae21e4Smrg autoflush TTY 1; 94a5ae21e4Smrg my $old = `stty -g`; 95a5ae21e4Smrg system "stty raw -echo min 0 time 5"; 96a5ae21e4Smrg 97a5ae21e4Smrg print TTY @_; 98a5ae21e4Smrg my $reply = <TTY>; 99a5ae21e4Smrg close TTY; 100a5ae21e4Smrg system "stty $old"; 101a5ae21e4Smrg if ( defined $reply ) { 102a5ae21e4Smrg die("^C received\n") if ( "$reply" eq "\003" ); 103a5ae21e4Smrg } 104a5ae21e4Smrg return $reply; 105a5ae21e4Smrg} 106a5ae21e4Smrg 107a5ae21e4Smrgsub read_cmd($) { 108a5ae21e4Smrg my $cmd = shift; 109a5ae21e4Smrg my @result; 110a5ae21e4Smrg if ( open my $fh, "$cmd |" ) { 111a5ae21e4Smrg @result = <$fh>; 112a5ae21e4Smrg close $fh; 113a5ae21e4Smrg chomp @result; 114a5ae21e4Smrg } 115a5ae21e4Smrg return @result; 116a5ae21e4Smrg} 117a5ae21e4Smrg 118a5ae21e4Smrgsub get_xprop($$) { 119a5ae21e4Smrg my $id = shift; 120a5ae21e4Smrg my $name = shift; 121a5ae21e4Smrg my @data = &read_cmd("xprop -id $id"); 122a5ae21e4Smrg my $prop = ""; 123a5ae21e4Smrg for my $n ( 0 .. $#data ) { 124a5ae21e4Smrg if ( $data[$n] =~ /$name\([^)]+\) =/ ) { 125a5ae21e4Smrg $prop = $data[$n]; 126a5ae21e4Smrg $prop =~ s/^[^=]*=\s*//; 127a5ae21e4Smrg $prop =~ s/"//g; 128a5ae21e4Smrg last; 129a5ae21e4Smrg } 130a5ae21e4Smrg } 131a5ae21e4Smrg return $prop; 132a5ae21e4Smrg} 133a5ae21e4Smrg 134a5ae21e4Smrgsub visible($) { 135a5ae21e4Smrg my $reply = $_[0]; 136a5ae21e4Smrg my $n; 137a5ae21e4Smrg my $result = ""; 138a5ae21e4Smrg for ( $n = 0 ; $n < length($reply) ; ) { 139a5ae21e4Smrg my $c = substr( $reply, $n, 1 ); 140a5ae21e4Smrg if ( $c =~ /[[:print:]]/ ) { 141a5ae21e4Smrg $result .= $c; 142a5ae21e4Smrg } 143a5ae21e4Smrg else { 144a5ae21e4Smrg my $k = ord substr( $reply, $n, 1 ); 145a5ae21e4Smrg if ( ord $k == 0x1b ) { 146a5ae21e4Smrg $result .= "\\E"; 147a5ae21e4Smrg } 148a5ae21e4Smrg elsif ( $k == 0x7f ) { 149a5ae21e4Smrg $result .= "^?"; 150a5ae21e4Smrg } 151a5ae21e4Smrg elsif ( $k == 32 ) { 152a5ae21e4Smrg $result .= "\\s"; 153a5ae21e4Smrg } 154a5ae21e4Smrg elsif ( $k < 32 ) { 155a5ae21e4Smrg $result .= sprintf( "^%c", $k + 64 ); 156a5ae21e4Smrg } 157a5ae21e4Smrg elsif ( $k > 128 ) { 158a5ae21e4Smrg $result .= sprintf( "\\%03o", $k ); 159a5ae21e4Smrg } 160a5ae21e4Smrg else { 161a5ae21e4Smrg $result .= chr($k); 162a5ae21e4Smrg } 163a5ae21e4Smrg } 164a5ae21e4Smrg $n += 1; 165a5ae21e4Smrg } 166a5ae21e4Smrg 167a5ae21e4Smrg return $result; 168a5ae21e4Smrg} 169a5ae21e4Smrg 170a5ae21e4Smrgsub limited($) { 171a5ae21e4Smrg my $value = shift; 172a5ae21e4Smrg if ( $value >= 65536 ) { 173a5ae21e4Smrg $value %= 65536; 174a5ae21e4Smrg } 175a5ae21e4Smrg if ( $value >= 32768 ) { 176a5ae21e4Smrg $value -= 65536; 177a5ae21e4Smrg } 178a5ae21e4Smrg return $value; 179a5ae21e4Smrg} 180a5ae21e4Smrg 181a5ae21e4Smrgsub check_position($$$) { 182a5ae21e4Smrg my $name = shift; 183a5ae21e4Smrg my $expect = shift; 184a5ae21e4Smrg my $actual = shift; 185a5ae21e4Smrg printf " ?%s:%d", $name, $expect if ( $expect != $actual ); 186a5ae21e4Smrg} 187a5ae21e4Smrg 188a5ae21e4Smrgsub report_position() { 189a5ae21e4Smrg my $reply = &get_reply( sprintf "%s13t", $CSI ); 190a5ae21e4Smrg my $status = 0; 191a5ae21e4Smrg my @result; 192a5ae21e4Smrg if ( index( $reply, $CSI ) == 0 ) { 193a5ae21e4Smrg $reply = substr( $reply, length($CSI) ); 194a5ae21e4Smrg $status = 1; 195a5ae21e4Smrg } 196a5ae21e4Smrg if ( $reply =~ /^3;\d+;\d+t$/ ) { 197a5ae21e4Smrg my $y = $reply; 198a5ae21e4Smrg $y =~ s/^3;(\d+);.*/$1/; 199a5ae21e4Smrg my $x = $reply; 200a5ae21e4Smrg $x =~ s/^3;\d+;(\d+).*/$1/; 201a5ae21e4Smrg $result[0] = &limited($y); 202a5ae21e4Smrg $result[1] = &limited($x); 203a5ae21e4Smrg printf "OK ->%s ->%d,%d", &visible($reply), $result[0], $result[1]; 204a5ae21e4Smrg } 205a5ae21e4Smrg else { 206a5ae21e4Smrg printf "ERR ->%s", &visible($reply); 207a5ae21e4Smrg } 208a5ae21e4Smrg if ( $opt_x and $ENV{WINDOWID} ) { 209a5ae21e4Smrg my @actual = `xwininfo -id $ENV{WINDOWID} | grep " upper-left [XY]:"`; 210a5ae21e4Smrg for my $n ( 0 .. $#actual ) { 211a5ae21e4Smrg $actual[$n] =~ s/^.*:\s+//; 212a5ae21e4Smrg } 213a5ae21e4Smrg if ( $#actual == 3 ) { 214a5ae21e4Smrg printf " abs(%d,%d) rel(%d,%d)", $actual[0], $actual[1], 215a5ae21e4Smrg $actual[2], $actual[3] 216a5ae21e4Smrg if ($opt_v); 217a5ae21e4Smrg my $expect_y; 218a5ae21e4Smrg my $expect_x; 219a5ae21e4Smrg if ( $wm_name =~ /^gnome/i ) { 220a5ae21e4Smrg $expect_x = $actual[0] - ( $extents[0] + $extents[1] ); 221a5ae21e4Smrg $expect_y = $actual[1] - ( $extents[2] + $extents[3] ); 222a5ae21e4Smrg } 223a5ae21e4Smrg elsif ( $#extents == 3 224a5ae21e4Smrg and ( $wm_name !~ /^fvwm/i ) 225a5ae21e4Smrg and ( $wm_name !~ /^enlightenment/i ) ) 226a5ae21e4Smrg { 227a5ae21e4Smrg $expect_x = $actual[0] - ( $extents[0] ); 228a5ae21e4Smrg $expect_y = $actual[1] - ( $extents[2] ); 229a5ae21e4Smrg } 230a5ae21e4Smrg else { 231a5ae21e4Smrg $expect_x = $actual[0] - $actual[2]; 232a5ae21e4Smrg $expect_y = $actual[1] - $actual[3]; 233a5ae21e4Smrg } 234a5ae21e4Smrg if ( $#result > 0 ) { 235a5ae21e4Smrg &check_position( "X", $expect_x, $result[0] ); 236a5ae21e4Smrg &check_position( "Y", $expect_y, $result[1] ); 237a5ae21e4Smrg } 238a5ae21e4Smrg } 239a5ae21e4Smrg } 240a5ae21e4Smrg printf "\n"; 241a5ae21e4Smrg return @result; 242a5ae21e4Smrg} 243a5ae21e4Smrg 244a5ae21e4Smrgsub update_position() { 245a5ae21e4Smrg my @pos = @{ $_[0] }; 246a5ae21e4Smrg printf "** update %d,%d\n", $pos[0], $pos[1]; 247a5ae21e4Smrg $pos[0] += 65536 if ( $pos[0] < 0 ); 248a5ae21e4Smrg $pos[1] += 65536 if ( $pos[1] < 0 ); 249a5ae21e4Smrg &no_reply( sprintf "%s3;%d;%dt", $CSI, $pos[0], $pos[1] ); 250a5ae21e4Smrg} 251a5ae21e4Smrg 252a5ae21e4Smrgsub update_and_report($) { 253a5ae21e4Smrg my @pos = @{ $_[0] }; 254a5ae21e4Smrg &update_position( \@pos ); 255a5ae21e4Smrg sleep 1 if ($opt_a); 256a5ae21e4Smrg return &report_position; 257a5ae21e4Smrg} 258a5ae21e4Smrg 259a5ae21e4Smrgsub get_screensize() { 260a5ae21e4Smrg my $reply = &get_reply( sprintf "%s15t", $CSI ); 261a5ae21e4Smrg my @result; 262a5ae21e4Smrg if ( index( $reply, $CSI ) == 0 ) { 263a5ae21e4Smrg $reply = substr( $reply, length($CSI) ); 264a5ae21e4Smrg if ( $reply =~ /^5;\d+;\d+t$/ ) { 265a5ae21e4Smrg my $y = $reply; 266a5ae21e4Smrg $y =~ s/^5;(\d+);.*/$1/; 267a5ae21e4Smrg my $x = $reply; 268a5ae21e4Smrg $x =~ s/^5;\d+;(\d+).*/$1/; 269a5ae21e4Smrg $result[0] = $x; 270a5ae21e4Smrg $result[1] = $y; 271a5ae21e4Smrg } 272a5ae21e4Smrg } 273a5ae21e4Smrg return @result; 274a5ae21e4Smrg} 275a5ae21e4Smrg 276a5ae21e4Smrgsub doit() { 277a5ae21e4Smrg my @old = &report_position; 278a5ae21e4Smrg if ($opt_a) { 279a5ae21e4Smrg my @size = &get_screensize; 280a5ae21e4Smrg if (@size) { 281a5ae21e4Smrg printf "Screen %dx%d\n", $size[0], $size[1]; 282a5ae21e4Smrg my $ulx = -$default_x; 283a5ae21e4Smrg my $uly = -$default_y; 284a5ae21e4Smrg my $lrx = $size[0] - $default_x; 285a5ae21e4Smrg my $lry = $size[1] - $default_y; 286a5ae21e4Smrg &update_and_report( [ $ulx, $uly ] ); 287a5ae21e4Smrg &update_and_report( [ $ulx, $lry ] ); 288a5ae21e4Smrg &update_and_report( [ $lrx, $lry ] ); 289a5ae21e4Smrg &update_and_report( [ $lrx, $uly ] ); 290a5ae21e4Smrg &update_position( \@old ); 291a5ae21e4Smrg } 292a5ae21e4Smrg } 293a5ae21e4Smrg else { 294a5ae21e4Smrg my @pos = ( $default_y, $default_x ); 295a5ae21e4Smrg for my $n ( 1 .. $repeat ) { 296a5ae21e4Smrg @pos = &update_and_report( \@pos ); 297a5ae21e4Smrg } 298a5ae21e4Smrg } 299a5ae21e4Smrg} 300a5ae21e4Smrg 301a5ae21e4Smrgprintf "\x1b G" if ($opt_8); 302a5ae21e4Smrg 303a5ae21e4Smrgif ( $opt_x and $ENV{WINDOWID} ) { 304a5ae21e4Smrg my $extents = &get_xprop( $ENV{WINDOWID}, "_NET_FRAME_EXTENTS" ); 305a5ae21e4Smrg if ( $extents ne "" ) { 306a5ae21e4Smrg @extents = split /,\s*/, $extents; 307a5ae21e4Smrg printf "** has EWMH extents: $extents\n"; 308a5ae21e4Smrg my $supwin = `xprop -root '_NET_SUPPORTING_WM_CHECK'`; 309a5ae21e4Smrg if ( $supwin ne "" ) { 310a5ae21e4Smrg $supwin =~ s/^.*(0x[[:xdigit:]]+).*/$1/; 311a5ae21e4Smrg $wm_name = &get_xprop( $supwin, "_NET_WM_NAME" ); 312a5ae21e4Smrg $wm_name = "unknown" unless ( $wm_name ne "" ); 313a5ae21e4Smrg printf "** using \"$wm_name\"\n"; 314a5ae21e4Smrg } 315a5ae21e4Smrg } 316a5ae21e4Smrg} 317a5ae21e4Smrg 318a5ae21e4Smrg&doit; 319a5ae21e4Smrg 320a5ae21e4Smrgprintf "\x1b F" if ($opt_8); 321a5ae21e4Smrg 322a5ae21e4Smrg1; 323