[RFE] Make "undecorated" accessible for Applets

Started by survivor, December 07, 2011, 20:49:15

Previous topic - Next topic

survivor

Currently, an Applet game lacks the ability to switch to 'Display Type: Desktop' due to the fact that an Applet is not allowed to call 'System.setProperty("org.lwjgl.opengl.Window.undecorated", "false")'. It would be really cool (and it's easy for you to do) if an Applet could switch to a fullscreen / desktop window (like youtube). Switching to a real fullscreen mode is messing up the position of other windows.

Here is an example.

Thanks a lot!

Regards
Stefan

kappa

applets can switch that parameter on, see lwjgl_arguments tag on the AppletLoader.

survivor

Yes, but that switch is not available at runtime. For an Applet it's a constant. By defining "lwjgl_arguments:'-Dorg.lwjgl.opengl.Window.undecorated=true'", the Applet starts with an undecorated window as display. That is undesirable in most cases. It would be better if the user could switch to fake fullscreen and back like a youtube video.

An Applet can already toggle between embedded, window and fullscreen display, but fullscreen is messing up the position of other windows. And there are players who have two monitors and like to be able to see teamspeak / vent / icq / web browser on the second monitor without alt-tabbing back and searching for the windows that have moved offscreen.


princec

Switching to real fullscreen should have no effect on other windows. You are setting the fullscreen mode to be the desktop display mode aren't you?

Cas :)

survivor

You're right. Fullscreen at desktop display mode dosn't change other windows. Remains the benefit of being able to drag the mouse over to the second monitor and for example drag someone into another channel in teamspeak / ventrillo. Many games today like WoW and Anno 2070 (excellent GUI) have such a "desktop mode" and I appreciate it a lot.

The needed changes in LWJGL are minimal. I did it myself, but I like the signed AppletLoader.

princec

TBH it would probably be nice if LWJGL had an option not to take over multiple monitors when it is placed in FS mode.

Cas :)

Mickelukas

Quote from: survivor on December 08, 2011, 14:04:22
You're right. Fullscreen at desktop display mode dosn't change other windows. Remains the benefit of being able to drag the mouse over to the second monitor and for example drag someone into another channel in teamspeak / ventrillo. Many games today like WoW and Anno 2070 (excellent GUI) have such a "desktop mode" and I appreciate it a lot.

The needed changes in LWJGL are minimal. I did it myself, but I like the signed AppletLoader.

Do you mind sharing what you changed and how you switch to desktop mode? I sign my lwjgl files anyway and some users have problems with entering/leaving full screen mode so it would be nice to test.

Mike

survivor

I did it in jME3. I had to implement the resolution switching for the Applet version by using the static methods of “org.lwjgl.opengl.Display” since "com.jme3.system.lwjgl.LwjglCanvas.restart()" is mostly a stub. So resolution switching for the Application version is done the jME3 way and for the Applet version it's my hack.

You can test resolution switching here:
http://www.nabyrinth.com/NabyBallMaze/

Here comes the code. You would call 'applyDisplaySettings("Desktop", 1920, 1080)' to switch to desktop mode. 'this.settings' is a member of the surrounding Application class (jME3) similar to a 'DisplayMode'.

 private DisplayMode getFullscreenDisplayMode(int width, int height, int bpp, int freq) 
  {
    try {
      DisplayMode[] modes = Display.getAvailableDisplayModes();
      for (DisplayMode mode : modes) {
        if (mode.getWidth() == width
          && mode.getHeight() == height
          && (mode.getBitsPerPixel() == bpp || (bpp == 24 && mode.getBitsPerPixel() == 32))
          && mode.getFrequency() == freq) {
          return mode;
        }
      }
    } catch (LWJGLException ex) {
      log.severe("Failed to acquire fullscreen display mode!");
    }
    
    return null;
  }
  
  private void setSettingsDisplayMode(boolean toggleCanvas)
  {
    try 
    {
      DisplayMode dm = null;
      if (settings.isFullscreen())
      {
        dm = getFullscreenDisplayMode(
          settings.getWidth(),
          settings.getHeight(), 
          settings.getBitsPerPixel(),
          settings.getFrequency());
      }
      else
      {
        dm = new DisplayMode(settings.getWidth(), settings.getHeight());
      }

      if (dm != null)
      {
        if (toggleCanvas)
        {
          if (canvas == null)
          {
            canvas = Display.getParent();
            Display.setParent(null);
            Graphics2D g = (Graphics2D) canvas.getGraphics();
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                               RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            Font font = g.getFont().deriveFont(36f);
            g.setFont(font);
            final String text = "External Display";
            int sw = g.getFontMetrics().stringWidth(text);
            g.drawString(text, (canvas.getWidth() - sw) / 2, canvas.getHeight() / 2);
            g.dispose();
          }
          else
          {
            settings.setWidth(canvas.getWidth());
            settings.setHeight(canvas.getHeight());
            Display.setParent(canvas);
            canvas.requestFocus();            
            canvas = null;
          }
        }

        reshape(settings.getWidth(), settings.getHeight());
        Display.setDisplayModeAndFullscreen(dm);
      }

    } catch (LWJGLException ex) {
      Logger.getLogger(NabyBallMaze.class.getName()).log(Level.SEVERE, null, ex);
    }    
  }
  
  void applyDisplaySettings(String displayType, int width, int height)
  {
    DisplayMode ddm = Display.getDesktopDisplayMode();
    boolean toggleCanvas = false;
    if (this.context.getType() == Type.Canvas) // Applet
    {
      this.settings.setBitsPerPixel(ddm.getBitsPerPixel());
      this.settings.setFrequency(ddm.getFrequency());
      
      if ("Applet".equals(displayType))
      {
        if (this.canvas != null)
        {
          this.settings.setResolution(this.canvas.getWidth(), this.canvas.getHeight());
          this.settings.setFullscreen(false);
          toggleCanvas = true;
        }
        else
        {
          return;
        }
      }
      else if ("Window".equals(displayType))
      {
        this.settings.setResolution(width, height);
        this.settings.setFullscreen(false);
//        System.setProperty("org.lwjgl.opengl.Window.undecorated", "false");
        if (canvas == null)
        {
          toggleCanvas = true;            
        }
      }
      else if ("Desktop".equals(displayType))
      {
//        hoping for a LWJGL enhancement
//        settings.setResolution(ddm.getWidth(), ddm.getHeight());
//        settings.setFullscreen(false);
//        System.setProperty("org.lwjgl.opengl.Window.undecorated", "true");
        
        this.ui.showAppletPopup();
        return;
      }
      else if ("Fullscreen".equals(displayType))
      {
        this.settings.setResolution(width, height);
        this.settings.setFullscreen(true);
        if (canvas == null)
        {
          toggleCanvas = true;            
        }
      }
      else
      {
        return;
      }
      
      this.restart();
      
      this.setSettingsDisplayMode(toggleCanvas);
    }
    else // Application
    {
      if ("Window".equals(displayType))
      {
        settings.setResolution(width, height);
        settings.setFullscreen(false);        
        System.setProperty("org.lwjgl.opengl.Window.undecorated", "false");
      }
      else if ("Desktop".equals(displayType))
      {
        settings.setResolution(ddm.getWidth(), ddm.getHeight());
        settings.setFullscreen(false);
        System.setProperty("org.lwjgl.opengl.Window.undecorated", "true");
      }
      else if ("Fullscreen".equals(displayType))
      {
        settings.setResolution(width, height);
        settings.setFullscreen(true);
      }
      else
      {
        return;
      }
      
      settings.setBitsPerPixel(ddm.getBitsPerPixel());
      settings.setFrequency(ddm.getFrequency());
      restart();
    }
  }  


Edit: For the LWJGL change... there is already a method

private static boolean isUndecorated() {
		return Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");
	}


in "org.lwjgl.opengl.WindowsDisplay". You can imagine there are many ways how to alter it. One could do it for WindowsDisplay only or generally for all implementations. One could even add a field in DisplayMode for it. That is up to the LWJGL devs. I simply did it in WindowsDisplay as a quick proof of concept. I don't use it since I need the signed AppletLoader.

WindowsDisplay:
private static boolean isUndecorated() {
		return Display.isUndecorated();
	}


Display:
private static boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");

	public static boolean isUndecorated() {
		return Display.undecorated;
	}

	public static void setUndecorated(boolean value) {
		Display.undecorated = value;
	}