Dual or Multiple Monitors

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 [L1 ].


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"

HE 2017-05-24- BWidget has a strange behaviour with two monitors on my win7 32bit System (not fully tested but 64bit has the same issue). I have two monitors with different size. The primary monitor is configured to be below the secondary monitor. I opened two wish 8.6. The first one is placed on the primary monitor and the other on the secondary.

package require BWidget
winfo geometry .   ;# 1: 200x200+25+25 2: 200x200+607+-692

Now I open the progress bar of BWidget in both wish:

ProgressDlg .p
winfo geometry .   ;# 1: 200x200+25+25   2: 200x200+607+-692
winfo geometry .p  ;# 1: 243x77+845+1611 2: 243x77+845+1611  In both cases dialog box is displayed below primary monitor.

The progressbar can't be seen on both monitors. I changed the secondary monitor to be displayed below the primary one and the progress bar becomes visible.

winfo geometry .   ;# 1: 200x200+25+25   2: 200x200+607+1408
winfo geometry .p  ;# 1: 243x77+845+1611 2: 243x77+845+1611  In both cases dialog box is displayed below primary monitor.

Now changed back the secondary monitor to be above primary monitor

winfo geometry .   ;# 1: 200x200+25+25   2: 200x200+587+-692
winfo geometry .p  ;# 1: 243x77+825+-489 2: 243x77+825+-489
wm maxsize .       ;# 1: 1916 2074       2: 1916 2074

What we see is that the main toplevel windows will stay in place and the coordinates are changing depending of the position of the secondary monitor. This behaviour is as expected.

But the requester is displayed not as expected! Other application have two strategies to dispaly requester/dialog boxes. One is to display the requester at the same monitor as the main window. The other is to display the requester always at the primary monitor. I would prefer the first one (Better or additional I would like to have requester displayed relative to the mouse for faster working).

The requester in BWidget is always displayed below the primary monitor. Which means displayed outside the visible area in case the primary monitor is the bottom one. Moreover, the requester afterwards move with the position of the secondary monitor. So the toplevel handling works as expected. But, the creation routine of the requester has problems to place the requester properly.