LWJGL 3: GLFW: Fullscreen error, only partial cover? - java

This is a bizarre issue. I have a 4k monitor, and when rendering a fullscreen window with a resolution that is 4k, everything works fine. If that resolution is any smaller, however, it only covers up part of the screen, exposing the rest of the desktop underneath, like this:
The actual resolution switches successfully; the image above is a 1080p screenshot on a 4k monitor, but the "display area" is still undersized. I'm almost positive this is a symptom of the scaling in Windows 10, but I can't even find a scaling setting that fits, default is 300%, shown above, and 100% just makes the area smaller. I also don't have a clue about how to handle it if this was the case.
I'm pretty sure there's just something obvious that I'm not aware of, it's been difficult to find any related issues, and the closest I've come was a GLFW bug reported 2 years ago that isn't even relevant anymore.
EDIT:
I modified the LWJGL example at their website to demonstrate this issue:
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.nio.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
public class Test {
// The window handle
private long window;
public void run() {
System.out.println("Hello LWJGL " + Version.getVersion() + "!");
init();
loop();
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
// Terminate GLFW and free the error callback
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");
// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
// Create the window
window = glfwCreateWindow(1600, 900, "Hello World!", glfwGetPrimaryMonitor(), NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
});
// Get the thread stack and push a new frame
try ( MemoryStack stack = stackPush() ) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center the window
glfwSetWindowPos(
window,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
} // the stack frame is popped automatically
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
}
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( !glfwWindowShouldClose(window) ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
public static void main(String[] args) {
new Test().run();
}
}
Notice window = glfwCreateWindow(1600, 900, "Hello World!", glfwGetPrimaryMonitor(), NULL);. By specifying a monitor, you are requesting fullscreen mode in GLFW, and it finds the closest compatible resolution to the size arguments given based on hardware i suppose, but my monitor is a 4K monitor, and unless I specify 4096 x 2160, I get the same bizarre result. Any Idea what I'm doing wrong?

Related

java.lang.NoClassDefFoundError in LWJGL when attempting to run in Eclipse

So I'm a moderately novice programmer, but after toiling over this error for a while, I can't find a solution. I'm making a puzzle game, and for some reason, it just refuses to run now. I always get this error:
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.lwjgl.system.Library
at org.lwjgl.system.MemoryAccess.<clinit>(MemoryAccess.java:22)
at org.lwjgl.system.Pointer.<clinit>(Pointer.java:24)
at org.lwjgl.glfw.GLFW.<clinit>(GLFW.java:594)
at Graphics.LaunchWindow.run(LaunchWindow.java:32)
at Graphics.LaunchWindow.main(LaunchWindow.java:96)
Eclipse tells me that none of my code has errors within it, and reinstalling LWJGL doesn't work (I tried both the stable 3.0.0b build 64 and the nightly 3.0.0 build 22). I have seen other similar questions taking about making sure the lwjgl.jar is in the class path, but I've made sure multiple times. Also, if it matters, I have lwjgl_util.jar and slick_util.jar in the class path as well, and even though they are outdated compared to lwjgl 3, removing them from the class path makes no difference.
package Graphics;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import Controls.KeyParser;
import Controls.KeyboardInput;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
public class LaunchWindow {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
public int width = 1024;
public int height = 600;
public String title = "Duplicity";
public long fullscreen = NULL;
public long window;
public void run() {
try {
init();
loop();
glfwDestroyWindow(window);
keyCallback.release();
} finally {
glfwTerminate();
errorCallback.release();
}
}
private void init() {
glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err));
KeyboardInput.initiate();
if ( glfwInit() != GLFW_TRUE )
throw new IllegalStateException("Unable to initialize GLFW");
if(fullscreen == NULL){
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
}
window = glfwCreateWindow(width, height, title, fullscreen, NULL);
if (window == NULL)
throw new RuntimeException("Failed to create the GLFW window");
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
});
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
keyCallback = GLFWKeyCallback.create(KeyboardInput::glfw_key_callback);
keyCallback.set(window);
/* mouseButtonCallback = GLFWMouseButtonCallback.create(Mouse::glfw_mouse_button_callback);
mouseButtonCallback.set(window);
cursorPosCallback = GLFWCursorPosCallback.create(Mouse::glfw_cursor_pos_callback);
cursorPosCallback.set(window); */
GL.createCapabilities();
}
public void loop() {
GL.createCapabilities();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
while ( glfwWindowShouldClose(window) == GLFW_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
new KeyParser().checkKeyState();
}
}
public static void main(String[] args) {
new LaunchWindow().run();
}
}
Incorrect system library path can be one reason for this error, but this can also be caused by system library incompatibility (on Linux). Code included in LWJGL 3 requires GLIBC version 2.14 or higher. If your system (e.g. Linux) is older (like Debian Wheezy, for example), your GLIBC version will be older than the required one.
If that's the case you'll need to install a newer GLIBC version, or upgrade your system (e.g. to Debian Jessie).
HTH,
M

LWJGL 3: window doesn't show up

I downloaded LWJGL 3 today, and found out that it was almost completly rewritten. I looked up a tutorial on how to create a window, but I still have problems creating a window.
The code runs without problems: no errors in the console, but the window isn't displayed!
I hope you can help me, I searched a lot for LWJGL 3 tutorials, but they seem pretty old, so I decided to ask my question here.
Here's my code:
//EDIT: Changed my code so everything runs in one thread but it still doesn' t work. Even System.out.println() doesn't work. No console output is displayed!
//IMPORTANT: I just realized that this may be a bug in GLFW (I'm working on Linux) !
package net.newworld.test;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFWVidMode;
public class Main {
private static long window;
private static int width = 1280;
private static int height = 800;
private static void init() {
glfwInit();
System.out.println("Initializing LWJGL...");
System.out.println("LWJGL Version: "+ Version.getVersion());
glfwWindowHint(GLFW_VISIBLE, GL_FALSE); //Set window visible after creation
window = glfwCreateWindow(width, height, "New World", 0, 0);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); //Get primary monitor
glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2); //Set window position
glfwMakeContextCurrent(window); //Make OpenGL contect current
glfwShowWindow(window); //Show window
}
public static void main(String[] args) {
init();
}
}
The problem might be that you forgot to add the window proc loop (which is blocking)
public static void main(String[] args) {
init();
while (!glfwWindowShouldClose(window)) {
glfwWaitEvents();
}
}

Failure to load lwjgl

I finished setting up lwjgl and tried to run the example from the website, but then, I keep getting this error (I changed the name of the class):
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to load the native library: lwjgl32
at org.lwjgl.LWJGLUtil.loadLibrarySystem(LWJGLUtil.java:338)
at org.lwjgl.Sys$1.run(Sys.java:36)
at java.security.AccessController.doPrivileged(Native Method)
at org.lwjgl.Sys.<clinit>(Sys.java:33)
at mehavenowebsite.DoStuff.run(DoStuff.java:24)
at mehavenowebsite.DoStuff.main(DoStuff.java:114)
I set up lwjgl correctly, and I added the natives, so I have no idea what's going on. I am using eclipse luna, with lwjgl 3. Does anyone know what's going on? Thanks.
EDIT: code:
package mehavenowebsite;
import org.lwjgl.Sys;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import java.nio.ByteBuffer;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
public class DoStuff {
// We need to strongly reference callback instances.
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
// The window handle
private long window;
public void run() {
System.out.println("Hello LWJGL " + Sys.getVersion() + "!");
try {
init();
loop();
// Release window and window callbacks
glfwDestroyWindow(window);
keyCallback.release();
} finally {
// Terminate GLFW and release the GLFWerrorfun
glfwTerminate();
errorCallback.release();
}
}
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err));
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( glfwInit() != GL11.GL_TRUE )
throw new IllegalStateException("Unable to initialize GLFW");
// Configure our window
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable
int WIDTH = 300;
int HEIGHT = 300;
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop
}
});
// Get the resolution of the primary monitor
ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
window,
(GLFWvidmode.width(vidmode) - WIDTH) / 2,
(GLFWvidmode.height(vidmode) - HEIGHT) / 2
);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
}
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the ContextCapabilities instance and makes the OpenGL
// bindings available for use.
GLContext.createFromCurrent();
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
public static void main(String[] args) {
new DoStuff().run();
}
}
Did you add the library the "Eclipse way"?
Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7

JOGL creating window using NEWT - examples?

I have been looking at using JOGL to create some things and have been looking through what documentation I can find.
Brief tutorials they all mention how using the JOGL version of canvas can have performance issues and instead you should use NEWT. However each and every tutorial / FAQ then goes on to use the canvas! Or simply specify a few tiny snippets of methods to create a window using NEWT but which (on my machine at least) I cannot get to correctly run.
Does anyone have a good source of examples of how to correctly implement creating and rendering to a window in JOGL using the NEWT method? I'm not even sure how it functions compared to the Canvas so an explanation of the differences between the two and a typical layout of methods to create / manage / render to a window would be ideal.
Just a little lost and cannot find anything useful. Hope someone's come across something before!
This tutorial helped me a lot, see chapter 3.9 - Yet Another Tutorial on JOGL.
Also documentation is useful. Take a look at the attached example, please.
JOGL2NewtDemo.java
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.FPSAnimator;
/**
* A program that draws with JOGL in a NEWT GLWindow.
*
*/
public class JOGL2NewtDemo {
private static String TITLE = "JOGL 2 with NEWT"; // window's title
private static final int WINDOW_WIDTH = 640; // width of the drawable
private static final int WINDOW_HEIGHT = 480; // height of the drawable
private static final int FPS = 60; // animator's target frames per second
static {
GLProfile.initSingleton(); // The method allows JOGL to prepare some Linux-specific locking optimizations
}
/**
* The entry main() method.
*/
public static void main(String[] args) {
// Get the default OpenGL profile, reflecting the best for your running platform
GLProfile glp = GLProfile.getDefault();
// Specifies a set of OpenGL capabilities, based on your profile.
GLCapabilities caps = new GLCapabilities(glp);
// Create the OpenGL rendering canvas
GLWindow window = GLWindow.create(caps);
// Create a animator that drives canvas' display() at the specified FPS.
final FPSAnimator animator = new FPSAnimator(window, FPS, true);
window.addWindowListener(new WindowAdapter() {
#Override
public void windowDestroyNotify(WindowEvent arg0) {
// Use a dedicate thread to run the stop() to ensure that the
// animator stops before program exits.
new Thread() {
#Override
public void run() {
if (animator.isStarted())
animator.stop(); // stop the animator loop
System.exit(0);
}
}.start();
}
});
window.addGLEventListener(new JOGL2Renderer());
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setTitle(TITLE);
window.setVisible(true);
animator.start(); // start the animator loop
}
}
JOGL2Renderer.java
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
/**
* Class handles the OpenGL events to render graphics.
*
*/
public class JOGL2Renderer implements GLEventListener {
private double theta = 0.0f; // rotational angle
/**
* Called back by the drawable to render OpenGL graphics
*/
#Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2(); // get the OpenGL graphics context
gl.glClear(GL.GL_COLOR_BUFFER_BIT); // clear background
gl.glLoadIdentity(); // reset the model-view matrix
// Rendering code - draw a triangle
float sine = (float)Math.sin(theta);
float cosine = (float)Math.cos(theta);
gl.glBegin(GL.GL_TRIANGLES);
gl.glColor3f(1, 0, 0);
gl.glVertex2d(-cosine, -cosine);
gl.glColor3f(0, 1, 0);
gl.glVertex2d(0, cosine);
gl.glColor3f(0, 0, 1);
gl.glVertex2d(sine, -sine);
gl.glEnd();
update();
}
/**
* Update the rotation angle after each frame refresh
*/
private void update() {
theta += 0.01;
}
/*... Other methods leave blank ...*/
}
take a look at JOGL's junit tests, they cover large parts of the NEWT API.

how to obtain mouse click coordinates outside my window in Java

I need to implement a class, using Swing, which can obtain the mouse coordinates when the user clicks anywhere on the screen. if I wanted to obtain the mouse coordinates inside my own window, I'd use a MouseListener, but I want it to work even when the user clicks outside my program.
I want my class to behave just like KColorChooser: the user clicks on the drop button and he can click anywhere on the screen to obtain the color of that spot. but I don't know if that's possible using pure Java.
It is possible though limited:
Add an AWTEventListener for focus events. As long as your app has focus before the button is clicked you'll receive a focus lost event. Then query for the pointer position.
The limitation is that, of course, your app loses focus. So depending on what you are ultimately trying to achieve this might not be useful.
If you don't want to lose focus then you will have to temporarily take a screenshot of the whole screen and display that in a screen filling window which listens for a mouse click as usual.
Proof of first method:
import java.awt.AWTEvent;
import java.awt.MouseInfo;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import javax.swing.JFrame;
public class Application1 {
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(
new Listener(), AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static class Listener implements AWTEventListener {
public void eventDispatched(AWTEvent event) {
System.out.print(MouseInfo.getPointerInfo().getLocation() + " | ");
System.out.println(event);
}
}
}
Clicking outside of the app produced:
java.awt.Point[x=198,y=59] | java.awt.event.MouseEvent[MOUSE_EXITED, ...
java.awt.Point[x=976,y=503] | java.awt.FocusEvent[FOCUS_LOST, ...
The second point is outside of the app.
Forget about GlassPane, there's another 100% native Java way to do it that works both on OS X and on Windows.
Java has always supported translucency for its windows on OS X and Java now supports translucency for its windows on Windows too (since Java 1.6.0_10 or so, needs to be checked).
So the trick is: upon clicking on the "pick a color" tool, you create a nearly transparent borderless Java window covering the entire screen. You set its alpha to 10 (alpha goes from 0 to 255). That alpha is so low the user won't notice that there's a very thin "nearly transparent but only very very very translucent" borderless window covering the entire screen.
Now when the user clicks on your "alpha set to 10 translucent borderless window" covering the entire screen, you get your (x,y).
Discard the borderless Java window.
Use Robot's getRgb(x,y) and you're done.
Why set the alpha to 10 and not 0? Because otherwise clicks aren't intercepted by Java but go directly to the OS (at least that's how it works for a fact on OS X). There's a treshold and I know it's not set at '1', nor '2', it's around 10 or so.
EDIT I just realized you know need to pick several colors, this is trickier but can still be done using 100% Java. Either you can live with "slightly off" colors (affected by the "nearly transparent" 'invisible' layer) or upon getting a click you must remove the layer, get the correct pixel color, and put again a "nearly transparent" layer. Now of course that is one heck of a hack but it can be done in 100% Java.
Use
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
PointerInfo inf = MouseInfo.getPointerInfo();
Point p = inf.getLocation();
p.x and p.y will give you co-ordinates outside your window.
I don't know if that's possible using
pure Java.
Its not possible using pure Java, since Java is only aware of MouseEvents on Windows belonging to Java.
These events are directed to the window which has the focus, from all events on the desktop you can only get the mouse position.
As already shown by Keilly it's only possible to get the mouse postion.
You need to include a native lib
I haven't tried this myself, but maybe you could create a full-screen, transparent panel/frame/etc, and add a MouseListener to that.
It is possible with a little trick. Should be 100% cross-platform (tested on Linux & Windows). Basically, you create a small JWindow, make it "alwaysOnTop" and move it around with the mouse using a timer.
For details, see my answer here.
The location (x,y) and the time interval
(d) between each click is supplied thru command line arguments. Here is the
program
import java.awt.* ;
import java.util.* ;
public final class ClickMouse extends TimerTask {
public static int x, y, d ;
public static void main(String[] args) {
TimerTask clikMouse = new ClickMouse();
Timer t = new Timer();
/*
x = Integer.parseInt(args[0]) ;
y = Integer.parseInt(args[1]) ;
d = Integer.parseInt(ares[2]) ;
*/
x = 500;
y = 200;
d = 5;
t.schedule(clikMouse,1000,d*1000);
}
public void run() {
try
{
Robot bot = new Robot();
bot.mouseMove(x,y);
bot.mousePress(java.awt.event.InputEvent.BUTTON1_MASK );
bot.mouseRelease(java.awt.event.InputEvent.BUTTON1_MASK);
}
catch (Exception e)
{
System.out.println("Exception occured :" + e.getMessage());
}
}
}
https://github.com/kwhat/jnativehook JNativeHook: Global keyboard and mouse listeners for Java.
I don't have enough rep yet to leave comments, but here are my comments on the other techniques:
Use a native lib: will work, but has obvious distribution limitations
Use GlassPane to fill entire screen: GlassPanes must be contained within a Window.
Create a Window containing a picture of the desktop and fill the entire screen: Will work, but it will suddenly make the desktop static. The cursor will no longer change, any animations or video in other windows or desktop will become eerily static.
Alternative solution:
A refinement of the screen filling window, if you are using Java 6u10 or later is to make the window completely transparent. Put this window in front of all others and listen for mouse clicks. It still has shortcomings, such as no cursor changes, but it depends on what you want to do.
Based on SyntaxT3rr0r's answer I created a sample color picker in groovy which shows how it can work.
import java.awt.*
import java.awt.datatransfer.*
//import com.sun.awt.AWTUtilities;
import javax.swing.WindowConstants as WC;
import javax.swing.SwingConstants as SWC
import groovy.swing.SwingBuilder
class ColorPicker {
SwingBuilder swb = new SwingBuilder()
def window;
def overlayWindow
def mainPanel;
def mainLabel;
def menu;
def transparent = new Color(0, 0, 0, 0);
def nearlyTransparent = new Color(0, 0, 0, 26);
Color color = new Color(150, 150, 255);
def colorHex = { col ->
col = col?: color;
"#"+Integer.toHexString(col.getRGB())[2..-1]
}
def getTextColor = { baseColor ->
baseColor = baseColor?: color;
(baseColor.red*1.5 + baseColor.green*1.5 + baseColor.blue > 400) ? Color.BLACK : Color.WHITE;
}
def setDisplayColor = {newColor ->
mainPanel.background = newColor
mainLabel.foreground = getTextColor(newColor)
mainLabel.text = colorHex(newColor)
}
def show(){
menu = swb.popupMenu { // invoker: mainPanel
menuItem(text: "Pick Color", actionPerformed: capturePixelColor)
menuItem(text: "Copy to Clipboard", actionPerformed: {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new StringSelection(colorHex()), null);
})
separator()
menuItem(text: "Close", actionPerformed: {dispose()})
}
window = swb.frame(
title: "Color Picker",
location:[50,50],
size:[60, 60],
resizable: false,
undecorated: true,
alwaysOnTop: true,
defaultCloseOperation:WC.EXIT_ON_CLOSE
){
def textColor = getTextColor()
mainPanel = panel( constraints: BorderLayout.CENTER,
border: lineBorder(color: Color.BLACK),
componentPopupMenu: menu){
borderLayout()
mainLabel = label(text: "--",
constraints: BorderLayout.CENTER,
horizontalAlignment: SWC.CENTER)
}
}
setDisplayColor(color);
window.show();
}
def capturePixelColor = {
def screenSize = Toolkit.getDefaultToolkit().screenSize
overlayWindow = swb.frame(
location:[0,0],
size: screenSize,
resizable: false,
undecorated: true,
alwaysOnTop: true,
defaultCloseOperation:WC.DISPOSE_ON_CLOSE,
show: true,
background: nearlyTransparent, // AWTUtilities.setWindowOpacity(overlayWindow, 0.1f);
cursor: Cursor.CROSSHAIR_CURSOR,
mouseClicked: {event ->
int x = event.getXOnScreen() // or maybe getX() is enough
int y = event.getYOnScreen()
overlayWindow.dispose()
overlayWindow = null
color = new Robot().getPixelColor(x, y)
setDisplayColor(color)
}
)
}
public static void main(String...args){
println "Welcome to ColorPicker"
def picker = new ColorPicker()
picker.show()
}
}
Look, I understand I am 7 years late...
This is a re-make of Keilly's answer, which allows to get when the mouse button is clicked, anywhere. The main problem is that fullscreen games are always unfocused, and it becomes annoying to handle.
Here is the code:
import java.awt.AWTEvent;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import javax.swing.JFrame;
public class Main {
public static JFrame frame = new JFrame();
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(
new Listener(), AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setLocation(1, 1);
}
private static class Listener implements AWTEventListener {
public void eventDispatched(AWTEvent event) {
// We do not want the event to show twice,
// as it shows for focusing and unfocusing
if(event.getID() == 1004) {
Point p = MouseInfo.getPointerInfo().getLocation();
System.out.println("Mouse Clicked at " + p.x + ", " + p.y);
}
// The frame was just unfocused! To make
// sure we get the next mouse click, we
// need to focus it again!
frame.setVisible(true);
}
}
}

Categories