From 518ad21d6cf0fa58998f7ddf410c3a445cca727c Mon Sep 17 00:00:00 2001 From: tulius Date: Sun, 10 Aug 2014 01:38:00 +0200 Subject: [PATCH] linux: improved xrandr-based display mode changing - fullscreen windows appear on primary screen - bits per pixel is derived from old getAvailableDisplayModes - removed debug output --- src/java/org/lwjgl/opengl/LinuxDisplay.java | 26 +++++++-- src/java/org/lwjgl/opengl/XRandR.java | 63 +++++++++++++-------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 6abbab8c..d46f0085 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -482,7 +482,16 @@ final class LinuxDisplay implements DisplayImplementation { window_y = y; window_width = mode.getWidth(); window_height = mode.getHeight(); - + + // overwrite arguments x and y - superclass always uses 0,0 for fullscreen windows + // use the coordinates of XRandRs primary screen instead + // this is required to let the fullscreen window appear on the primary screen + if (mode.isFullscreenCapable() && current_displaymode_extension == XRANDR) { + Screen primaryScreen = XRandR.DisplayModetoScreen(Display.getDisplayMode()); + x = primaryScreen.xPos; + y = primaryScreen.yPos; + } + current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window, resizable); // Set the WM_CLASS hint which is needed by some WM's e.g. Gnome Shell @@ -604,7 +613,7 @@ final class LinuxDisplay implements DisplayImplementation { private void switchDisplayModeOnTmpDisplay(DisplayMode mode) throws LWJGLException { if (current_displaymode_extension == XRANDR) { // let Xrandr set the display mode - XRandR.setConfiguration(XRandR.toScreen(mode)); + XRandR.setConfiguration(false, XRandR.DisplayModetoScreen(mode)); } else { incDisplay(); try { @@ -734,7 +743,7 @@ final class LinuxDisplay implements DisplayImplementation { saved_mode = AccessController.doPrivileged(new PrivilegedAction() { public DisplayMode run() { XRandR.saveConfiguration(); - return XRandR.toDisplayMode(XRandR.getConfiguration()); + return XRandR.ScreentoDisplayMode(XRandR.getConfiguration()); } }); break; @@ -935,12 +944,17 @@ final class LinuxDisplay implements DisplayImplementation { try { incDisplay(); if (current_displaymode_extension == XRANDR) { - // nGetAvailableDisplayModes cannot be trusted. Use xrandr + // nGetAvailableDisplayModes cannot be trusted. Use it only for bitsPerPixel + DisplayMode[] nDisplayModes = nGetAvailableDisplayModes(getDisplay(), getDefaultScreen(), current_displaymode_extension); + int bpp = 24; + if (nDisplayModes.length > 0) { + bpp = nDisplayModes[0].getBitsPerPixel(); + } + // get the resolutions and frequencys from XRandR Screen[] resolutions = XRandR.getResolutions(XRandR.getScreenNames()[0]); - // quick hack, copy Screens to DisplayModes (todo: get bpp from somewhere, instead of using 24 as default) DisplayMode[] modes = new DisplayMode[resolutions.length]; for (int i = 0; i < modes.length; i++) { - modes[i] = new DisplayMode(resolutions[i].width, resolutions[i].height, 24, resolutions[i].freq); + modes[i] = new DisplayMode(resolutions[i].width, resolutions[i].height, bpp, resolutions[i].freq); } return modes; } else { diff --git a/src/java/org/lwjgl/opengl/XRandR.java b/src/java/org/lwjgl/opengl/XRandR.java index cf8e65a4..0d6a5ef9 100644 --- a/src/java/org/lwjgl/opengl/XRandR.java +++ b/src/java/org/lwjgl/opengl/XRandR.java @@ -156,7 +156,6 @@ public class XRandR // find and return primary for (Screen screen : current) { if (screen.name.equals(primaryScreenIdentifier)) { - System.out.println("getConfiguration returned " + screen.width + "x" + screen.height + " @" + screen.freq); return new Screen[]{screen}; } } @@ -166,12 +165,14 @@ public class XRandR } /** + * @param disableOthers + * if screens not included in screens should be turned off (true) or left alone (false) * @param screens * The desired screen set, may not be null * @throws IllegalArgumentException * if no screens are specified */ - public static void setConfiguration(Screen... screens) + public static void setConfiguration(boolean disableOthers, Screen... screens) { if( screens.length == 0 ) throw new IllegalArgumentException( "Must specify at least one screen" ); @@ -179,22 +180,24 @@ public class XRandR List cmd = new ArrayList(); cmd.add( "xrandr" ); - // switch off those in the current set not in the new set - for ( Screen screen : current ) { - boolean found = false; - for ( Screen screen1 : screens ) { - if ( screen1.name.equals(screen.name) ) { - found = true; - break; - } - } + if (disableOthers) { + // switch off those in the current set not in the new set + for ( Screen screen : current ) { + boolean found = false; + for ( Screen screen1 : screens ) { + if ( screen1.name.equals(screen.name) ) { + found = true; + break; + } + } - if ( !found ) { - cmd.add("--output"); - cmd.add(screen.name); - cmd.add("--off"); - } - } + if ( !found ) { + cmd.add("--output"); + cmd.add(screen.name); + cmd.add("--off"); + } + } + } // set up new set for ( Screen screen : screens ) @@ -237,7 +240,7 @@ public class XRandR */ public static void restoreConfiguration() { if (savedConfiguration != null) { - setConfiguration(savedConfiguration); + setConfiguration(true, savedConfiguration); } } @@ -332,16 +335,26 @@ public class XRandR screenPosition[1] = Integer.parseInt(m.group(4)); } - static Screen toScreen(DisplayMode mode) { + static Screen DisplayModetoScreen(DisplayMode mode) { populate(); - // test: use first screen in list - // TODO: replace with "primary" - return new Screen(current[0].name, mode.getWidth(), mode.getHeight(), mode.getFrequency(), current[0].xPos, current[0].yPos); + Screen primary = findPrimary(current); + return new Screen(primary.name, mode.getWidth(), mode.getHeight(), mode.getFrequency(), primary.xPos, primary.yPos); } - static DisplayMode toDisplayMode(Screen... screens) { - // todo: use "primary" screen - return new DisplayMode(screens[0].width, screens[0].height, 24, screens[0].freq); + static DisplayMode ScreentoDisplayMode(Screen... screens) { + populate(); + Screen primary = findPrimary(screens); + return new DisplayMode(primary.width, primary.height, 24, primary.freq); + } + + private static Screen findPrimary(Screen... screens) { + for (Screen screen : screens) { + if (screen.name.equals(primaryScreenIdentifier)) { + return screen; + } + } + // fallback + return screens[0]; } /**