com.sun.glass.ui.monocle.X11Screen Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.glass.ui.monocle;
import com.sun.glass.ui.Pixels;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
/** Native screen implementation for the X11 platform
*
*/
class X11Screen implements NativeScreen {
private int depth;
private int nativeFormat;
private int width;
private int height;
private long nativeHandle;
private long display;
private static X xLib = X.getX();
/** Create the screen. If showCursor is true, set the corresponding X11
* window attribute.
* @param showCursor
*/
X11Screen(boolean showCursor) {
// Since we will be accessing X from multiple threads, we need to call
// XInitThreads before we do anything else. Then, lock the X display
// until we are done doing our setup
xLib.XInitThreads();
display = xLib.XOpenDisplay(null);
xLib.XLockDisplay(display);
if (display == 0l) {
throw new NullPointerException("Cannot open X11 display");
}
long screen = xLib.DefaultScreenOfDisplay(display);
X.XSetWindowAttributes attrs = new X.XSetWindowAttributes();
attrs.setEventMask(attrs.p,
X.ButtonPressMask | X.ButtonReleaseMask
| X.PointerMotionMask);
long cwMask = X.CWEventMask;
if (!showCursor) {
cwMask |= X.CWCursorMask;
attrs.setCursor(attrs.p, X.None);
}
int x = 0;
int y = 0;
int w = xLib.WidthOfScreen(screen);
int h = xLib.HeightOfScreen(screen);
boolean fullScreen = true;
@SuppressWarnings("removal")
String geometry =
AccessController.doPrivileged((PrivilegedAction) () ->
System.getProperty("x11.geometry"));
if (geometry != null) {
try {
String size;
if (geometry.contains(",")) {
// use the first two numbers for x and y
String location;
int i = geometry.indexOf("+");
if (i >= 0) {
location = geometry.substring(0, i);
size = geometry.substring(i + 1);
} else {
location = geometry;
size = "";
}
i = location.indexOf(",");
x = Integer.parseInt(location.substring(0, i));
y = Integer.parseInt(location.substring(i + 1));
fullScreen = false;
} else {
size = geometry;
}
if (size.length() > 0) {
int i = size.indexOf("x");
w = Integer.parseInt(size.substring(0, i));
h = Integer.parseInt(size.substring(i + 1));
fullScreen = false;
}
} catch (NumberFormatException e) {
System.err.println("Cannot parse geometry string: '"
+ geometry + "'");
}
}
if (fullScreen) {
X.XSetWindowAttributes.setOverrideRedirect(attrs.p, true);
cwMask |= X.CWOverrideRedirect;
}
long window = xLib.XCreateWindow(
display,
xLib.RootWindowOfScreen(screen),
x, y, w, h,
0, // border width
X.CopyFromParent, // depth
X.InputOutput, // class
X.CopyFromParent, // visual
cwMask,
attrs.p);
xLib.XMapWindow(display, window);
if (fullScreen) {
X.XClientMessageEvent event = new X.XClientMessageEvent(
new X.XEvent());
X.XEvent.setWindow(event.p, window);
X.XClientMessageEvent.setMessageType(event.p,
xLib.XInternAtom(display,
"_NET_WM_STATE",
false)
);
X.XClientMessageEvent.setFormat(event.p, 32);
X.XClientMessageEvent.setDataLong(event.p, 0, X._NET_WM_STATE_ADD);
X.XClientMessageEvent.setDataLong(event.p, 1,
xLib.XInternAtom(display,
"_NET_WM_STATE_FULLSCREEN",
false)
);
X.XClientMessageEvent.setDataLong(event.p, 2, 0);
xLib.XSendEvent(display, xLib.RootWindowOfScreen(screen),
false,
X.SubstructureRedirectMask | X.SubstructureNotifyMask,
event.p);
xLib.XGrabKeyboard(display, window, true,
X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime);
}
xLib.XStoreName(display, window, "JavaFX framebuffer container");
xLib.XSync(display, false);
int[] widthA = new int[1];
int[] heightA = new int[1];
int[] depthA = new int[1];
xLib.XGetGeometry(display, window, null, null, null, widthA,
heightA, null, depthA);
xLib.XUnlockDisplay(display);
width = widthA[0];
height = heightA[0];
depth = depthA[0];
nativeFormat = Pixels.Format.BYTE_BGRA_PRE;
nativeHandle = window;
}
@Override
public int getDepth() {
return depth;
}
@Override
public int getNativeFormat() {
return nativeFormat;
}
@Override
public int getWidth() {
return width;
}
@Override
public int getHeight() {
return height;
}
@Override
public float getScale() {
return 1.0f;
}
@Override
public long getNativeHandle() {
return nativeHandle;
}
@Override
public int getDPI() {
return 96;
}
@Override
public void shutdown() {
}
long getDisplay() {
return display;
}
@Override
public void uploadPixels(Buffer b,
int x, int y, int width, int height,
float alpha) {
// TODO: upload pixels to X11 window
}
@Override
public void swapBuffers() {
}
@Override
public ByteBuffer getScreenCapture() {
return null;
}
}