I was looking for a way to properly choose the monitor I want to fullscreen on based on the position of the window prior to fullscreening.
I looked online for ages but couldn't find anything so I ended up trying a bunch of things until I got something working.
I figured someone eventually will try to look this problem up and I might as well share my solution.
What I ended up doing is get the virtual screen coordinates of the center of the window using LWJGL2's Display class like so:
int x = Display.getX() + Display.getWidth()/2,
y = Display.getY() + Display.getHeight()/2;
I then used AWT to get all available monitors:
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()
I iterated through them and got their virtual bounds(and applied any DPI scaling they might have):
Rectangle bounds = screenDevice.getDefaultConfiguration().getDefaultTransform().createTransformedShape(screenDevice.getDefaultConfiguration().getBounds()).getBounds();
EDIT: Slightly altered line so it can support Windows' DPI scaling properly.
If the bounds contained the center of the window, it means that most of the window is probably within that monitor:
if(bounds.contains(x,y))
return bounds; //getMonitorFromWindow()
Then to toggle between windowed borderless fullscreen and normal windowed in LibGDX I did the following:
// config is the LwjglApplicationConfiguration of the application
// upon changing using alt+enter
if(fullscreen) {
config.resizable = false;
Gdx.graphics.setUndecorated(true);
Rectangle monitor = getMonitorFromWindow();
// set to full screen in current monitor
Gdx.graphics.setWindowedMode(monitor.width, monitor.height);
Display.setLocation(monitor.x, monitor.y);
} else {
config.resizable = true;
Gdx.graphics.setUndecorated(false);
Rectangle monitor = getMonitorFromWindow();
// set to windowed centered in current monitor
Gdx.graphics.setWindowedMode((int) (monitor.width * 0.8f), (int) (monitor.height * 0.8f));
Display.setLocation(monitor.x + (int) (monitor.width * 0.1f), monitor.y + (int) (monitor.height * 0.1f));
}
I hope someone would find this useful.
I’m building a program and I’m stuck at picking a random image that already is defined in the program.
Here’s the code:
Image Opic = new Image(getClass().getResourceAsStream("Resource/O1.png"));
Image Xpic = new Image(getClass().getResourceAsStream("Resource/X1.png"));
Image PlayerPic = new Random[Opic,Xpic];
Image AiPic = new Random[Opic,Xpic];
Image Opic = new Image(getClass().getResourceAsStream("Resource/O1.png"));
Image Xpic = new Image(getClass().getResourceAsStream("Resource/X1.png"));
Image PlayerPic = Math.random() > 0.5 ? Opic : Xpic;
Not sure what language you are actually coding in, since it does not look like javascript (well not Java either) to me. But this is just a demonstration in Java on how this problem can be approach. You can almost for sure be able to find similar method in any language.
Is it possible to take a screen capture of a specific application/exe launched on Windows in Java?
I tried this code but it does not take a capture of the application itself and return a black picture:
try {
...
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage bufferedImage = robot.createScreenCapture(captureSize);
ImageIO.write(bufferedImage,"png",myFile);
...
} catch(AWTException e) {
System.err.println("call a doc!");
}
This is why I think that forcing a screenshot linked with the process launched may solve the problem.
Or maybe they are other ways to take a capture of the displayed screen? (if yes could you please show me some working code?)
I have a fullscreen java app that will run on an 8 monitor digital signage type display on a Windows 7 machine. I need to be able to display content on specific physical monitors. Ideally I would like the displays ordered 1-8 in Display Properties -> Settings, however many attempts of unplugging/plugging in and reordering have failed to get the physical monitors to appear in any deterministic order via the Display Properties->Settings. I can reorder them fine, but when my java program retrieves information on the displays it is not in the layout/order that windows has them configured.
GraphicsEnvironment ID returns Strings such as Device0 and Device1, but these do not match the Windows Display numbering as seen in the Display properties. For instance if the layout is 7,4,1,2,3,4,5,6 I still get back Device0, Device1... in which Device0 corresponds to identified screen 1 (not 7 which is the first screen on the left). Is there a way to query the OS to determine what layout the displays are in and/or some other technique to display fullscreen on a specific physical monitor?
You can get the bounds of the screens relative to the big virtual desktop:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
for (GraphicsDevice gd : ge.getScreenDevices()) {
Rectangle bounds = gd.getDefaultConfiguration().getBounds();
System.out.println(bounds.toString());
}
for my setup this gives:
java.awt.Rectangle[x=0,y=0,width=1280,height=1024]
java.awt.Rectangle[x=1280,y=304,width=1280,height=720]
You can use this information to determine their order. E.g. if you are absolutely sure that your monitors are in a nice grid you can go fullscreen on the upper right monitor like this:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gdUpperRight = null;
Rectangle bUpperRight = null;
for (GraphicsDevice gd : ge.getScreenDevices()) {
Rectangle b = gd.getDefaultConfiguration().getBounds();
if (bUpperRight == null || b.x > bUpperRight.x || b.y > bUpperRight.y) {
bUpperRight = b;
gdUpperRight = gd;
}
}
gdUpperRight.setFullScreenWindow(myFrame);
When I run my swing GUI applications under Java 6, they automatically use my configured sub-pixel anti-alias settings for all fonts. The result is much improved over standard AA options.
But when I paint to an image I can find no way to initialize the graphics context to use the system's AA configuration. Trying to play around with Java's different AA hints is a lost cause because no sub-pixel method will work for all users.
Is there any way to inherit system AA settings for a given graphics context instead of having to pick one and explicitly set the hint? At the moment I have to use GASP AA to avoid the horrible results that standard AA gives with small fonts. I have tried not setting anything for text AA, and not setting any AA hints at all.
Update 2010-01-05
I think I have pinned this down; the subpixel AA hints appear to only be respected when painting directly to the AWT graphics context; when I paint to a double-buffer image it just does standard AA; but when I bypass the double-buffer image the subpixel AA is done.
Otherwise The_Fire's answer would work in JVMs which have Swing available (but not J2ME JVMs); Note that The_Fire's answer does not work using an AWT component (using new Label() instead of new JLabel() fails), presumably because the FontRenderContext cannot be extracted until the component is realized to the display.
My current code to get the graphics context for my target image currently looks like this:
try {
if((dbImage=dctRoot.createImage(wid,hgt,1))!=null) { // if createImage returns null or throws an exception the component is not yet displayable
dbGraphics=(Graphics2D)dbImage.getGraphics();
if(dctRoot.properties.getBoolean("Antialias",true)) {
try {
// set AA on overall
dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING ,RenderingHints.VALUE_ANTIALIAS_ON);
// set text AA to platform/impl default
dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
// try to override platform/impl AA with font-specified AA (Java 6+)
try { dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); } catch(Throwable thr) {;} // yes, ignore exception
}
catch(Throwable thr) {
dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+").");
dctRoot.setProperty("Antialias","False"); // turn off AA for subsequent painting
}
}
}
}
catch(Throwable thr) {
dbImage=null;
dbGraphics=null;
}
The code to create the image uses an underlying AWT component, which forms the backdrop on which I do all my painting - the component is a Panel, because I need to be able to do a setFocusCycleRoot so it plays well with other AWT components. The create image code follows:
public DctImage createImage(int wid, int hgt, float accpty) {
GraphicsConfiguration cfg=awtComponent.getGraphicsConfiguration();
Image img=null;
if(transparentImages) {
//y { img=new BufferedImage(wid,hgt,BufferedImage.TYPE_INT_ARGB); } // NB: J2ME CDC/PP 1.1 does not have the BufferedImage constructors (one day I may discover a way to create a BufferedImage via another API!!)
try { img=cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT); }// NB: J2ME CDC/PP 1.1 does not have this API, but prefer to use GraphicsConfiguration over new BufferImage(...)
catch(NoClassDefFoundError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
catch(NoSuchMethodError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
catch(NoSuchFieldError thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
}
else {
img=cfg.createCompatibleImage(wid,hgt);
}
if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); } catch(Throwable thr) {;}
}
return (img==null ? null : new DctImage(img));
}
I found there were a few factors going on here.
First, the image needs to be created from the underlying AWT component, and it must be created without transparency:
cfg.createCompatibleImage(wid,hgt);
instead of
cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT);
Second, for some inexplicable reason, the primary AA setting, KEY_ANTIALIASING, must be off to use LCD subpixel AA.
Lastly, and most importantly, the desktop font rendering hints are easily retrieved using:
java.awt.Toolkit.getDesktopProperty("awt.font.desktophints")
Update 2010-01-05
Retesting in Java 6.26, it seems like the problem with needing to set general AA off to render text AA has finally been resolved (way to go Oracle... after Sun was just a few years decade too late).
Using Swing, I'm able to get the right text anti-aliasing hint like this:
JLabel label = new JLabel();
FontMetrics fm = label.getFontMetrics( label.getFont() );
Object aaHintValue = fm.getFontRenderContext().getAntiAliasingHint();
On my system this returns RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB.
java.awt.Toolkit.getDesktopProperty("awt.font.desktophints") appears to be null on linux, at least without any special vm command line options, presumably because it's unable to figure out what the platform defaults are.. adding e.g "-Dawt.useSystemAAFontSettings=lcd" seems to cure it and enables subpixel rendering if you set the hints on your Graphics2D instance.
Wait, are you running this code on a Windows JVM? I thought ClearType was a Microsoft technology that Swing inherits through some native code (ie, not available on Linux or other non Microsoft platforms).
I once wrote a servlet that generated JPGs with anti aliased fonts that ran on Debian, and this was the code I used
Font font = new Font("Komix", Font.PLAIN, 8);
Graphics2D g2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext frc = g2.getFontRenderContext();
g2.setFont(font);
g2.setPaint(Color.black);
g2.drawString(sMessage, xOffset, yOffset);
Offhand I can't recall if any of this code relies on Swing (I imported javax.swing and the servlet is about 300 lines long, so I may have thought I needed it for something else), a quick check on Google looks like this is squarely in the AWT space. Hope that helps.