Updated 2016-02-26 07:59:43 by kpv

Try to determine if we are operating on a system with dual monitors. It even handles switching modes mid-execution. At least on Windows. The maxsize command seems to keep up with the changes to the display. Damon Courtney
proc DualMonitors {} {
    set top .#dualMonitorCheck#
    if {![winfo exists $top]} { toplevel $top; wm withdraw $top }
    set sw [winfo screenwidth $top]
    set mw [lindex [wm maxsize .] 0]
    return [expr {($sw * 2) < $mw}]
}

RT quick news flash: twapi now supports the bare Windows api needed for multi-monitor work according to the author. And there is now a high level Tcl interface as well. See get_display_* Changes in CVS, not yet in an official release (aimed at 2.0) - 9Mar07

This doesn't work when running wish on MacOSX with X11. I've got dual monitors but the proc returns 0. For my setup, the value for sw is 2624 (1600 + 1024) and the value of mw is (curiously) 2609.

DKF: Hmm. [winfo screenwidth] only reports the width of the primary monitor.

PT: The standard Windows multiple screen setup extends your desktop over N monitors but depending upon where you get your information from, the desktop size is returned as the size of the primary monitor whose top left coordinate is set as 0,0. This helps applications that try to center windows to actually center them in a monitor and not split them over two monitors. This has the interesting effect of setting a monitor to the left or above to have negative coordinates. Thus [wm geometry . 100x100+-1000+100] is a valid geometry string (note the +-). BWidgets and parts of Tk have been modified to accomodate this, but this is the first time I have seen an example of how to get the available workspace size within Tk.

So my system which has the secondary monitor to the left of the primary yields:
% list [winfo screenwidth $top] [winfo screenheight $top]
1152 864
% wm maxsize $top
2308 842

I account for the difference in vertical size as the space reserved for the XP Start bar. And I'm guessing that horizontally its adding some borderwidth space (we have an extra 4 pixels). Handilly
% expr [lindex [wm maxsize $top] 0] / [winfo screenwidth $top]
2

which is corrent for this setup, but doesn't say anything about the possible coordinate range. Here windows may be placed from -1152 to +1152. If I set the leftmost monitor as primary, then my range would be 0 - 2304. This can be important for trying to decide if a window or menu is going to fall off the edge of the viewable area (done in BWidgets and Tk).

If we can find some way to identify the coordinate range too, then I know a Tk bug we can close :)

LV DualMonitors doesn't work for me either. I have dual monitors, controled by Windows XP and then, via Exceed, running Sun GNOME on a SPARC. Oh, and I have the dual monitors running in "Cinematic" mode - i.e. they display one extra wide desktop, where I can drag X or Windows apps from one scren to the other. Another thing I have is that the two monitors run at different resolutions... Shrug.

When I run the Solaris Tcl/Tk (8.5a6) from Sun, what I see is DualMonitors returning a 0, $sw having a value of 2304, and mw having a value of 2289.

Just to really make things crazy, when I run the proc on Windows XP directly, using Tk 8.4.10, I get a 1 returned from DualMonitors, with $sw = 1024 and $mw = 2308. This is the same two monitors - just using a different version of Tk...

jnc What about this proc, does it not answer the question "Do I have dual monitors?" I am unsure, though, on some linux desktops that may have virtual sizes set.
proc is_dual_monitors {} {
    if { [winfo screenwidth .] < [lindex [wm maxsize .] 0] } {
        return yes
    }
    return no
}

Related links:

Documenting 'wm geometry' -- Screen geometry & coordinates are not uniform across platforms.

Total Window Geometry -- This also covers some of the cross-platform issues regarding screen measurements. Note that one Windows-specific way to handle such problems is to call TWAPI functions directly, such as "twapi::get_desktop_workarea".

Check geometry on Aqua

Also notice this SF item [1].

LG - 2016-02-25 15:59:20

I had the same problems as LV so i came up with a workaround. It uses the linux function xrandr which gives you information about the screensize.
catch {exec xrandr > ~/temp/screenres.txt}

set scre [open ~/temp/screenres.txt r]
set i 1
set screenarea 0
while { [eof $scre] == 0 } {
  set zeile [gets $scre]
  if {[lsearch $zeile "*x*+*+*"] > -1} {
    set screenr [lindex $zeile [lsearch $zeile "*x*+*+*"]]
    set screenx_$i [lindex [split $screenr "x+"] 0]
    set screeny_$i [lindex [split $screenr "x+"] 1]
    set screenxoff_$i [lindex [split $screenr "x+"] 2]
    set screenyoff_$i [lindex [split $screenr "x+"] 3]
    if {[expr {[set screenx_$i] * [set screeny_$i]}] > $screenarea} {set screenarea [expr {[set screenx_$i] * [set screeny_$i]}] ; set ii $i}
    incr i
  }
}
set sw [set screenx_$ii]
set sh [expr {[set screeny_$ii]-30}]

kpv 2016-02-25 -- the above can be re-written more concisely
set screenData [exec xrandr]  ;# Just die if error
set sw [set sh 0]
foreach line [split [string trim $screenData] \n] {
    if {[regexp {(\d+)x(\d+)\+(\d+)\+(\d+)} $line . screenX screenY screenXOff screenYOff]} {
        if {$screenX * $screenY > $sw * $sh} {
            set sw $screenX
            set sh $screenY
        }
    }
}
incr sh -30  ;# Not sure why, but just copying the code
puts "sw: $sw  sh: $sh"