Mouse outside window in windowed mode

Hi there,



is it possible to have a mouse pointer outside a window in a non-fullscreen (windowed) mode? Normally, the mouse does not go beyond the window border.



Thanks

Currently there are two mouse types in jME, absolute (a mouse cursor goes where you point) and relative (the mouse stays in the center). Take a look at AbsoluteMouse (which is what you’d base your mouse type off of), do everything the same but in the update method remove the checks for the boundries of the window. This will do what you want.

Thanks for your answer. I’m not sure if this does it.



Let’s take TestAbsolutMouse for example. I created my own Absolute Mouse as you said:



public class MyAbsoluteMouse extends AbsoluteMouse {

    public MyAbsoluteMouse(String name) {
        super(name, 0, 0); // don't need boundary
    }

    public void update(boolean updateState) {
        if (updateState)
            mouse.updateState();

        localTranslation.x += mouse.getXDelta() * _speed;
        localTranslation.y += mouse.getYDelta() * _speed;


        /* ===  no boundary checking
        if (localTranslation.x  + _hotSpotOffset.x < 0) {
            localTranslation.x = -_hotSpotOffset.x;
        } else if (localTranslation.x + _hotSpotOffset.x > width) {
            localTranslation.x = width - _hotSpotOffset.x;
        }

        if (localTranslation.y + _hotSpotOffset.y < 0 - imageHeight) {
            localTranslation.y = 0 - imageHeight - _hotSpotOffset.y;
        } else if (localTranslation.y  + _hotSpotOffset.y > height) {
            localTranslation.y = height - _hotSpotOffset.y;
        }
        === */

        worldTranslation.set(localTranslation);
        _hotSpotLocation.set(localTranslation).addLocal(_hotSpotOffset);
    }
 
}



and used this class in TestAbsoluteMouse instead of AbsoluteMouse. When I run the test (non-fullscreen mode), the mouse goes indeed beyond the window border but without becoming the default Windows mouse. The mouse just disappears. What I need is the system mouse outside the game window. Do I have to release the mouse in some way as soon as it crosses the border?

You can use mouse.setCursorVisible( true/false ) to show and hide the cursor when it’s outside/inside the game window.

Ok, now I’m a bit confused. Tried to changed the AbsoluteMouse class to show the hardware cursor when the mouse is moved outside the window, as requested above. The strange thing is that when I use mouse.setCursorVisible( true ) inside the update method the cursor behaves strangely. It’s jumping around, changeing position as if visible on/off moved it. If I set it to true in setMouseInput and leave it that way everything is fine and the cursors (hw and software) are in the right places.



Anyone got any ideas?



Removed all comments to shrink the post a bit…


package com.jme.input;

import com.jme.scene.Text;

public class AbsoluteWindowMouse extends Mouse {
   
   private static final long serialVersionUID = 1L;
   private boolean bCursorVisible = true;
   private boolean bChange = true;
   private Text txt = null;
   private int iWidth, iHeight;
   
   public AbsoluteWindowMouse( String strName, int width, int height, Text txt ) {
      super( strName );
      this.iWidth = iWidth;
      this.iHeight = iHeight;
      this.txt = txt;
   }
   
   public void update() {
      update( true );
   }
   
   public void update(boolean updateState) {
      if( updateState ) {
         mouse.updateState();
      }
      
      localTranslation.x += mouse.getXDelta() * _speed;
      localTranslation.y += mouse.getYDelta() * _speed;
      
      if( ( ( localTranslation.x > -hotSpotOffset.x ) &&
               ( localTranslation.x + hotSpotOffset.x < iWidth - 1 ) ) &&
            ( ( localTranslation.y + hotSpotOffset.y > 0 ) &&
               ( localTranslation.y + hotSpotOffset.y < iHeight - 1 ) ) ) {
         bChange = bCursorVisible;
         bCursorVisible = false;
      }
      else {
         bChange = !bCursorVisible;
         bCursorVisible = true;
      }
      
      txt.print( "hw cursor visible: " + bCursorVisible +
      ", x: " + (localTranslation.x + hotSpotOffset.x) +
      ", y: " + (localTranslation.y + hotSpotOffset.y) );
      
      if( localTranslation.x + hotSpotOffset.x < 0 ) {
         localTranslation.x = -hotSpotOffset.x;
      }
      else if( localTranslation.x + hotSpotOffset.x > iWidth ) {
         localTranslation.x = iWidth;
      }
      
      if (localTranslation.y + hotSpotOffset.y < 0 - imageHeight) {
         localTranslation.y = 0 - imageHeight - hotSpotOffset.y;
      }
      else if (localTranslation.y + hotSpotOffset.y > iHeight) {
         localTranslation.y = iHeight - hotSpotOffset.y;
      }
      
      worldTranslation.set( localTranslation );
      hotSpotLocation.set( localTranslation ).addLocal( hotSpotOffset );
      
      if( bChange ) {
         //mouse.setCursorVisible( bCursorVisible );
         bChange = false;
      }
   }
   
   public boolean isCursorVisible() {
      return this.bCursorVisible;
   }
   
   public void setMouseInput( MouseInput mouse ) {
      super.setMouseInput( mouse );
      mouse.setCursorVisible( true );
   }
   
   public void setLimit( int iWidth, int iHeight ) {
      this.iWidth = iWidth;
      this.iHeight = iHeight;
   }
}



Also added a new Text object to the fps node with info if the cursor should be visible etc.


Text txtTemp = new Text( "txt", "" );
txtTemp.setLocalTranslation( new Vector3f( 0, 20, 0 ) );
this.fpsNode.attachChild( txtTemp );
am = new AbsoluteWindowMouse( "mouse", display.getWidth(), display.getHeight(), txtTemp );
am.setLocalTranslation( new Vector3f(
   ( display.getWidth() / 2 ) + ( t.getImage().getWidth() / 2 ),
   ( display.getHeight() / 2 ) - ( t.getImage().getHeight() / 2 ), 0 ) );

Hmm… anyone? Or did everyone stop looking at this thread around Oct 13?

e-mail me your test code when you have a chance and I’ll take a look.

Ok, the mail is on it’s way…

ok, playing with it right now (I see the issue, trying to find the cause).

in LWJGLMouseInput’s setCursorVisible method there is a call:


Mouse.setGrabbed(!v);



Commenting this out removes the "jump" but does not properly dispose of the hardware cursor.

from the Java doc...

Sets whether or not the mouse has grabbed the cursor (and thus hidden). If grab is false, the getX() and getY() will return delta movement in pixels clamped to the display dimensions, from the center of the display.


So, when we enter the jME display we setGrabbed(true), this then alters the definition of center from the window center to display center. My thinking is this switch is causing a large value to be returned for the next frame's mouse delta, putting the mouse cursor in an unexpected position.

I would suggest trying to figure out a way to handle the switch of centers, such that after the switch you just ignore the next mouse updates for that frame. My work break is over, so I can't do it right now, but I can try tackling it in a bit, if you don't get to it.

Hmm… ignoring the next update works when just moving outside the window in one axis, but with both x and y it gradually gets worse.

The only way to really make this work is to actually interface directly with the OS. This would be something that LWJGL would have to do for us… I’m going to look into it.

Is there any update to this subject? I am trying to solve the same problem.



Thanks.

Filip

use hardware mouse and set the cursor of that should solve ur problem