Closed IanTrudel closed 5 years ago
Since I know nothing I started at the top level. How does a osx user work with multiple monitors. Many issues arise. Extended desktop is the only configuration we care about. Note that they say an app's windows open on the primary and the user drags the window to the other monitor. If that's it, Shoes is mostly compatible now.
If we want to explicitly set the monitor for a shoes window we do this in osx in slightly modified shoes_native_app_window. Seems easy. Dialogs do not have that ability. OSX has rules about that.
This article for pygtk is a reasonable starting point no easy answer for the question of what the new top,left should be - it will be wrong for someone.
My only question? about the api is one would expect app.monitors to return 1 - not zero based. We can subtract -1 in shoes_native_window()
I also found something think harder about Mouse position.
Valuable feedback.
RE: extended desktop
That would be correct. I believe Windows has a similar behaviour. What happens when Shoes is opened from a terminal on a second monitor? I kinda recall that would open on the same monitor rather than primary.
On FreeBSD, it normally opens on the monitor where the mouse pointer is at the time of rendering.
Alternatively, it could open on the designated monitor and fallback to the primary monitor if the designated monitor is not found.
RE: top, left
Alternatively, we could let the OS decide as it is the default behaviour for Shoes. If top, left and monitor are passed to Shoes.app hash parameters, then the user should know where to place it properly anyway... we just let them do it.
My only question? about the api is one would expect app.monitors to return 1 - not zero based. We can subtract -1 in shoes_native_window()
I'm tempted to agree with you. The reason it was 0 is that most APIs, such as GTK, designate the primary monitor as zero. But we could settle for 1 as it makes more sense to users.
If top, left and monitor are passed to Shoes.app
As in Shoes.app {width: 400, height: 600, monitor: 2, top: 40, left: 20} do .. end ?
These should be stored in the shoes_app (see app.h) structure which is passed in to shoes_native_window()
I've created a branch 'monitors' at my github origin (your upstream) hopefully you can
git pull upstream monitors
- nothing new yet but it's the playground.
As in Shoes.app {width: 400, height: 600, monitor: 2, top: 40, left: 20} do .. end ?
Correct.
These should be stored in the shoes_app (see app.h) structure which is passed in to shoes_native_window()
Yes, nothing fancy. Just like top, left, width, height, etc.
I've created a branch 'monitors' at my github origin (your upstream) hopefully you can git pull upstream monitors - nothing new yet but it's the playground.
I probably should resync with the whole Shoes3 at this point anyway.
One other thing, app->monitors == 0 means { monitor: n } was not provided - Shoes as usual. top: and left: should be parsed and stored by shoes_app_window() but for now, only shoes_native_window() needs to know that something special needs to be done for app->monitor > 0. Purists might want another field in shoes_app - 'use_monitors' or something like that. so the monitors field is not using hidden value assumptions.
Yes, we always default to primary monitor. It will ensure compatibility.
Purists might want another field in shoes_app - 'have_monitors' or something like that.
Sorry? I didn't get what you mean here.
Sorry? I didn't get what you mean here
It's Ruby vs C thing style thing. Is app->monitors a boolean or is it a number with special meanings depending on the value like a C union (shudder) ? At the moment, I think we need that boolean app->use_monitors so its apparent that different processing maybe needed (thinking ahead about the mouse issue)
Neither. A call to app.monitors
should always call a (gtk, macOS) function to dynamically check the number of monitors. Occasionally, a monitor is disconnected and no longer available. We need to be avare of that and thus always check. For example, let's say someone is running a Shoes app and then plug a projector for an audience.
shoes_app
structure will (or may?) contain a member monitor
(int) to pass monitor information down to whatever needs it, if necessary. We still need to keep track at runtime though, as a user could move one window to one monitor to another.
Basically, any data is volatile, it will be best to check at runtime each time it is relevant. Shouldn't be a big deal though.
We still need to keep track at runtime though, as a user could move one window to one monitor to another.
Shoes has no way to learn that the user moved the window to another monitor except by asking where the window is when a shoes script wants to know and that may not be accurate at all times. Perhaps an 'app.monitor` method like you suggested?
For example, let's say someone is running a Shoes app and then plug a projector for an audience.
How would we know? A very good example to think about. That would be mirrored and not extended in osx terms.
We don't need to know anything. That's the beauty of it.
Listen, this is very simple.
app.monitors
or app.monitor
instead of stored values in shoes_app structure. app.monitor=
).So what happens when one disconnect a monitor or projector? Nothing.
However, when a Shoes user creates a new window or use app.monitor
, app.monitor=
, we do call the system API first and check against whatever the user input. So, let's say a Shoes.app has a button that creates a window on monitor 2 but the monitor has been disconnected, Shoes internal will check the list of monitors and understand there is no longer a monitor 2 and will display the window on monitor 0.
Is this making more sense to you? We always check number of monitors in app.c:shoes_app_window
(and app.monitor=
C code) before setting anything. app.monitors
and app.monitor
will be wrappers to system calls instead of using shoes_app
.
After more thought, in Shoes 3.3.7, some of this information belongs in the shoes_world_t struct, along with some other 'new' variables. and some other mis-uses of the app (like image cache clearing). I've ordered a new video card that should let my Linux box handle multiple monitors - I have a spare 19" 4:3 monitor that will be a good test.
Welcome back!
Tests/gapp/app1.rb: on OSX:
Now I need a willing OSX user with a multiple monitor setup to test further.
Running the Script 1 with Shoes 3.3.7 beta on MacOS X 10.10.5 (Yosemite) with two monitors:
Running the Script 2 with Shoes 3.3.7 beta on MacOS X 10.10.5 (Yosemite) with two monitors:
Move this app
moves the main window to the second monitor but Second monitor
opens a window always at the same monitor where the main window is.
Thanks @kantel ! I think I see my bug. I was not setting the rect.origin to the second monitor. Would you please try the latest beta (Apr 11, 13:42) ?
For documentation purposes. I've got a Linux system with two monitors now. Here's what Shoes thinks it has.
It has different problems from OSX when displaying on the second monitor from Shoes but thats why we test.
I only found build 3.3.7 r3194 (11. April 2018, 12:42) at the usual place
and with this beta I've got the same behaviour as yesterday:
with one difference: The default monitor is 1
But this is a normal behaviour -- it depends which monitor the focus has. I can reproduces this.
Correct, the default monitor can be shifted by the user and the script is a little dumb about that.. I discovered yesterdays that my mac mini has a display port so I order an inexpensive dongle to convert to vga/dvd/hdmi. I should be able to test the Mac code in a day or two.
This is a better test script. Uses all the Shoes monitor methods - working on Linux, Windows, and Freebsd. Behaves better default.
Shoes.app do
stack do
para "Muliple Monitor Test"
st = Shoes.settings
@eb = edit_box width: 400, height: 150
end
start do
st = Shoes.settings
dflt = st.monitor_default
@eb.append "Default monitor is #{dflt}\n"
st.monitor_count.times do |mon|
@eb.append "Monitor #{mon} => #{st.monitor_geometry(mon)}\n"
end
(st.monitor_count- 1).times do |mon|
flow do
newmon = (dflt ^ 1)
button "New Window on #{newmon}" do
window title: "Launched in #{newmon}", monitor: newmon do
stack do
para "My Monitor is #{app.monitor}"
button "Dialog" do
alert "Which Windows?"
end
end
end
end
button "Move This to #{newmon}" do
app.monitor = newmon
end
button "Restore this to #{dflt}" do
app.monitor = dflt
end
end
end
end
end
I tried this script on my Mac with Shoes build 3.3.7 r3194, too. It runs and New Window on 1
and Restore this to 0
are Working, but New Window on 1
opens the window always on the monitor where the main window is (in my case Monitor 0) but it says, it is on Monitor 1 (see screenshot):
My osx dongle is working. The move to buttons work but the new window doesn't. I suspect screen vs view co-ordinates.
@kantel - Well, that took a while! I've got another beta for osx that works for me. My setup has the second monitor to the right of main monitor which maybe different that yours.
It works. In my setting the monitor 0 is on the left and the monitor 1 is on the right. But it doesn't matter. Either if I declare the monitor 0 or the monitor 1 to the default monitor, the test programms work as expected (see screenshots):
The windows moved correctly to 0 or 1. (Pls. excuse my bad (d)english.) But I think, everything is okay.
Need a full screen test app:
Shoes.app do
stack do
para "Muliple Monitor Full Screen Test"
st = Shoes.settings
@eb = edit_box width: 400, height: 150
end
start do
st = Shoes.settings
dflt = st.monitor_default
@eb.append "Default monitor is #{dflt}\n"
st.monitor_count.times do |mon|
@eb.append "Monitor #{mon} => #{st.monitor_geometry(mon)}\n"
end
button "Tooggle FullScreen #{dflt}" do
state = app.fullscreen
app.fullscreen = (state ? false : true);
end
(st.monitor_count - 1).times do |mon|
flow do
newmon = (dflt ^ 1)
button "New Window on #{newmon}" do
window title: "Launched in #{newmon}", monitor: newmon, fullscreen: false do
stack do
para "My Monitor is #{app.monitor}"
button "Fullscreen #{app.monitor}" do
state = app.fullscreen
app.fullscreen = (state ? false : true);
end
@eb = edit_box width: 300, height: 150
end
end
end
end
end
end
end
Almost works correctly on OSX.
It works as expected. I was able to tooggle a full screen on monitor 0 and on monitor 1 and it also opens a new window at 1 which I could tooggle, too.
Closing 3.3.7 issues.
This is the proposed API for multiple monitors support on Shoes. A follow-up on issue #64 for which it now requires its own issue. Please, take a look at the API and give your feedback here.
app.monitors
app.monitor
andapp.monitor=
monitor
hash parameterSample code: