aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-03-20 21:42:23 +0100
committerSven Gothel <[email protected]>2015-03-20 21:42:23 +0100
commit2c88b6dfd4eb7e2cd9a50fa48e08ecafc980931a (patch)
tree2d89ec775fdd59499a934d622462b8915b89cead /src/newt
parentd9fe5c4aee7547bb89571c19c89ad173b63a4598 (diff)
Bug 1147 - Fix XRandR13 Usage: Rotate / Change-Mode, use unique CRTC/Mode ids, ..
RandR 1.3 XRRSetCrtcConfig related: - X11RandR13 now sets the new screen size via XRRSetScreenSize(..) - X11RandR13 now propagates RRScreenChangeNotify events via XRRUpdateConfiguration(event). Hence reporting virtual desktop size now. - X11RandR13 now disables the CRTC before XRRSetCrtcConfig(..) to avoid invalid configuration (see spec)! RandR 1.3 General: - Uses unique id named instead of unstable index for modes and CRTC. This allows proper identification even for 'swizzled' devices.
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorDevice.java1
-rw-r--r--src/newt/classes/jogamp/newt/MonitorModeProps.java2
-rw-r--r--src/newt/classes/jogamp/newt/ScreenImpl.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java25
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR.java23
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR11.java104
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR13.java71
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java37
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java6
-rw-r--r--src/newt/native/X11Display.c22
-rw-r--r--src/newt/native/X11RandR11.c89
-rw-r--r--src/newt/native/X11RandR13.c275
-rw-r--r--src/newt/native/X11Screen.c6
-rw-r--r--src/newt/native/X11Screen.h4
-rw-r--r--src/newt/native/X11Window.c6
-rw-r--r--src/newt/native/xrandr_utils.c322
16 files changed, 766 insertions, 229 deletions
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
index 4f06a946a..e96fc82f5 100644
--- a/src/newt/classes/com/jogamp/newt/MonitorDevice.java
+++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
@@ -332,6 +332,7 @@ public abstract class MonitorDevice {
/**
* Set the current {@link com.jogamp.newt.MonitorMode}.
+ * <p>This method is <a href="Window.html#lifecycleHeavy">lifecycle heavy</a>.</p>
* @param mode to be made current, must be element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
* @return true if successful, otherwise false
* @throws IllegalStateException if the {@link #getScreen() associated screen} is not {@link Screen#isNativeValid() valid natively}.
diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java
index 073a9a355..4e2806118 100644
--- a/src/newt/classes/jogamp/newt/MonitorModeProps.java
+++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java
@@ -272,7 +272,7 @@ public class MonitorModeProps {
* @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
* @param screen the associated {@link ScreenImpl}
* @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
- * @param monitorProperties the input data minus supported modes!
+ * @param monitorProperties the input data inclusive supported modes.
* @param offset the offset to the input data
* @param monitor_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
* @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index c96a2e06e..347ea650e 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -440,7 +440,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
monitor.getMutuableViewportPU(),
monitor.getMutuableViewportWU());
if( DEBUG ) {
- System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": updated: "+viewportUpdated+
+ System.err.println("Screen.updateMonitorViewport["+Display.toHexString(monitor.getId())+"] @ "+Thread.currentThread().getName()+": updated: "+viewportUpdated+
", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits()+
", pixelScale ["+pixelScale[0]+", "+pixelScale[1]+"]");
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 3276f3ed1..81ccdbfcd 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -40,7 +40,6 @@ import java.nio.ByteBuffer;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.nativewindow.util.PixelFormat;
-
import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
@@ -110,7 +109,8 @@ public class DisplayDriver extends DisplayImpl {
try {
final long handle = _aDevice.getHandle();
if(0 != handle) {
- DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
+ DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */, // XKB disabled for now
+ randr_event_base, randr_error_base);
}
} finally {
_aDevice.unlock();
@@ -120,6 +120,8 @@ public class DisplayDriver extends DisplayImpl {
protected long getJavaObjectAtom() { return javaObjectAtom; }
protected long getWindowDeleteAtom() { return windowDeleteAtom; }
// protected long getKbdHandle() { return kbdHandle; } // XKB disabled for now
+ protected int getRandREventBase() { return randr_event_base; }
+ protected int getRandRErrorBase() { return randr_error_base; }
/** Returns <code>null</code> if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */
protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
@@ -142,14 +144,26 @@ public class DisplayDriver extends DisplayImpl {
private native void CompleteDisplay0(long handle);
- private void displayCompleted(final long javaObjectAtom, final long windowDeleteAtom /*, long kbdHandle */) {
+ private void displayCompleted(final long javaObjectAtom, final long windowDeleteAtom /*, long kbdHandle */,
+ final int randr_event_base, final int randr_error_base) {
this.javaObjectAtom=javaObjectAtom;
this.windowDeleteAtom=windowDeleteAtom;
// this.kbdHandle = kbdHandle; // XKB disabled for now
+ this.randr_event_base = randr_event_base;
+ this.randr_error_base = randr_error_base;
+ }
+ private void sendRRScreenChangeNotify(final long event) {
+ if( null != rAndR ) {
+ rAndR.sendRRScreenChangeNotify(getHandle(), event);
+ }
+ }
+ void registerRandR(final RandR rAndR) {
+ this.rAndR = rAndR;
}
private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */); // XKB disabled for now
- private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
+ private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */, // XKB disabled for now
+ final int randr_event_base, final int randr_error_base);
private static long createPointerIcon(final long display, final Buffer pixels, final int width, final int height, final int hotX, final int hotY) {
final boolean pixels_is_direct = Buffers.isDirect(pixels);
@@ -171,5 +185,8 @@ public class DisplayDriver extends DisplayImpl {
/** X11 Keyboard handle used on EDT */
// private long kbdHandle; // XKB disabled for now
+ private int randr_event_base, randr_error_base;
+
+ private RandR rAndR;
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
index 14c9c0856..f45762173 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
@@ -43,6 +43,8 @@ public interface RandR {
public static final VersionNumber version140 = new VersionNumber(1, 4, 0);
VersionNumber getVersion();
+ @Override
+ String toString();
void dumpInfo(final long dpy, final int screen_idx);
@@ -50,7 +52,7 @@ public interface RandR {
* Encapsulate initial device query allowing caching of internal data structures.
* Methods covered:
* <ul>
- * <li>{@link #getMonitorDeviceCount(long, ScreenDriver)}</li>
+ * <li>{@link #getMonitorDeviceIds(long, ScreenDriver)}</li>
* <li>{@link #getAvailableRotations(long, ScreenDriver, int)}</li>
* <li>{@link #getMonitorModeProps(long, ScreenDriver, int)}</li>
* <li>{@link #getCurrentMonitorModeProps(long, ScreenDriver, int)</li>
@@ -67,8 +69,8 @@ public interface RandR {
boolean beginInitialQuery(long dpy, ScreenDriver screen);
void endInitialQuery(long dpy, ScreenDriver screen);
- int getMonitorDeviceCount(final long dpy, final ScreenDriver screen);
- int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx);
+ int[] getMonitorDeviceIds(final long dpy, final ScreenDriver screen);
+ int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_id);
/**
*
* @param dpy
@@ -77,10 +79,15 @@ public interface RandR {
* @return props w/o actual rotation
*/
int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx);
- int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx);
- int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx);
- int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx);
- boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+ int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_id);
+ int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_id);
+ int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_id);
+ /** The device shall be locked, blocking message handling. */
+ boolean setCurrentMonitorModeStart(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+ /** The device must not be locked, allowing message handling. */
+ boolean setCurrentMonitorModeWait(final ScreenDriver screen);
+ /** Invoked from Display's EDT thread for message handling. */
+ void sendRRScreenChangeNotify(final long dpy, final long event);
- public void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport);
+ void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
index e9cb95548..8fd03320a 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
@@ -40,12 +40,19 @@ import com.jogamp.newt.Screen;
class RandR11 implements RandR {
private static final boolean DEBUG = ScreenDriver.DEBUG;
- RandR11() {
+ private static final int SINGLE_CRT_ID = 0x01;
+
+ private final VersionNumber version;
+
+ RandR11(final VersionNumber version) {
+ this.version = version;
}
@Override
- public final VersionNumber getVersion() {
- return version110;
+ public final VersionNumber getVersion() { return version; }
+ @Override
+ public String toString() {
+ return "RandR11[version "+version+"]";
}
@Override
@@ -104,13 +111,14 @@ class RandR11 implements RandR {
}
@Override
- public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
- return 1;
+ public int[] getMonitorDeviceIds(final long dpy, final ScreenDriver screen) {
+ // RandR11 only supports 1 CRT
+ return new int[] { SINGLE_CRT_ID };
}
@Override
- public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
- if( 0 < crt_idx ) {
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_id) {
+ if( SINGLE_CRT_ID != crt_id ) {
// RandR11 only supports 1 CRT
return null;
}
@@ -171,12 +179,12 @@ class RandR11 implements RandR {
}
@Override
- public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
- if( 0 < crt_idx ) {
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_id) {
+ if( SINGLE_CRT_ID != crt_id ) {
// RandR11 only supports 1 CRT
return null;
}
- final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_idx);
+ final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_id);
if( null == currentModeProps) { // disabled
return null;
}
@@ -185,9 +193,9 @@ class RandR11 implements RandR {
final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 + allModesCount];
int i = 0;
props[i++] = props.length;
- props[i++] = crt_idx;
+ props[i++] = SINGLE_CRT_ID;
props[i++] = 0; // is-clone
- props[i++] = 0 == crt_idx ? 1 : 0; // is-primary
+ props[i++] = 0 == crt_id ? 1 : 0; // is-primary
props[i++] = widthMM;
props[i++] = heightMM;
props[i++] = 0; // rotated viewport x pixel-units
@@ -207,8 +215,8 @@ class RandR11 implements RandR {
}
@Override
- public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
- if( 0 < crt_idx ) {
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_id) {
+ if( SINGLE_CRT_ID != crt_id ) {
// RandR11 only supports 1 CRT
return null;
}
@@ -252,8 +260,8 @@ class RandR11 implements RandR {
}
@Override
- public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
- if( 0 < crt_idx ) {
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_id) {
+ if( SINGLE_CRT_ID != crt_id ) {
// RandR11 only supports 1 CRT
return null;
}
@@ -313,35 +321,63 @@ class RandR11 implements RandR {
}
@Override
- public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
- final long t0 = System.currentTimeMillis();
- boolean done = false;
+ public boolean setCurrentMonitorModeStart(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
final int screen_idx = screen.getIndex();
final long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
if(0 == screenConfigHandle) {
- return Boolean.valueOf(done);
+ return false;
}
+ boolean res = false;
try {
- final int resId = mode.getId();
- if(0>resId || resId>=resolutionCount) {
- throw new RuntimeException("Invalid resolution index: ! 0 < "+resId+" < "+resolutionCount+", "+monitor+", "+mode);
+ final int mode_idx = mode.getId();
+ if(0>mode_idx || mode_idx>=resolutionCount) {
+ throw new RuntimeException("Invalid resolution index: ! 0 < "+mode_idx+" < "+resolutionCount+", "+monitor+", "+mode);
}
- final int f = (int)mode.getRefreshRate(); // simply cut-off, orig is int
- final int r = mode.getRotation();
-
- if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resId, f, r) ) {
- while(!done && System.currentTimeMillis()-t0 < Screen.SCREEN_MODE_CHANGE_TIMEOUT) {
- done = setCurrentScreenModePollEnd0(dpy, screen_idx, resId, f, r);
- if(!done) {
- try { Thread.sleep(10); } catch (final InterruptedException e) { }
- }
- }
+ final int freq = (int)mode.getRefreshRate(); // simply cut-off, orig is int
+ final int rot = mode.getRotation();
+ set_screen_idx = screen_idx;
+ set_mode_idx = mode_idx;
+ set_freq = freq;
+ set_rot = rot;
+ set_done = false;
+ res = setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, mode_idx, freq, rot);
+ if( !res ) {
+ clearSetModeState();
}
} finally {
freeScreenConfiguration0(screenConfigHandle);
}
+ return res;
+ }
+ @Override
+ public boolean setCurrentMonitorModeWait(final ScreenDriver screen) {
+ final long t0 = System.currentTimeMillis();
+ boolean done = false;
+ while(!done && System.currentTimeMillis()-t0 < Screen.SCREEN_MODE_CHANGE_TIMEOUT) {
+ done = set_done;
+ if(!done) {
+ try { Thread.sleep(10); } catch (final InterruptedException e) { }
+ }
+ }
+ clearSetModeState();
return done;
}
+ volatile int set_screen_idx;
+ volatile int set_mode_idx;
+ volatile int set_freq;
+ volatile int set_rot;
+ volatile boolean set_done;
+ @Override
+ public void sendRRScreenChangeNotify(final long dpy, final long event) {
+ set_done = sendRRScreenChangeNotify0(dpy, set_screen_idx, event, set_mode_idx, set_freq, set_rot);
+ }
+ private void clearSetModeState() {
+ set_screen_idx = -1;
+ set_mode_idx = -1;
+ set_freq = 0;
+ set_rot = 0;
+ set_done = false;
+ }
@Override
public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
@@ -367,6 +403,6 @@ class RandR11 implements RandR {
/** needs own Display connection for XRANDR event handling */
private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
- private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+ private static native boolean sendRRScreenChangeNotify0(long display, int screen_index, final long event, int mode_index, int freq, int rot);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
index 2f7110b5c..95bff0118 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
@@ -47,13 +47,17 @@ import com.jogamp.newt.MonitorMode;
*/
class RandR13 implements RandR {
private static final boolean DEBUG = ScreenDriver.DEBUG;
+ private final VersionNumber version;
- RandR13() {
+ RandR13(final VersionNumber version) {
+ this.version = version;
}
@Override
- public final VersionNumber getVersion() {
- return version130;
+ public final VersionNumber getVersion() { return version; }
+ @Override
+ public String toString() {
+ return "RandR13[version "+version+"]";
}
@Override
@@ -113,16 +117,16 @@ class RandR13 implements RandR {
}
}
- private final long getMonitorInfoHandle(final long dpy, final int screen_idx, final long screenResources, final int monitor_idx) {
+ private final long getMonitorInfoHandle(final long dpy, final int screen_idx, final long screenResources, final int crt_id) {
if( null != crtInfoHandleMap ) {
- long h = crtInfoHandleMap.get(monitor_idx);
+ long h = crtInfoHandleMap.get(crt_id);
if( 0 == h ) {
- h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
- crtInfoHandleMap.put(monitor_idx, h);
+ h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, crt_id);
+ crtInfoHandleMap.put(crt_id, h);
}
return h;
} else {
- return getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+ return getMonitorInfoHandle0(dpy, screen_idx, screenResources, crt_id);
}
}
private final void releaseMonitorInfoHandle(final long monitorInfoHandle) {
@@ -132,22 +136,22 @@ class RandR13 implements RandR {
}
@Override
- public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+ public int[] getMonitorDeviceIds(final long dpy, final ScreenDriver screen) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- return getMonitorDeviceCount0(screenResources);
+ return getMonitorDeviceIds0(screenResources);
} finally {
releaseScreenResourceHandle(screenResources);
}
}
@Override
- public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_id) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_id);
try {
final int[] availRotations = getAvailableRotations0(monitorInfo);
if(null==availRotations || 0==availRotations.length) {
@@ -174,13 +178,13 @@ class RandR13 implements RandR {
}
@Override
- public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_id) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_id);
try {
- return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_idx);
+ return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_id);
} finally {
releaseMonitorInfoHandle(monitorInfo);
}
@@ -190,11 +194,11 @@ class RandR13 implements RandR {
}
@Override
- public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_id) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_id);
try {
return getMonitorViewport0(monitorInfo);
} finally {
@@ -206,11 +210,11 @@ class RandR13 implements RandR {
}
@Override
- public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_id) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_id);
try {
return getMonitorCurrentMode0(screenResources, monitorInfo);
} finally {
@@ -222,15 +226,15 @@ class RandR13 implements RandR {
}
@Override
- public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
+ public boolean setCurrentMonitorModeStart(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
final boolean res;
try {
final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
try {
- res = setMonitorMode0(dpy, screenResources, monitorInfo, monitor.getId(), mode.getId(), mode.getRotation(),
- -1, -1); // no fixed position!
+ res = setMonitorMode0(dpy, screen_idx, screenResources, monitorInfo, monitor.getId(),
+ mode.getId(), mode.getRotation(), -1, -1); // no fixed position!
} finally {
releaseMonitorInfoHandle(monitorInfo);
}
@@ -239,6 +243,15 @@ class RandR13 implements RandR {
}
return res;
}
+ @Override
+ public void sendRRScreenChangeNotify(final long dpy, final long event) {
+ sendRRScreenChangeNotify0(dpy, event);
+ }
+ @Override
+ public boolean setCurrentMonitorModeWait(final ScreenDriver screen) {
+ // RandR13 set command waits until done ..
+ return true;
+ }
@Override
public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
@@ -255,9 +268,9 @@ class RandR13 implements RandR {
private static native void freeScreenResources0(long screenResources);
private static native void dumpInfo0(long display, int screen_index, long screenResources);
- private static native int getMonitorDeviceCount0(long screenResources);
+ private static native int[] getMonitorDeviceIds0(long screenResources);
- private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int monitor_index);
+ private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int crtc_id);
private static native void freeMonitorInfoHandle0(long monitorInfoHandle);
private static native int[] getAvailableRotations0(long monitorInfo);
@@ -266,8 +279,12 @@ class RandR13 implements RandR {
private static native int[] getMonitorMode0(long screenResources, int mode_index);
private static native int[] getMonitorCurrentMode0(long screenResources, long monitorInfo);
- private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int monitor_idx);
+ private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int crtc_id);
- private static native boolean setMonitorMode0(long display, long screenResources, long monitorInfo, int monitor_idx, int mode_id, int rotation, int x, int y);
- private static native boolean setScreenViewport0(long display, int screen_index, long screenResources, int x, int y, int width, int height);
+ private static native boolean setMonitorMode0(long display, int screen_index, long screenResources,
+ long monitorInfo, int crtc_id,
+ int mode_id, int rotation, int x, int y);
+ private static native boolean setScreenViewport0(long display, int screen_index, long screenResources,
+ int x, int y, int width, int height);
+ private static native void sendRRScreenChangeNotify0(long display, final long event);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index 993ff58f9..2dc416063 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -91,15 +91,16 @@ public class ScreenDriver extends ScreenImpl {
}
{
if( !DEBUG_TEST_RANDR13_DISABLED && randrVersion.compareTo(RandR.version130) >= 0 ) {
- rAndR = new RandR13();
+ rAndR = new RandR13(randrVersion);
} else if( randrVersion.compareTo(RandR.version110) >= 0 ) {
- rAndR = new RandR11();
+ rAndR = new RandR11(randrVersion);
} else {
rAndR = null;
}
}
+ ((DisplayDriver)display).registerRandR(rAndR);
if( DEBUG ) {
- System.err.println("RandR "+randrVersion+", "+rAndR);
+ System.err.println("Using "+rAndR);
rAndR.dumpInfo(dpy, screen_idx);
}
}
@@ -119,12 +120,13 @@ public class ScreenDriver extends ScreenImpl {
try {
if( rAndR.beginInitialQuery(device.getHandle(), this) ) {
try {
- final int crtCount = rAndR.getMonitorDeviceCount(device.getHandle(), this);
+ final int[] crt_ids = rAndR.getMonitorDeviceIds(device.getHandle(), this);
+ final int crtCount = crt_ids.length;
// Gather all available rotations
final ArrayHashSet<Integer> availableRotations = new ArrayHashSet<Integer>();
for(int i = 0; i < crtCount; i++) {
- final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, i);
+ final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, crt_ids[i]);
if( null != rotations ) {
final List<Integer> rotationList = new ArrayList<Integer>(rotations.length);
for(int j=0; j<rotations.length; j++ ) { rotationList.add(rotations[j]); }
@@ -148,7 +150,7 @@ public class ScreenDriver extends ScreenImpl {
}
if( cache.monitorModes.size() > 0 ) {
for(int i = 0; i < crtCount; i++) {
- final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, i);
+ final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, crt_ids[i]);
if( null != monitorProps &&
MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ?
MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) {
@@ -196,16 +198,21 @@ public class ScreenDriver extends ScreenImpl {
if( null == rAndR ) { return false; }
final long t0 = System.currentTimeMillis();
- final boolean done = runWithOptTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
+ final boolean started = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
@Override
public Boolean run(final long dpy) {
- return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) );
+ return Boolean.valueOf( rAndR.setCurrentMonitorModeStart(dpy, ScreenDriver.this, monitor, mode) );
}
}).booleanValue();
-
+ final boolean done;
+ if( started ) {
+ done = rAndR.setCurrentMonitorModeWait(this);
+ } else {
+ done = false;
+ }
if(DEBUG || !done) {
- System.err.println("X11Screen.setCurrentMonitorModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
- (System.currentTimeMillis()-t0)+"ms; "+monitor.getCurrentMode()+" -> "+mode);
+ System.err.println("X11Screen.setCurrentMonitorModeImpl: "+(done?" OK":"NOK")+" (started "+started+"): t/TO "+
+ (System.currentTimeMillis()-t0)+"/"+SCREEN_MODE_CHANGE_TIMEOUT+"ms; "+monitor.getCurrentMode()+" -> "+mode);
}
return done;
}
@@ -276,14 +283,6 @@ public class ScreenDriver extends ScreenImpl {
return res;
}
- private final <T> T runWithOptTempDisplayHandle(final DisplayRunnable<T> action) {
- if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 ) {
- return display.runWithLockedDisplayDevice(action);
- } else {
- return runWithTempDisplayHandle(action);
- }
- }
-
private static native long GetScreen0(long dpy, int scrn_idx);
private static native int getWidth0(long display, int scrn_idx);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index cdeb7d6d0..6cf9727f2 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -149,7 +149,8 @@ public class WindowDriver extends WindowImpl {
edtDevice.lock();
try {
CloseWindow0(edtDevice.getHandle(), windowHandleClose,
- display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */); // XKB disabled for now
+ display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */, // XKB disabled for now
+ display.getRandREventBase(), display.getRandRErrorBase());
} catch (final Throwable t) {
if(DEBUG_IMPLEMENTATION) {
final Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
@@ -451,7 +452,8 @@ public class WindowDriver extends WindowImpl {
int visualID, long javaObjectAtom, long windowDeleteAtom,
int x, int y, int width, int height, boolean autoPosition, int flags,
int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct);
- private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
+ private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/, // XKB disabled for now
+ final int randr_event_base, final int randr_error_base);
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
long windowDeleteAtom, int x, int y, int width, int height, int flags);
private native void requestFocus0(long display, long windowHandle, boolean force);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 60daf1af2..b79c1ee95 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -39,6 +39,7 @@ jmethodID visibleChangedID = NULL;
static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver";
static jmethodID displayCompletedID = NULL;
+static jmethodID sendRRScreenChangeNotifyID = NULL;
static jmethodID getCurrentThreadNameID = NULL;
static jmethodID dumpStackID = NULL;
@@ -242,8 +243,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
}
}
- // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB
- displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
+ // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJII)V"); // Variant using XKB
+ displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJII)V");
+ sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)V");
getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V");
@@ -259,6 +261,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
if (displayCompletedID == NULL ||
+ sendRRScreenChangeNotifyID == NULL ||
getCurrentThreadNameID == NULL ||
dumpStackID == NULL ||
insetsChangedID == NULL ||
@@ -311,9 +314,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
// XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
// kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now
+ int randr_event_base, randr_error_base;
+ XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+
DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
- (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/, // XKB disabled for now
+ randr_event_base, randr_error_base);
}
/*
@@ -349,7 +356,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
* Signature: (JJJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/,
+ jint randr_event_base, jint randr_error_base)
{
Display * dpy = (Display *) (intptr_t) display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -397,6 +405,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
return ;
}
+ if( randr_event_base > 0 && RRScreenChangeNotify == ( evt.type - randr_event_base ) ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event RRScreenChangeNotify %p\n", (void*)dpy, (void*)&evt);
+ (*env)->CallVoidMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt);
+ continue;
+ }
+
if( 0==evt.xany.window ) {
DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
continue;
diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c
index 38d61289b..8d2651d61 100644
--- a/src/newt/native/X11RandR11.c
+++ b/src/newt/native/X11RandR11.c
@@ -297,75 +297,56 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenM
DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
- int xrot = NewtScreen_Degree2XRotation(env, rotation);
-
XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
- XSync(dpy, False);
+ Rotation xrot = NewtScreen_Degree2XRotation(env, rotation);
XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime);
- XSync(dpy, False);
-
return JNI_TRUE;
}
/*
* Class: jogamp_newt_driver_x11_RandR11
- * Method: setCurrentScreenModePollEnd0
- * Signature: (JIII)Z
+ * Method: sendRRScreenChangeNotify0
+ * Signature: (JIJIII)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModePollEnd0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_sendRRScreenChangeNotify0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong jevent, jint resMode_idx, jint freq, jint rotation)
{
- Display *dpy = (Display *) (intptr_t) display;
- int randr_event_base, randr_error_base;
- XEvent evt;
- XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
+ Display * dpy = (Display *) (intptr_t) display;
+ XEvent *event = (XEvent*)(intptr_t)jevent;
+ XRRUpdateConfiguration(event);
+ DBG_PRINT("RandR11_sendRRScreenChangeNotify0: dpy %p, event %p\n", dpy, event);
+ if( -1 == resMode_idx || -1 == screen_idx ) {
+ // No validation requested
+ return JNI_FALSE;
+ }
+ // Validate numbers ..
+ XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) event;
int num_sizes;
XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- XRRScreenConfiguration *conf;
-
if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
}
- XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
- int done = 0;
- int rot;
- do {
- if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
- return JNI_FALSE; // not done
+ jboolean done = JNI_FALSE;
+ if(0 < scn_event->rotation ) { // All valid values greater zero: 0, 90, 180, 270, ..
+ int rot = NewtScreen_XRotation2Degree(env, scn_event->rotation);
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(OK) %p (root %p) resIdx %d rot %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index, rot,
+ scn_event->width, scn_event->height);
+ // done = scn_event->size_index == resMode_idx; // not reliable ..
+ if( rot == rotation &&
+ scn_event->width == xrrs[resMode_idx].width &&
+ scn_event->height == xrrs[resMode_idx].height ) {
+ done = JNI_TRUE;
}
- XNextEvent(dpy, &evt);
-
- switch (evt.type - randr_event_base) {
- case RRScreenChangeNotify:
- if(0 < scn_event->rotation ) {
- rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
- DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n",
- (void*)scn_event->window, (void*)scn_event->root,
- (int)scn_event->size_index, rot,
- scn_event->width, scn_event->height);
- // done = scn_event->size_index == resMode_idx; // not reliable ..
- done = rot == rotation &&
- scn_event->width == xrrs[resMode_idx].width &&
- scn_event->height == xrrs[resMode_idx].height;
- } else {
- DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n",
- (void*)scn_event->window, (void*)scn_event->root,
- (int)scn_event->size_index,
- scn_event->width, scn_event->height);
- }
- break;
- default:
- DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
- }
- XRRUpdateConfiguration(&evt);
- } while(!done);
-
- XSync(dpy, False);
-
- return done ? JNI_TRUE : JNI_FALSE;
+ } else { // invalid .. skip
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(SKIP) %p (root %p) resIdx %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index,
+ scn_event->width, scn_event->height);
+ }
+ return done;
}
+
diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c
index 4f52ad190..37a6ea055 100644
--- a/src/newt/native/X11RandR13.c
+++ b/src/newt/native/X11RandR13.c
@@ -61,33 +61,35 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0
#define SAFE_STRING(s) (NULL==s?"":s)
-static void dumpOutputs(const char *prefix, Display *dpy, int screen_idx, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+static void dumpOutput(const char *prefix, Display *dpy, int screen_idx, XRRScreenResources *resources, int outputIdx, RROutput output) {
int i, j, primIdx=0;
Window root = RootWindow(dpy, screen_idx);
RROutput pxid = XRRGetOutputPrimary (dpy, root);
- fprintf(stderr, "%s %p: Output[count %d, prim %#lx]\n", prefix, resources, noutput, pxid);
+ int isPrim =0;
+ if ( None != pxid && pxid == output ) {
+ primIdx = i;
+ isPrim = 1;
+ }
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ fprintf(stderr, "%s: Output[%d]: id %#lx, crtx 0x%lX, name %s (%d), %lux%lu, ncrtc %d, nclone %d, nmode %d (preferred %d), primary %d\n",
+ prefix, outputIdx, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen,
+ xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
+ xrrOutputInfo->ncrtc, xrrOutputInfo->nclone, xrrOutputInfo->nmode, xrrOutputInfo->npreferred, isPrim);
+ for(j=0; j<xrrOutputInfo->ncrtc; j++) {
+ fprintf(stderr, "%s: Output[%d].Crtc[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->crtcs[j]);
+ }
+ for(j=0; j<xrrOutputInfo->nclone; j++) {
+ fprintf(stderr, "%s: Output[%d].Clones[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->clones[j]);
+ }
+ for(j=0; j<xrrOutputInfo->nmode; j++) {
+ fprintf(stderr, "%s: Output[%d].Mode[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->modes[j]);
+ }
+ XRRFreeOutputInfo (xrrOutputInfo);
+}
+static void dumpOutputs(const char *prefix, Display *dpy, int screen_idx, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+ int i;
for(i=0; i<noutput; i++) {
- int isPrim =0;
- RROutput output = outputs[i];
- if ( None != pxid && pxid == output ) {
- primIdx = i;
- isPrim = 1;
- }
- XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
- fprintf(stderr, " Output[%d]: id %#lx, crtx 0x%lX, name %s (%d), %lux%lu, ncrtc %d, nclone %d, nmode %d (preferred %d), primary %d\n",
- i, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen,
- xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
- xrrOutputInfo->ncrtc, xrrOutputInfo->nclone, xrrOutputInfo->nmode, xrrOutputInfo->npreferred, isPrim);
- for(j=0; j<xrrOutputInfo->ncrtc; j++) {
- fprintf(stderr, " Output[%d].Crtc[%d].id %#lx\n", i, j, xrrOutputInfo->crtcs[j]);
- }
- for(j=0; j<xrrOutputInfo->nclone; j++) {
- fprintf(stderr, " Output[%d].Clones[%d].id %#lx\n", i, j, xrrOutputInfo->clones[j]);
- }
- for(j=0; j<xrrOutputInfo->nmode; j++) {
- fprintf(stderr, " Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]);
- }
- XRRFreeOutputInfo (xrrOutputInfo);
+ dumpOutput(prefix, dpy, screen_idx, resources, i, outputs[i]);
}
}
@@ -116,7 +118,39 @@ static float getVRefresh(XRRModeInfo *mode) {
}
return rate;
}
+static RRCrtc findRRCrtc(XRRScreenResources *resources, RRCrtc crtc) {
+ if( NULL != resources ) {
+ int i;
+ for(i=resources->ncrtc-1; i>=0; i--) {
+ if( resources->crtcs[i] == crtc ) {
+ return crtc;
+ }
+ }
+ }
+ return 0;
+}
+static XRRCrtcInfo* getXRRCrtcInfo(Display *dpy, XRRScreenResources *resources, RRCrtc _crtc) {
+ RRCrtc crtc = findRRCrtc( resources, _crtc );
+ if( 0 == crtc ) {
+ return NULL;
+ } else {
+ return XRRGetCrtcInfo (dpy, resources, crtc);
+ }
+}
+static XRRModeInfo* findMode(XRRScreenResources *resources, RRMode modeId) {
+ if( NULL != resources ) {
+ int i;
+ for(i=resources->nmode-1; i>=0; i--) {
+ XRRModeInfo *imode = &resources->modes[i];
+ if( imode->id == modeId ) {
+ return imode;
+ }
+ }
+ }
+ return NULL;
+}
+#include "xrandr_utils.c"
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
(JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources)
@@ -144,10 +178,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
for(i=0; i<resources->ncrtc; i++) {
RRCrtc crtc = resources->crtcs[i];
XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
- fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n",
- i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
+ fprintf(stderr, "Crtc[%d] %#lx: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n",
+ i, crtc, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
for(j=0; j<xrrCrtcInfo->noutput; j++) {
fprintf(stderr, " Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]);
+ dumpOutput(" ", dpy, screen_idx, resources, j, xrrCrtcInfo->outputs[j]);
}
XRRFreeCrtcInfo(xrrCrtcInfo);
}
@@ -166,14 +201,28 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
/*
* Class: jogamp_newt_driver_x11_RandR13
- * Method: getMonitorDeviceCount0
+ * Method: getMonitorDeviceIds0
* Signature: (J)I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceIds0
(JNIEnv *env, jclass clazz, jlong screenResources)
{
XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
- return ( NULL != resources ) ? resources->ncrtc : 0;
+ int ncrtc = ( NULL != resources ) ? resources->ncrtc : 0;
+ jintArray properties = NULL;
+ if( 0 < ncrtc ) {
+ int crtcs[ncrtc];
+ int i;
+ for(i=0; i<ncrtc; i++) {
+ crtcs[i] = (int)(intptr_t)resources->crtcs[i];
+ }
+ properties = (*env)->NewIntArray(env, ncrtc);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", ncrtc);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, ncrtc, crtcs);
+ }
+ return properties;
}
/*
@@ -182,19 +231,12 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount
* Signature: (JIJI)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx)
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_id)
{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)screen_idx);
- XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
-
- if( NULL == resources || crt_idx >= resources->ncrtc ) {
- return 0;
- }
- RRCrtc crtc = resources->crtcs[crt_idx];
- XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
-
- return (jlong) (intptr_t) xrrCrtcInfo;
+ XRRCrtcInfo *xrrCrtcInfo = getXRRCrtcInfo((Display *)(intptr_t)display,
+ (XRRScreenResources *)(intptr_t)screenResources,
+ (RRCrtc)(intptr_t)crt_id );
+ return (jlong)(intptr_t)xrrCrtcInfo;
}
/*
@@ -360,16 +402,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurren
return NULL;
}
- int modeId = xrrCrtcInfo->mode;
- XRRModeInfo *mode = NULL;
- int i;
- for(i=0; i<resources->nmode; i++) {
- XRRModeInfo *imode = &resources->modes[i];
- if( imode->id == modeId ) {
- mode = imode;
- break;
- }
- }
+ RRMode modeId = xrrCrtcInfo->mode;
+ XRRModeInfo *mode = findMode(resources, modeId);
if( NULL == mode ) {
// oops ..
return NULL;
@@ -412,17 +446,20 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurren
* Signature: (JJJJ)[I
*/
JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
- (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx)
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_id)
{
Display * dpy = (Display *) (intptr_t) display;
XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ RRCrtc crtc = findRRCrtc( resources, (RRCrtc)(intptr_t)crt_id );
+ if( 0 == crtc ) {
+ // n/a
+ return NULL;
+ }
XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
-
- if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ if( NULL == xrrCrtcInfo ) {
// n/a
return NULL;
}
-
if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
// disabled
return NULL;
@@ -444,7 +481,7 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice
int propIndex = 0;
prop[propIndex++] = propCount;
- prop[propIndex++] = crt_idx;
+ prop[propIndex++] = crt_id;
prop[propIndex++] = 0; // isClone, does not work: 0 < xrrOutputInfo->nclone ? 1 : 0;
prop[propIndex++] = isPrimary;
prop[propIndex++] = xrrOutputInfo->mm_width;
@@ -457,14 +494,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice
prop[propIndex++] = xrrCrtcInfo->y; // rotated viewport window units (same)
prop[propIndex++] = xrrCrtcInfo->width; // rotated viewport window units (same)
prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport window units (same)
- prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
+ prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
int i;
for(i=0; i<numModes; i++) {
// avail modes ..
prop[propIndex++] = xrrOutputInfo->modes[i];
}
-
XRRFreeOutputInfo (xrrOutputInfo);
jintArray properties = (*env)->NewIntArray(env, propCount);
@@ -482,43 +518,147 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice
* Signature: (JJJIIIII)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0
- (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y)
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources,
+ jlong monitorInfo, jint crt_id,
+ jint jmode_id, jint rotation, jint x, jint y)
{
+ jboolean res = JNI_FALSE;
Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ RRCrtc crtc = findRRCrtc( resources, (RRCrtc)(intptr_t)crt_id );
+ if( 0 == crtc ) {
+ // n/a
+ DBG_PRINT("RandR13_setMonitorMode0.0: n/a: resources %p (%d), crt_id %#lx \n",
+ resources, (NULL == resources ? 0 : resources->ncrtc), (RRCrtc)(intptr_t)crt_id);
+ return res;
+ }
XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
- jboolean res = JNI_FALSE;
-
- if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ if( NULL == xrrCrtcInfo ) {
// n/a
+ DBG_PRINT("RandR13_setMonitorMode0.1: n/a: resources %p (%d), xrrCrtcInfo %p, crtc %#lx\n",
+ resources, (NULL == resources ? 0 : resources->ncrtc), xrrCrtcInfo, crtc);
return res;
}
-
if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
// disabled
+ DBG_PRINT("RandR13_setMonitorMode0: disabled: mode %d, noutput %d\n", xrrCrtcInfo->mode, xrrCrtcInfo->noutput);
return res;
}
-
- if( 0 >= modeId ) {
+ if( 0 >= jmode_id ) {
// oops ..
+ DBG_PRINT("RandR13_setMonitorMode0: inv. modeId: modeId %d\n", jmode_id);
return res;
}
+ RRMode mode_id = (RRMode)(intptr_t)jmode_id;
+ XRRModeInfo *mode_info = findMode(resources, mode_id);
+ if( NULL == mode_info ) {
+ // oops ..
+ DBG_PRINT("RandR13_setMonitorMode0: inv. mode_id: mode_id %#lx\n", mode_id);
+ return res;
+ }
if( 0 > x || 0 > y ) {
x = xrrCrtcInfo->x;
y = xrrCrtcInfo->y;
}
- Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime,
- x, y, modeId, NewtScreen_Degree2XRotation(env, rotation),
- xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+ Rotation xrotation = NewtScreen_Degree2XRotation(env, rotation);
+ int rot_change = xrrCrtcInfo->rotation != xrotation;
+ DBG_PRINT("RandR13_setMonitorMode0: crt %#lx, noutput %d -> 0x%X, mode %#lx -> %#lx, pos %d / %d, rotation %d -> %d (change %d)\n",
+ crtc, xrrCrtcInfo->noutput, xrrCrtcInfo->outputs[0], xrrCrtcInfo->mode, mode_id,
+ x, y, (int)xrrCrtcInfo->rotation, (int)xrotation, rot_change);
+
+ XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
+ Status status = RRSetConfigSuccess;
+ int pre_fb_width=0, pre_fb_height=0;
+ int fb_width=0, fb_height=0;
+ int fb_width_mm=0, fb_height_mm=0;
+
+ crtc_t *root_crtc = get_screen_size1(dpy, root, &fb_width, &fb_height,
+ resources, crtc, xrrCrtcInfo, xrotation, x, y, mode_info);
+
+ Bool fb_change = get_screen_sizemm(dpy, screen_idx, fb_width, fb_height,
+ &fb_width_mm, &fb_height_mm,
+ &pre_fb_width, &pre_fb_height);
+
+ DBG_PRINT("RandR13_setMonitorMode0: crt %#lx, fb[change %d: %d x %d -> %d x %d [%d x %d mm]\n",
+ crtc, fb_change, pre_fb_width, pre_fb_height, fb_width, fb_height, fb_width_mm, fb_height_mm);
+ if(fb_change) {
+ // Disable CRTC first, since new size differs from current
+ // and we shall avoid invalid intermediate configuration (see spec)!
+ #if 0
+ {
+ // Disable all CRTCs (Not required!)
+ crtc_t * iter_crtc;
+ for(iter_crtc=root_crtc; RRSetConfigSuccess == status && NULL!=iter_crtc; iter_crtc=iter_crtc->next) {
+ if( None == iter_crtc->mode_id || NULL == iter_crtc->mode_info || 0 == iter_crtc->crtc_info->noutput ) {
+ // disabled
+ continue;
+ }
+ status = XRRSetCrtcConfig (dpy, resources, iter_crtc->crtc_id, CurrentTime,
+ 0, 0, None, RR_Rotate_0, NULL, 0);
+ }
+ }
+ #else
+ status = XRRSetCrtcConfig (dpy, resources, crtc, CurrentTime,
+ 0, 0, None, RR_Rotate_0, NULL, 0);
+ #endif
+ DBG_PRINT("RandR13_setMonitorMode0: crt %#lx disable: %d -> %d\n", crtc, status, RRSetConfigSuccess == status);
+ if( RRSetConfigSuccess == status ) {
+ XRRSetScreenSize (dpy, root, fb_width, fb_height,
+ fb_width_mm, fb_height_mm);
+ DBG_PRINT("RandR13_setMonitorMode0: crt %#lx screen-size\n", crtc);
+ }
+ }
+ if( RRSetConfigSuccess == status ) {
+ #if 0
+ {
+ // Enable/Set all CRTCs (Not required!)
+ crtc_t * iter_crtc;
+ for(iter_crtc=root_crtc; RRSetConfigSuccess == status && NULL!=iter_crtc; iter_crtc=iter_crtc->next) {
+ if( None == iter_crtc->mode_id || NULL == iter_crtc->mode_info || 0 == iter_crtc->crtc_info->noutput ) {
+ // disabled
+ continue;
+ }
+ status = XRRSetCrtcConfig( dpy, resources, iter_crtc->crtc_id, CurrentTime,
+ iter_crtc->x, iter_crtc->y, iter_crtc->mode_id, iter_crtc->rotation,
+ iter_crtc->crtc_info->outputs, iter_crtc->crtc_info->noutput );
+ }
+ }
+ #else
+ status = XRRSetCrtcConfig( dpy, resources, crtc, CurrentTime,
+ x, y, mode_id, xrotation,
+ xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+ #endif
+ DBG_PRINT("RandR13_setMonitorMode0: crt %#lx set-config: %d -> %d\n", crtc, status, RRSetConfigSuccess == status);
+ }
+
res = status == RRSetConfigSuccess;
+ DBG_PRINT("RandR13_setMonitorMode0: FIN: %d -> ok %d\n", status, res);
+
+ destroyCrtcChain(root_crtc, crtc);
+ root_crtc=NULL;
return res;
}
/*
* Class: jogamp_newt_driver_x11_RandR13
+ * Method: sendRRScreenChangeNotify0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_sendRRScreenChangeNotify0
+ (JNIEnv *env, jclass clazz, jlong display, jlong jevent)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XEvent *event = (XEvent*)(intptr_t)jevent;
+ XRRUpdateConfiguration(event);
+ DBG_PRINT("RandR13_sendRRScreenChangeNotify0: dpy %p, event %p\n", dpy, event);
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
* Method: setScreenViewport0
* Signature: (JIJIIII)Z
*/
@@ -539,4 +679,3 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport
return JNI_TRUE;
}
-
diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c
index 152a092c9..b4bb8a112 100644
--- a/src/newt/native/X11Screen.c
+++ b/src/newt/native/X11Screen.c
@@ -74,7 +74,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0
return (jint) DisplayHeight( dpy, scrn_idx);
}
-int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+int NewtScreen_XRotation2Degree(JNIEnv *env, Rotation xrotation) {
int degree;
if(xrotation == RR_Rotate_0) {
degree = 0;
@@ -93,8 +93,8 @@ int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
return degree;
}
-int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
- int xrot;
+Rotation NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
+ Rotation xrot;
if(degree == 0) {
xrot = RR_Rotate_0;
}
diff --git a/src/newt/native/X11Screen.h b/src/newt/native/X11Screen.h
index c81ee05d5..5f47cc90d 100644
--- a/src/newt/native/X11Screen.h
+++ b/src/newt/native/X11Screen.h
@@ -32,7 +32,7 @@
#include "X11Common.h"
-int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation);
-int NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
+int NewtScreen_XRotation2Degree(JNIEnv *env, Rotation xrotation);
+Rotation NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
#endif /* _X11SCREEN_H */
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 43506c6a6..e640b0c20 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -696,7 +696,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
- (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/, // XKB disabled for now
+ jint randr_event_base, jint randr_error_base)
{
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
@@ -726,7 +727,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
XUnmapWindow(dpy, w);
// Drain all events related to this window ..
- Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
+ Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */, // XKB disabled for now
+ randr_event_base, randr_error_base);
XDestroyWindow(dpy, w);
if( None != xwa.colormap ) {
diff --git a/src/newt/native/xrandr_utils.c b/src/newt/native/xrandr_utils.c
new file mode 100644
index 000000000..564fdd44b
--- /dev/null
+++ b/src/newt/native/xrandr_utils.c
@@ -0,0 +1,322 @@
+/**
+ * This file contains code from xrandr.c,
+ * see <http://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c>:
+ *
+ * ++++
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2002 Hewlett Packard Company, Inc.
+ * Copyright © 2006 Intel Corporation
+ * Copyright © 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Thanks to Jim Gettys who wrote most of the client side code,
+ * and part of the server code for randr.
+ *
+ * ++++
+ *
+ * Modifications / Additions are from:
+ *
+ * Copyright 2015 JogAmp Community. All rights reserved.
+ *
+ * License text: Same as above!
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Common.h"
+
+#include <math.h>
+
+typedef struct {
+ int x1, y1, x2, y2;
+} box_t;
+typedef struct {
+ int x, y;
+} point_t;
+typedef struct {
+ XTransform transform;
+ char *filter;
+ int nparams;
+ XFixed *params;
+} transform_t;
+typedef struct _crtc {
+ struct _crtc *next;
+ RRCrtc crtc_id;
+ Rotation rotation;
+ transform_t transform;
+ int x, y;
+ RRMode mode_id;
+ // float refresh;
+ // Bool primary;
+
+ XRRModeInfo *mode_info;
+ XRRCrtcInfo *crtc_info;
+ XRRPanning *panning_info;
+} crtc_t;
+static int mode_height (XRRModeInfo *mode_info, Rotation rotation) {
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode_info->height;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode_info->width;
+ default:
+ return 0;
+ }
+}
+static int mode_width (XRRModeInfo *mode_info, Rotation rotation) {
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode_info->width;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode_info->height;
+ default:
+ return 0;
+ }
+}
+static Bool transform_point (XTransform *transform, double *xp, double *yp) {
+ double vector[3];
+ double result[3];
+ int i, j;
+ double v;
+
+ vector[0] = *xp;
+ vector[1] = *yp;
+ vector[2] = 1;
+ for (j = 0; j < 3; j++)
+ {
+ v = 0;
+ for (i = 0; i < 3; i++) {
+ v += (XFixedToDouble (transform->matrix[j][i]) * vector[i]);
+ }
+ if (v > 32767 || v < -32767) {
+ return False;
+ }
+ result[j] = v;
+ }
+ if (!result[2]) {
+ return False;
+ }
+ for (j = 0; j < 2; j++) {
+ vector[j] = result[j] / result[2];
+ }
+ *xp = vector[0];
+ *yp = vector[1];
+ return True;
+}
+static void path_bounds (XTransform *transform, point_t *points, int npoints, box_t *box) {
+ int i;
+ box_t point;
+
+ for (i = 0; i < npoints; i++) {
+ double x, y;
+ x = points[i].x;
+ y = points[i].y;
+ transform_point (transform, &x, &y);
+ point.x1 = floor (x);
+ point.y1 = floor (y);
+ point.x2 = ceil (x);
+ point.y2 = ceil (y);
+ if (i == 0) {
+ *box = point;
+ } else {
+ if (point.x1 < box->x1) { box->x1 = point.x1; }
+ if (point.y1 < box->y1) { box->y1 = point.y1; }
+ if (point.x2 > box->x2) { box->x2 = point.x2; }
+ if (point.y2 > box->y2) { box->y2 = point.y2; }
+ }
+ }
+}
+static void mode_geometry (XRRModeInfo *mode_info, Rotation rotation,
+ XTransform *transform, box_t *bounds) {
+ point_t rect[4];
+ int width = mode_width (mode_info, rotation);
+ int height = mode_height (mode_info, rotation);
+
+ rect[0].x = 0;
+ rect[0].y = 0;
+ rect[1].x = width;
+ rect[1].y = 0;
+ rect[2].x = width;
+ rect[2].y = height;
+ rect[3].x = 0;
+ rect[3].y = height;
+ path_bounds (transform, rect, 4, bounds);
+}
+static void get_screen_size0(Display * dpy, Window root,
+ crtc_t * root_crtc, int *io_scrn_width, int *io_scrn_height) {
+ int fb_width = *io_scrn_width;
+ int fb_height = *io_scrn_height;
+ crtc_t *crtc;
+ for (crtc = root_crtc; NULL != crtc; crtc = crtc->next) {
+ if( None == crtc->mode_id || NULL == crtc->mode_info || 0 == crtc->crtc_info->noutput ) {
+ // disabled
+ continue;
+ }
+ XRRModeInfo *mode_info = crtc->mode_info;
+ int x, y, w, h;
+ box_t bounds;
+
+ mode_geometry (mode_info, crtc->rotation,
+ &crtc->transform.transform, &bounds);
+ x = crtc->x + bounds.x1;
+ y = crtc->y + bounds.y1;
+ w = bounds.x2 - bounds.x1;
+ h = bounds.y2 - bounds.y1;
+
+ /* fit fb to crtc */
+ XRRPanning *pan;
+ if (x + w > fb_width) {
+ fb_width = x + w;
+ }
+ if (y + h > fb_height) {
+ fb_height = y + h;
+ }
+ pan = crtc->panning_info;
+ if (pan && pan->left + pan->width > fb_width) {
+ fb_width = pan->left + pan->width;
+ }
+ if (pan && pan->top + pan->height > fb_height) {
+ fb_height = pan->top + pan->height;
+ }
+ }
+ int minWidth=0, minHeight=0, maxWidth=0, maxHeight=0;
+ if( 1 != XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight) ) {
+ // Use defaults in case of error ..
+ minWidth=8; minHeight=8; maxWidth=16384; maxHeight=16384;
+ }
+ if( fb_width < minWidth ) {
+ fb_width = minWidth;
+ } else if( fb_width > maxWidth ) {
+ fb_width = maxWidth;
+ }
+ if( fb_height < minHeight ) {
+ fb_height = minHeight;
+ } else if( fb_height > maxHeight ) {
+ fb_height = maxHeight;
+ }
+ *io_scrn_width = fb_width;
+ *io_scrn_height = fb_height;
+}
+static crtc_t* createCrtcChain(Display *dpy,
+ XRRScreenResources *resources,
+ RRCrtc customCrtc, XRRCrtcInfo *customCrtcInfo,
+ Rotation customRotation, int customX, int customY,
+ XRRModeInfo *customModeInfo)
+{
+ crtc_t *root_crtc = NULL;
+ crtc_t *iter_crtc = NULL;
+ int i;
+ for(i=0; i<resources->ncrtc; i++) {
+ crtc_t *next_crtc = calloc(1, sizeof(crtc_t));
+ if( NULL == iter_crtc ) {
+ root_crtc = next_crtc;
+ } else {
+ iter_crtc->next = next_crtc;
+ }
+ iter_crtc = next_crtc;
+
+ RRCrtc crtcId = resources->crtcs[i];
+ iter_crtc->crtc_id = crtcId;
+ if( crtcId == customCrtc && 0 != customCrtc ) {
+ iter_crtc->rotation = customRotation;
+ iter_crtc->x = customX;
+ iter_crtc->y = customY;
+ iter_crtc->mode_info = customModeInfo;
+ iter_crtc->mode_id = customModeInfo->id;
+ iter_crtc->crtc_info = customCrtcInfo;
+ } else {
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtcId);
+ iter_crtc->rotation = xrrCrtcInfo->rotation;
+ iter_crtc->x = xrrCrtcInfo->x;
+ iter_crtc->y = xrrCrtcInfo->y;
+ iter_crtc->mode_id = xrrCrtcInfo->mode;
+ iter_crtc->mode_info = findMode(resources, iter_crtc->mode_id);
+ iter_crtc->crtc_info = xrrCrtcInfo;
+ }
+ iter_crtc->panning_info = XRRGetPanning(dpy, resources, crtcId);
+ }
+ return root_crtc;
+}
+static void destroyCrtcChain(crtc_t *root_crtc, RRCrtc customCrtc) {
+ crtc_t * iter_crtc = root_crtc;
+ while(NULL!=iter_crtc) {
+ if( NULL != iter_crtc->crtc_info ) {
+ if( iter_crtc->crtc_id != customCrtc || 0 == customCrtc ) {
+ XRRFreeCrtcInfo(iter_crtc->crtc_info);
+ }
+ iter_crtc->crtc_info = NULL;
+ }
+ if( NULL != iter_crtc->panning_info ) {
+ XRRFreePanning(iter_crtc->panning_info);
+ iter_crtc->panning_info = NULL;
+ }
+ {
+ crtc_t * last = iter_crtc;
+ iter_crtc = iter_crtc->next;
+ last->next = NULL;
+ free(last);
+ }
+ }
+}
+static crtc_t *get_screen_size1(Display * dpy, Window root,
+ int *io_scrn_width, int *io_scrn_height,
+ XRRScreenResources *resources,
+ RRCrtc customCrtc, XRRCrtcInfo *customCrtcInfo,
+ Rotation customRotation, int customX, int customY,
+ XRRModeInfo *customModeInfo) {
+ crtc_t *root_crtc = createCrtcChain(dpy, resources, customCrtc, customCrtcInfo,
+ customRotation, customX, customY, customModeInfo);
+ get_screen_size0(dpy, root, root_crtc, io_scrn_width, io_scrn_height);
+ return root_crtc;
+}
+static crtc_t *get_screen_size2(Display * dpy, Window root,
+ int *io_scrn_width, int *io_scrn_height,
+ XRRScreenResources *resources) {
+ crtc_t *root_crtc = createCrtcChain(dpy, resources, 0, NULL, 0, 0, 0, NULL);
+ get_screen_size0(dpy, root, root_crtc, io_scrn_width, io_scrn_height);
+ return root_crtc;
+}
+static Bool get_screen_sizemm(Display *dpy, int screen_idx,
+ int fb_width, int fb_height,
+ int *fb_width_mm, int *fb_height_mm,
+ int *pre_fb_width, int *pre_fb_height) {
+ *pre_fb_width = DisplayWidth (dpy, screen_idx);
+ *pre_fb_height = DisplayHeight (dpy, screen_idx);
+ Bool fb_change;
+ if (fb_width != *pre_fb_width || fb_height != *pre_fb_height ) {
+ float dpi = (25.4 * *pre_fb_height) / DisplayHeightMM(dpy, screen_idx);
+ *fb_width_mm = (25.4 * fb_width) / dpi;
+ *fb_height_mm = (25.4 * fb_height) / dpi;
+ fb_change = True;
+ } else {
+ *fb_width_mm = DisplayWidthMM (dpy, screen_idx);
+ *fb_height_mm = DisplayHeightMM (dpy, screen_idx);
+ fb_change = False;
+ }
+ return fb_change;
+}
+