0095: Hardware II – Full Monitor Report
This time, we’re looking for more than just a monitor head count. We can get the resolution of each monitor in a multi-monitor Seat
, each monitor’s position within the Screen
(or Seat
, if you prefer), the model and, since we’ll have all the information we’ll need at our fingertips, let’s also find out which monitor our Window
is on at any given time. This fulfills a request made by GreatSam4Sure on forum.dlang.org.
Window Location & Other Stuff
To accomplish all this, we’re going to need a whole raft of imports, so as well as the ones we used from last time, we need to add these:
import gtk.Button;
import gdk.Device;
import gdk.Seat;
import gdk.Window;
import gdk.Rectangle;
import gdk.MonitorG;
import gdk.Screen;
The reason we need the first import is obvious. The Button
created will, when pressed, tell us which monitor the window is on. The rest are for gathering the information we want and we’ll go over them as we come to them.
TestRigWindow Class Preamble
Here in the class preamble, we get set up to gather the info:
Screen screen;
ReportButton reportButton;
How they’re used:
screen
: the defaultScreen
used by our application,reportButton
: which, as stated above, will be used to tell us which monitor theWindow
is on at any given time. (If you’ve got a multi-monitorSeat
, try moving the window from one to another and then clicking the button.)
The Constructor
Here, we also have a bit more to do:
this()
{
super(title);
myDisplay = Display.getDefault();
monitorReport();
screen = Screen.getDefault();
writeln("screen width: ", screen.width(), ", height: ", screen.height());
reportButton = new ReportButton(myDisplay);
add(reportButton);
addOnDestroy(&quitApp);
showAll();
} // this()
Besides calling monitorReport()
to dump all the monitor information to the terminal, we also:
- grab a pointer to the default
Screen
(from which all the other info is gleaned), and - instantiate the
reportButton
, passing it a pointer to the defaultDisplay
.
We don’t have to pass this pointer. Because the Display
is the default Display
, it’s accessible from anywhere within our application. And that means we could just grab a pointer to the default Display
from within the reportButton
constructor instead. Either way works, but…
For the TestRigWindow.monitorReport()
function to work, we need a pointer to the default Display
there as well, so we might as well leave it there in the TestRigWindow
constructor and pass it to the ReportButton
. Then if, sometime down the road, we decide to change the way we’re handling the Display
pointer, we only have to rework it in one place.
The monitorReport() Function
Here’s the function where it all happens:
void monitorReport()
{
MonitorG monitorG;
GdkRectangle rectangle;
int numberOfMonitors = myDisplay.getNMonitors();
writeln("Your set-up has ", numberOfMonitors, " monitors...\n\n");
if(numberOfMonitors > 1)
{
foreach(int i; 0..numberOfMonitors)
{
monitorG = myDisplay.getMonitor(i);
monitorG.getGeometry(rectangle);
writeln("monitor #", i);
writeln("monitor position within the screen area - x = ", rectangle.x, ", y = ", rectangle.y);
writeln("monitor size: width = ", rectangle.width, ", height = ", rectangle.height);
writeln("manufacturer: ", monitorG.getManufacturer());
write("monitor model: ", monitorG.getModel());
if(monitorG.isPrimary())
{
write(" and it's your primary display.");
}
writeln();
writeln();
}
}
else
{
monitorG = myDisplay.getMonitor(0);
writeln("You have a single monitor");
writeln("monitor position within the display - x = ", rectangle.x, ", y = ", rectangle.y);
writeln("monitor size: width = ", rectangle.width, ", height = ", rectangle.height);
writeln("manufacturer: ", monitorG.getManufacturer());
write("monitor model: ", monitorG.getModel());
writeln(" and it's your only display.");
}
} // monitorReport()
This function starts off the same as it did in our previous example, by finding out how many monitors are available to the Seat
, but from there, it goes into more detail, but before we go there, let’s look at the variables in the function preamble and what they’re used for:
int numberOfMonitors
: self-explanitory,monitorG
: a temporary pointer for each monitor as we loop through the list of monitors inmonitorReport()
, andrectangle
: each monitor’s geometry (screen size and its placement in theScreen
) as we loop through the list.
Looking at the big picture here, we first determine if we’re on a single-monitor Seat
. If not, we dig in and:
- grab a pointer to the current monitor, assigning it to
monitorG
, - find it’s geometry and store that info in a rectangle struct (
GdkRectangle
is defined in generated/gtkd/gdk/c/types.d starting on line #3933), - as each monitor is examined, we look to see if it’s the primary monitor for the
Seat
, and - push all these various bits of information to the terminal.
However, if there’s only one monitor, we don’t need to dig around so much. Instead, we just grab a pointer to the single monitor and dump all its info to the terminal.
The ReportButton
A lot of this is similar to any Button
we’ve worked with before. It’s got a string to name the Button
, we make a size request (for convenience, really; it’s just so the full Window
title shows and there’s something to grab onto when moving the Window
from monitor to monitor), add a callback, and connect that callback to a signal.
So, let’s go over what we haven’t done before…
Preamble
We declare:
Display _myDisplay;
MonitorG _monitorG;
Since we’ve gone over these already, let’s just move on to…
Constructor
this(Display myDisplay)
{
super(labelText);
setSizeRequest(250, 30);
addOnClicked(&onClicked);
_myDisplay = myDisplay;
} // this()
We add a line to assign our local copy of the default Display
pointer.
Things get interesting when we look at…
Callback
void onClicked(Button b)
{
MonitorG monitorG4Window;
monitorG4Window = _myDisplay.getMonitorAtWindow(this.getWindow());
int numberOfMonitors = _myDisplay.getNMonitors();
foreach(int i; 0..numberOfMonitors)
{
_monitorG = _myDisplay.getMonitor(i);
if(_monitorG is monitorG4Window)
{
writeln("The current window is on monitor #", i);
}
}
} // onClicked()
monitorG4Window
: reports whichever monitor theWindow
is on at the time theButton
is pressed which is determined by a call to:_myDisplay.getMonitorAtWindow()
and passing in a pointer to our application’sWindow
,- then we go through the process once again of finding out how many monitors there are and grabbing a pointer to each so we can compare that pointer to the
monitorG4Window
to see if they match, and - write the result to the terminal.
Conclusion
And that leaves just one more thing to say before closing:
Happy holidays!
See you next time for more hardware stuff when we look at keyboards, including an alternate way to grab key presses.
See you then.
Comments? Questions? Observations?
Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
- come on over to the D Language Forum and look for one of the gtkDcoding announcement posts,
- drop by the GtkD Forum,
- follow the link below to email me, or
- go to the gtkDcoding Facebook page.
You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.
© Copyright 2024 Ron Tarrant