lilphil has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

A short question today, but possibly not that simple.
Does anyone happen to know if it is possible to retrieve the current screen resolution? And just as importantly, the screen resolution for each monitor with Xinerama?

TIA
Phil

Replies are listed 'Best First'.
Re: Getting screen resolution
by Ao (Friar) on Feb 10, 2004 at 01:43 UTC
    lilphil, you could use Perl/Tk and create a widget on each display. Then use
        $height = $widget->screenheight; $width = $widget->screenwidth; $depth = $widget->screendepth; to capture the dimensions of the screen.

    Repeat the process for the widget(s) on the other screen(s). Then, if you don't want a GUI, destroy the main widget.

Re: Getting screen resolution
by DrHyde (Prior) on Feb 10, 2004 at 09:20 UTC
    Perhaps some variation on `xwininfo ...`? On this 'ere machine, xwininfo -root returns the correct info. How well it works with Xinerama I don't know. Don't rely on it being portable, as the format of the data it returns may differ.

    If you really want to be portable, look at X11::Protocol:

    use X11::Protocol; my $x = X11::Protocol->new(); print $x->{screens}->[0]->{width_in_pixels} . ' x ' . $x->{screens}->[0]->{height_in_pixels} . "\n";
    I haven't been able to test this with Xinerama, but some variation on that theme should do the trick.
Re: Getting screen resolution
by calin (Deacon) on Feb 10, 2004 at 15:27 UTC
    The following code example parses the output of xdpyinfo(1x) program. You need the base X client utilities from XFree86 installed (don't know about compatibility with other X distributions).

    #!/usr/bin/perl use Data::Dumper; my ($scr, $curr_scr, %screens); open my $fh, "xdpyinfo|" or die; while (<$fh>) { $scr = $1 if m/^\s*screen\s+#(\d+):/; $curr_scr = $1 if m/^\s*default screen number:\s+(\d+)/; @{$screens{$scr}}{'x','y'} = ($1, $2) if m/^\s*dimensions:\s+(\d+)x(\d+)/; } close $fh; print "Current screen: $curr_scr\n\n"; print Dumper \%screens;

    with the following output on an Xnest with four screens :

    Current screen: 2 $VAR1 = { '1' => { 'y' => '576', 'x' => '768' }, '3' => { 'y' => '576', 'x' => '768' }, '0' => { 'y' => '576', 'x' => '768' }, '2' => { 'y' => '576', 'x' => '768' } };

    I don't know how/if the Xinerama screens map to historic X server screens, though (I'm not familiar with Xinerama). Try and see if it works.

      Thanks to all.

      Unfortunatly, as it turns out, xwininfo, xdpyinfo and X11::Protocol report a single screen under xinerama (2432x1064 in my case), but this is a good start.
      I think Ao's idea will work, although it could be difficult to ensure the windows maximise over the top of the task bar. I'm going to have a think about that one, largely because i've never used Perl/TK :)

      Any further ideas welcome.
      Thanks,
      Phil

        Sorry for the delay - 2004 was before my time on PerlMonks...

        Today, xrandr would be the tool of choice:

        qwurx [shmem] ~ > xrandr Screen 0: minimum 320 x 200, current 2944 x 1200, maximum 4096 x 4096 VGA-0 connected 1920x1200+0+0 (normal left inverted right x axis y axi +s) 518mm x 324mm 1920x1200 60.0*+ 1280x1024 75.0 1152x864 75.0 1024x768 75.1 70.1 60.0 832x624 74.6 800x600 72.2 75.0 60.3 56.2 640x480 72.8 75.0 66.7 60.0 720x400 70.1 0x0 0.0 DVI-0 disconnected (normal left inverted right x axis y axis) LVDS connected 1024x768+1920+0 (normal left inverted right x axis y ax +is) 0mm x 0mm 1024x768 60.0*+ 60.0 800x600 60.3 56.2 640x480 59.9

        I'd parse that as follows, to get the current Xinerama screen portion a toplevel is in. Crude hack...

        my ($W, $H); # width and height of current display { (my $screennumber = $ENV{DISPLAY}) =~ s/:(\w+\.)?//; my $screenfound = 0; open my $fh, '-|', 'xdpyinfo' or die "Can't run xdpyinfo: $!\n"; while(<$fh>) { $screenfound++ if /screen #$screennumber:/; next unless $screenfound; if(/dimensions:\s+(\d+)x(\d+)/) { ($W,$H) = ($1,$2); 1 while <I>; } } close $fh; } # get_area - get the current Xinerama screen portion # # input: $window - a Toplevel Tk window # return: # $ox: offset x # $oy: offset y # $w: width # $w: height sub get_area { my $window = shift; chomp (my $xrandr = `which xrandr`); my ($ox, $oy, $w, $h); if ($xrandr) { open my $fh, '-|', $xrandr or die "Can't run xrandr: $!\n"; my @a; while(<$fh>) { /\bconnected (\d+)x(\d+)\+(\d+)\+(\d+)/ and push @a, { w => $1, h => $2, x => $3, y => $4 }; } if (1 < @a) { # find current offset my @g = $window->geometry =~ /(\d+)x(\d+)([\+-])(\d+)\+(\d ++)/; $g[3] += $W-$g[0] if $g[2] eq '-'; splice @g,2,1; my %g; @g{qw(w h x y)} = @g; my ($min,$max) = ($a[0]->{w} >= $a[1]->{w} && $a[0]->{h} >= $a[1]->{h}) ? reverse @a : @a; if( $g{x} >= $min->{x} && $g{y} >= $min->{y} && $g{x}+$g{w} <= $min->{x}+$min->{w} && $g{y}+$g{h} <= $min->{y}+$min->{h} ) { $ox = $min->{x}; $oy = $min->{y}; $w = $min->{w}; $h = $min->{h}; } else { $ox = $max->{x}; $oy = $max->{y}; $w = $max->{w}; $h = $max->{h}; } } } ($ox, $oy, $w, $h); }

        Heh... does this post make sense, more than five years later? ;-)