1#!/usr/bin/perl 2# 3# panner.pl: start up x11vnc in '-clip' mode viewing a small (WxH) 4# rectangular region of the screen. Allow the viewer user 5# to 'pan' around the display region by moving the mouse. 6# 7# Remote interaction with applications, e.g. clicking a 8# button though the VNC viewer, will be very difficult. 9# This may be useful in a 'demo' mode where the user sitting 10# at the physical display is the only one moving the mouse. 11# Depending on your usage the following x11vnc options may 12# be useful: -nonap 13# 14# Usage: panner.pl WxH <x11vnc-args> (e.g. -display ...) 15# or panner.pl WxH:0.05 <x11vnc-args> (e.g. 0.05 is polling time in secs.) 16 17use strict; 18 19my $WxH = shift; 20my $poll_time; 21 22# split off poll time: 23# 24($WxH, $poll_time) = split(/:/, $WxH); 25my ($W, $H) = split(/x/, $WxH); 26 27$poll_time = 0.1 unless $poll_time ne ''; 28 29# set to x11vnc command (e.g. full PATH) 30# 31my $x11vnc = "x11vnc"; 32 33# check if display was given: 34# 35my $query_args = ""; 36for (my $i=0; $i < @ARGV; $i++) { 37 if ($ARGV[$i] eq '-display') { 38 $query_args = "-display $ARGV[$i+1]"; 39 } 40} 41 42# find the size of display and the current mouse position: 43my %v; 44vset("DIRECT:wdpy_x,wdpy_y,pointer_x,pointer_y,pointer_same"); 45 46# set a -clip argument based on the above: 47# 48my $clip = ''; 49clip_set(); 50$clip = "${W}x${H}+0+0" unless $v{pointer_same}; 51 52# launch x11vnc with -clip in the background: 53# 54my $cmd = "$x11vnc -clip $clip -bg " . join(" ", @ARGV); 55print STDERR "running: $cmd\n"; 56system $cmd; 57 58# user can hit Ctrl-C or kill this script to quit (and stop x11vnc) 59# 60sub quit { 61 system("$x11vnc $query_args -R stop"); 62 exit 0; 63} 64 65$SIG{INT} = \&quit; 66$SIG{TERM} = \&quit; 67 68# loop forever waiting for mouse position to change, then shift -clip: 69# 70my $clip_old = $clip; 71while (1) { 72 fsleep($poll_time); 73 vset("pointer_x,pointer_y,pointer_same"); 74 next unless $v{pointer_same}; 75 clip_set(); 76 if ($clip ne $clip_old) { 77 system("$x11vnc $query_args -R clip:$clip"); 78 $clip_old = $clip 79 } 80} 81 82exit 0; 83 84# short sleep: 85# 86sub fsleep { 87 my ($time) = @_; 88 select(undef, undef, undef, $time) if $time; 89} 90 91# set the -clip string, making sure view doesn't go off edges of display: 92# 93sub clip_set { 94 my $x = int($v{pointer_x} - $W/2); 95 my $y = int($v{pointer_y} - $H/2); 96 $x = 0 if $x < 0; 97 $y = 0 if $y < 0; 98 $x = $v{wdpy_x} - $W if $x + $W > $v{wdpy_x}; 99 $y = $v{wdpy_y} - $H if $y + $H > $v{wdpy_y}; 100 $clip = "${W}x${H}+$x+$y"; 101} 102 103# query x11vnc for values, put results in the %v hash: 104# 105sub vset { 106 my $str = shift; 107 my $out = `$x11vnc $query_args -Q $str 2>/dev/null`; 108 chomp $out; 109 foreach my $pair (split(/,/, $out)) { 110 $pair =~ s/^a..=//; 111 my ($k, $v) = split(/:/, $pair, 2); 112 if ($k ne '' && $v ne '') { 113 print STDERR "k=$k v=$v\n" if $ENV{DEBUG}; 114 $v{$k} = $v; 115 } 116 } 117} 118