Skip to content
This repository has been archived by the owner on Dec 5, 2022. It is now read-only.

Option to move or show player on another screen #105

Closed
kevkha opened this issue Apr 6, 2015 · 39 comments
Closed

Option to move or show player on another screen #105

kevkha opened this issue Apr 6, 2015 · 39 comments

Comments

@kevkha
Copy link

kevkha commented Apr 6, 2015

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

@RSATom
Copy link
Owner

RSATom commented Apr 6, 2015

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.

@jaruba
Copy link

jaruba commented Apr 6, 2015

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. :)

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

Thanks for a quick turnaround. The above code works great as this observation

  1. Start off with two screens
  2. Launch NW app and player appears on screen 2
  3. Disconnect screen 2, player goes back to screen 1 as expected
  4. Reconnect screen 2, player does not go back to screen 2

Can you check on # 4 again? Thanks.

@jaruba
Copy link

jaruba commented Apr 6, 2015

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.

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

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'?

@jaruba
Copy link

jaruba commented Apr 6, 2015

why not just put that code only in player.html directly?

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

Good point. I was thinking a hard way again and focused on default index.html. Will keep you posted shortly. Thanks.

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

Sweet! Everything works the way I wanted. Thanks so much again jaruba! Please consider NW.js side is resolved.

@jaruba
Copy link

jaruba commented Apr 6, 2015

Glad I could help! :)

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

Is there a donate button on your plugin page? Gotta buy you coffees :-)

@kevkha kevkha closed this as completed Apr 6, 2015
@jaruba
Copy link

jaruba commented Apr 6, 2015

The button from http://www.webchimera.org/ is the entire project's donate button.

You already donated. :)

@kevkha
Copy link
Author

kevkha commented Apr 6, 2015

Ok cool. Good to know. More to come in a few days ;p

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

I think we still need do something similar for fullscreen window?

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

Agreed.

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

@kevkha, btw, how do you attach/detach additional displays? hdmi? And why do you need it to do "on the fly"?

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

Yes, attach and detach the HDMI cable. I need this solution when there is no mouse available to drag player to another screen.

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

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)?

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

or it's another solution exists - if you can detect screen attach/detach inside NW.js - you could just:

  • turn off fullscreen
  • move main application window to appropriate screen
  • turn on fullscreen

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.

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

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?

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

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?

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

And will you have WebChimera on both windows or only one of them?

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

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.

@jaruba
Copy link

jaruba commented Apr 7, 2015

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)

@RSATom
Copy link
Owner

RSATom commented Apr 7, 2015

@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.

@jaruba
Copy link

jaruba commented Apr 7, 2015

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.

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

@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.

@jaruba
Copy link

jaruba commented Apr 7, 2015

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?

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

Yes, that's the only last thing I need to hide.

@jaruba
Copy link

jaruba commented Apr 7, 2015

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. :)

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

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.

@jaruba
Copy link

jaruba commented Apr 7, 2015

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..

@jaruba
Copy link

jaruba commented Apr 7, 2015

Mouse Cursor might now disappear either..

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

Above works well except for the circular/square progress position indicator. Which line is it?

@jaruba
Copy link

jaruba commented Apr 7, 2015

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

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

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().

@jaruba
Copy link

jaruba commented Apr 7, 2015

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.

@kevkha
Copy link
Author

kevkha commented Apr 7, 2015

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!

@jaruba
Copy link

jaruba commented Apr 7, 2015

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.

@mitselek
Copy link

mitselek commented Feb 3, 2016

Consider using something like socket.io for communication

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants