Closed kevkha closed 9 years ago
I'll look what I can do. At the first look it should be possible, just don't sure what exact logic will be best.
I think this can be done with just NW.js, try something like:
var gui = require('nw.gui');
gui.Screen.Init();
var win = gui.Window.get();
var lastScreens = 1;
function checkScreens() {
win = gui.Window.get();
if (gui.Screen.screens.length != lastScreens) {
if (gui.Screen.screens.length == 2 && lastScreens == 1) {
lastScreens = gui.Screen.screens.length;
if (win.x < gui.Screen.screens[lastScreens -1].work_area.x) win.x = gui.Screen.screens[lastScreens -1].work_area.x + win.x;
} else if (gui.Screen.screens.length == 1 && lastScreens == 2) lastScreens = gui.Screen.screens.length;
}
}
setInterval(function() { checkScreens(); },2000);
checkScreens();
This should (hopefully) move the nw window to the second monitor when it is detected.. it does not move the window back to the first monitor when the second monitor is disconnected because the OS does that anyway (why would it leave it on a non-existing screen?). I did not test this to much though.. tell me if it worked for you. :)
Thanks for a quick turnaround. The above code works great as this observation
Can you check on # 4 again? Thanks.
I think I over-complicated things in that code, try this code instead:
var gui = require('nw.gui');
gui.Screen.Init();
win = gui.Window.get();
if (win.x < gui.Screen.screens[gui.Screen.screens.length -1].work_area.x) win.x = gui.Screen.screens[gui.Screen.screens.length -1].work_area.x + win.x;
var screenCB = {
onDisplayAdded : function(screen) {
win = gui.Window.get();
if (win.x < screen.work_area.x) win.x = screen.work_area.x + win.x;
}
};
gui.Screen.on('displayAdded', screenCB.onDisplayAdded);
It worked for me in all the situations you mentioned.
You are a super genius, latter code works both cases. Thanks so much. Now, suppose I create a second window ie
// Create a new window var new_win = gui.Window.open('player.html', { position: 'center', width: 800, height: 640 });
and want to move the second window instead and leave default 'win' on screen 1 at all time. Can I simply replace 'win' with 'new_win'?
why not just put that code only in player.html directly?
Good point. I was thinking a hard way again and focused on default index.html. Will keep you posted shortly. Thanks.
Sweet! Everything works the way I wanted. Thanks so much again jaruba! Please consider NW.js side is resolved.
Glad I could help! :)
Is there a donate button on your plugin page? Gotta buy you coffees :-)
The button from http://www.webchimera.org/ is the entire project's donate button.
You already donated. :)
Ok cool. Good to know. More to come in a few days ;p
I think we still need do something similar for fullscreen window?
Agreed.
@kevkha, btw, how do you attach/detach additional displays? hdmi? And why do you need it to do "on the fly"?
Yes, attach and detach the HDMI cable. I need this solution when there is no mouse available to drag player to another screen.
so it will be enough for fullscreen window if it just will follow movements of main application window across displays (i.e. without need save active screen history inside fullscreen window)?
or it's another solution exists - if you can detect screen attach/detach inside NW.js - you could just:
It should work, since fullscreen window shown on screen where plugin area is (inside browser). Now it will work at least on Windows, on Mac I still need implement fullcreen on second monitor.
For my project I need main app window be on screen 1 to display other elements from back end server. When there is only one screen the player (second) window should move to screen 1 and can be on top of main app window. I haven't tested in fullscreen mode movement yet. Do you suggest that I should add fullscreen in onLoad or do it in QML?
Hm... it's more complex configuration than I thought. Did you implement this 2 windows already? I just don't sure if it possible communicate between 2 top level windows in NW.js?
And will you have WebChimera on both windows or only one of them?
Yes, I have implemented two windows. I only have WebChimera on second window. So it will be active to accept commands from IR. I will test to see if I can do some basic controls using mouse from main window like toggleFullscreen() to second window.
Do you guys mean that if a second monitor is connected, and the player is already fullscreen on the first window, it should move with fullscreen already set to the second monitor?
var wasFullscreen = 0;
var gui = require('nw.gui');
gui.Screen.Init();
function onDisplayAdded(screen) {
if (wjs("#webchimera").plugin.fullscreen) {
wasFullscreen = 1;
wjs("#webchimera").plugin.toggleFullscreen();
} else wasFullscreen = 0;
if (wjs("#webchimera").plugin.fullscreen) wjs("#webchimera").plugin.toggleFullscreen();
win = gui.Window.get();
if (win.x < screen.work_area.x) win.x = screen.work_area.x + win.x;
if (wasFullscreen == 1) setTimeout(function() { wjs("#webchimera").plugin.toggleFullscreen(); }, 3000);
}
function onDisplayRemoved(screen) {
if (wjs("#webchimera").plugin.fullscreen) {
wjs("#webchimera").plugin.toggleFullscreen();
setTimeout(function() { wjs("#webchimera").plugin.toggleFullscreen(); }, 1000);
}
}
if (gui.Screen.screens.length > 1) onDisplayAdded(gui.Screen.screens[gui.Screen.screens.length -1]);
gui.Screen.on('displayAdded', onDisplayAdded);
gui.Screen.on('displayRemoved', onDisplayRemoved);
Or do you want the player to auto-fullscreen on the second monitor every time it is connected? (as you mentioned you had no mouse anyway)
var gui = require('nw.gui');
gui.Screen.Init();
function onDisplayAdded(screen) {
if (wjs("#webchimera").plugin.fullscreen) wjs("#webchimera").plugin.toggleFullscreen();
win = gui.Window.get();
if (win.x < screen.work_area.x) win.x = screen.work_area.x + win.x;
setTimeout(function() { wjs("#webchimera").plugin.toggleFullscreen(); }, 3000);
}
function onDisplayRemoved(screen) {
if (wjs("#webchimera").plugin.fullscreen) {
wjs("#webchimera").plugin.toggleFullscreen();
setTimeout(function() { wjs("#webchimera").plugin.toggleFullscreen(); }, 1000);
}
}
if (gui.Screen.screens.length > 1) onDisplayAdded(gui.Screen.screens[gui.Screen.screens.length -1]);
gui.Screen.on('displayAdded', onDisplayAdded);
gui.Screen.on('displayRemoved', onDisplayRemoved);
These are untested though, but they should work.
As @RSATom mentioned, fullscreen on second monitor will only work on Windows, on Mac it was not implemented yet.
Although we could partially hack it on Mac too.. as HTML5 fullscreen does not require any user interaction in NW. (but the player will act by the rules of a non-fullscreen environment, as with html5 fullscreen, it doesn't know when it's fullscreen or not in QML)
@jaruba, yes, something like this. I just think (but didn't try, so not sure) current fullscreen implementation has bug with disconnecting second monitor on-the-fly: If fullscreen mode activated on second screen, and detach this screen, I think fullscreen window will not go to first screen without help from JS.
I edited the code above to include a scenario in which the display is removed. (although I didn't test this either) I also delayed the second .toggleFullscreen()
for safety. I tried to test it but didn't manage to test it to well... I think it's because I don't test it with a hdmi cable, I'm testing with WiDi on a TV and connecting/disconnecting take a lot longer, in my last tests fullscreen didn't work on the tv at all.. but again, this could be from WiDi.
@jaruba I tested both of your new codes but none works. Player does not follow screen 2 at all.
Since I can't move webchimera player when in fullscreen mode I manged to move NW fullscreen window back and forth with following code
// moving player to secondary screen when available
var gui = require('nw.gui');
gui.Screen.Init();
win = gui.Window.get();
if (win.x < gui.Screen.screens[gui.Screen.screens.length -1].work_area.x) win.x = gui.Screen.screens[gui.Screen.screens.length -1].work_area.x + win.x;
// start with fullscreen and focus
win.enterFullscreen();
win.focus();
var screenCB = {
onDisplayBoundsChanged : function(screen) {
win = gui.Window.get();
win.leaveFullscreen();
win.enterFullscreen();
},
onDisplayAdded : function(screen) {
win = gui.Window.get();
if (win.x < screen.work_area.x) win.x = screen.work_area.x + win.x;
win.leaveFullscreen();
win.enterFullscreen();
},
onDisplayRemoved : function(screen) {
win = gui.Window.get();
win.leaveFullscreen();
win.enterFullscreen();
}
};
// listen to screen events
gui.Screen.on('displayBoundsChanged', screenCB.onDisplayBoundsChanged);
gui.Screen.on('displayAdded', screenCB.onDisplayAdded);
gui.Screen.on('displayRemoved', screenCB.onDisplayRemoved);
And in css I have
html, body { margin: 0; padding: 0; overflow: hidden}
#player_wrapper { width: 100%; height: 100%; position: absolute; top: 0; bottom: 0}
With this solution I need to disable fullscreen on double-click to prevent window movement issue.
But that will make the player act like it is not fullscreen.. for example, the toolbar doesn't fade out, it slides down and the progress bar remains visible..
What happens when you try my codes?
Yes, that's the only last thing I need to hide.
And about your code.. I think this code:
// moving player to secondary screen when available
var gui = require('nw.gui');
gui.Screen.Init();
win = gui.Window.get();
if (win.x < gui.Screen.screens[gui.Screen.screens.length -1].work_area.x) win.x = gui.Screen.screens[gui.Screen.screens.length -1].work_area.x + win.x;
// start with fullscreen and focus
win.enterFullscreen();
win.focus();
function onDisplayAdded(screen) {
win = gui.Window.get();
if (win.x < screen.work_area.x) win.x = screen.work_area.x + win.x;
win.leaveFullscreen();
win.enterFullscreen();
}
// listen to screen events
gui.Screen.on('displayAdded', onDisplayAdded);
Does the exact same thing, I don't think you need displayBoundsChanged
and displayRemoved
at all in this particular case. :)
You're absolutely right. I use your code now to save some memory :-). Any hint to hide the Toolbar in this situation? I observe the entire tool bar is visible on screen 1 and on screen 2 just the single progress bar which I can live at the moment but hide the whole thing would be a nice hack.
That is a bit tricky... the toolbar itself is not made of one element..
In /player/themes/sleek/components/Toolbar.qml
change:
anchors.bottomMargin: fullscreen ? 0 : parent.containsMouse ? 0 : -height
...
opacity: fullscreen ? settings.ismoving > 5 ? 0 : 1 : 1
to this:
anchors.bottomMargin: 0
...
opacity: settings.ismoving > 5 ? 0 : 1
Then in /player/themes/sleek/components/ProgressBar.qml
change:
anchors.bottomMargin: settings.multiscreen == 1 ? fullscreen ? 32 : -8 : fullscreen ? 32 : mousesurface.containsMouse ? 30 : 0 // Multiscreen - Edit
opacity: settings.multiscreen == 1 ? fullscreen ? fullscreen ? settings.ismoving > 5 ? 0 : 1 : 1 : 0 : fullscreen ? settings.ismoving > 5 ? 0 : 1 : 1 // Multiscreen - Edit
to:
anchors.bottomMargin: 30
opacity: settings.ismoving > 5 ? 0 : 1
I can't be sure of any other implications node-webkit's internal fullscreen window might have on the player though..
Mouse Cursor might now disappear either..
Above works well except for the circular/square progress position indicator. Which line is it?
Try going to /player/themes/sleek/components/ProgressBar.qml
and looking for id: movecur
then changing:
anchors.bottomMargin: settings.multiscreen == 1 ? fullscreen ? toolbar.height : -16 : fullscreen ? toolbar.height : mousesurface.containsMouse ? toolbar.height : 0
opacity: settings.multiscreen == 1 ? fullscreen ? settings.ismoving > 5 ? 0 : 1 : 0 : fullscreen ? settings.ismoving > 5 ? 0 : 1 : 1
to this:
anchors.bottomMargin: toolbar.height
opacity: settings.ismoving > 5 ? 0 : 1
You're super! Everything is working. Thanks! As for your NW complication concern I don't it matter with webchimer player not being fullscreen inside NW fullscreen window. If we have both NW and Webchimera in fullscreen mode there would be 2 or more instances of windows to deal with. If I wish to exit fullscreen of NW I can do so with win.toggleFullscreen().
I don't see it as a complication, quite the contrary, I understand why your doing it. Even more so, as fullscreen does not work on second monitor on Mac and doesn't work at all on Linux, using a full-window player with Node-Webkit's Window API - Fullscreen actually fixes all of them in Node-Webkit.
My concern was with the player itself.. it checks "fullscreen" in a lot of places in the logic. So more things might not work as expected.. and I can never be sure what works and what doesn't in this scenario as the player is really big these days. :)
Also, for a more general scenario, it might even be better to use HTML5 Fullscreen instead of NW's Window API - Fullscreen, as HTML5 Fullscreen can be called on html elements, so the player doesn't even need to be the full size of the window for it to work.
I hear you. Currently, I have disabled Key_F and double-click for toggleFullscreen in QML so that should prevent it I think. I will run more tests on Windows before moving onto Linux and OSX later. If you don't hear back from me which means things are going well. :-)
My next challenge is figure out how to use global variables in NW so that I can pass and and make calls to webchimera player commands using Javascript API across windows. If you have any ideas I'm all ears. Thanks mate!
I'm afraid I never tried communication between 2 windows in NW.
I know there is an object in NW, called localStorage that is not erased even between app close/reopen, so it might also be possible to use it between windows, I can't be sure though, I never tried. I just keep user settings in localStorage.
Consider using something like socket.io for communication
Auto detect multiple screens and show option to move player to another screen. Even better have option to automatically move player once screen 2 detected and move back to screen 1 when screen 2 is disconnected. Can this be achieved in QML or NW.js?
Some info for Qt5 I found http://www.ics.com/blog/whats-new-qt-5-qscreen-class