Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac only: Mission window glides across screen when moved #590

Open
Brigadirk opened this issue Aug 18, 2017 · 5 comments
Open

Mac only: Mission window glides across screen when moved #590

Brigadirk opened this issue Aug 18, 2017 · 5 comments

Comments

@Brigadirk
Copy link

Brigadirk commented Aug 18, 2017

When I start up the Minecraft server, I'm able to move and adjust the screen as I please.

However, after starting a mission, any attempt to move the Minecraft window will send it spiralling out of control across the screen, often sliding out of vision, necessitating a restart of the server.

Additionally, adding a videoproducer to the XML centers the Minecraft window. Combined with the screen playing ice hockey with the Minecraft window, this can make it very annoying to run tests on a single laptop screen.

According to David Bignell, this only happens on Mac, hence the title.

@Brigadirk Brigadirk changed the title MAC: Mission window glides across screen when moved Mac only: Mission window glides across screen when moved Aug 18, 2017
@DaveyBiggers
Copy link
Member

Yes, after some digging it seems it's due to to the following code in EntityRenderer:

        if (flag && Minecraft.IS_RUNNING_ON_MAC && this.mc.inGameHasFocus && !Mouse.isInsideWindow())
        {
            Mouse.setGrabbed(false);
            Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2 - 20);
            Mouse.setGrabbed(true);
        }

This is also the reason why the OSX Minecraft window is so reluctant to relinquish the mouse capture (Malmo contains code to ensure Minecraft doesn't keep hold of the mouse, which works fine on Windows and Linux). Any time the window gains focus and the mouse is outside of the window, the mouse is automatically grabbed, and moved to within the window... Unfortunately, if you are dragging the window, the window gets moved with the mouse (leaving the mouse outside the window client area again, thus re-triggering the move, shifting the window again, etc.etc.)

@DaveyBiggers
Copy link
Member

As for the automatic centring of the window after resize...
In theory this should be an easy fix - just grab the x/y coords of the window before resizing, and reset them afterwards:

            int oldX = Display.getX();
            int oldY = Display.getY();
            DisplayMode dm = new DisplayMode(this.renderWidth, this.renderHeight); // new dimensions
            Display.setDisplayMode(dm); // resizes window
            Display.setLocation(oldX,  oldY); // reset position

Unfortunately there are a few problems with this:
Firstly, lwjgl (which Minecraft uses) has mismatched position getters/setters - the getters seem to take into account the window furniture (title bar etc), whereas the setters don't - so calling

Display.setLocation(Display.getX(), Display.getY())

will result in the window gradually creeping up and to the left.

Secondly, this is lwjgl's helpful OSX implementation of the reshape method (which is called by setLocation):

	public void reshape(int x, int y, int width, int height) {
        //if (native_mode) {
        //    nResizeWindow(window, x, y, width, height);
        //}
	}

So calling setLocation on OSX doesn't actually move the window at all... though it does cache the values for x and y, which will then be used the next time the window is recreated (eg when the dimensions change), so, somewhat counter-intuitively, this almost works:

            int oldX = Display.getX();
            int oldY = Display.getY();
            Display.setLocation(oldX,  oldY); // Do this *before* changing dimension
            DisplayMode dm = new DisplayMode(this.renderWidth, this.renderHeight); // new dimensions
            Display.setDisplayMode(dm); // resizes window

Why is the setLocation necessary at all, in this case?
Because Display's cached x and y values (which are used when recreating the window) have nothing to do with the window's actual position. They are not updated if the window is moved by the user. (This is what causes the centring in the first place - by default they are set to -1, which is a magic value used to indicate that the window should be centred, and moving the window manually doesn't change them, so each resize re-centres the window.)

Fortunately Display.getX() and getY() get the actual window positions (hence the mismatch between getters and setters - the getWindowX() and getWindowY() methods which return the cached values are private), and then these values can be written back to the cached values using setLocation, so that the window will appear in roughly the right place after recreation.

Ugh.

@DaveyBiggers
Copy link
Member

To make matters worse, according to the lwjgl documentation for setLocation, "The window is clamped to remain entirely on the screen."
As far as I can tell, this is just a lie. There doesn't appear to be any code anywhere that actually implements this. So the result of creeping up and to the left, eventually, is that the Minecraft window disappears off screen entirely.

Admittedly, it takes a while for this to happen, and under normal working conditions the Minecraft window won't be changing size often, so it shouldn't present a problem in most cases.

@DaveyBiggers
Copy link
Member

This has been "fixed" (allowing for the above ugliness) in 0.31.0.

@DaveyBiggers
Copy link
Member

Am reopening this because the fix (making sure this.mc.inGameHasFocus is false for the check in EntityRenderer) breaks the continuous attack command.

@DaveyBiggers DaveyBiggers reopened this Oct 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants