| /* GdkScreenGraphicsDevice.java -- information about a screen device |
| Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package gnu.java.awt.peer.gtk; |
| |
| import java.awt.DisplayMode; |
| import java.awt.Frame; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.GraphicsDevice; |
| import java.awt.Rectangle; |
| import java.awt.Window; |
| import java.util.ArrayList; |
| |
| class GdkScreenGraphicsDevice extends GraphicsDevice |
| { |
| private final int native_state = GtkGenericPeer.getUniqueInteger (); |
| |
| private Window fullscreenWindow; |
| |
| private boolean oldWindowDecorationState; |
| |
| private Rectangle oldWindowBounds; |
| |
| private Rectangle bounds; |
| |
| private GdkGraphicsConfiguration[] configurations; |
| |
| /** The <code>GdkGraphicsEnvironment</code> instance that created this |
| * <code>GdkScreenGraphicsDevice</code>. This is only needed for native |
| * methods which need to access the 'native_state' field storing a pointer |
| * to a GdkDisplay object. |
| */ |
| GdkGraphicsEnvironment env; |
| |
| /** An identifier that is created by Gdk |
| */ |
| String idString; |
| |
| /** The display modes supported by this <code>GdkScreenGraphicsDevice</code>. |
| * If the array is <code>null</code> <code>nativeGetDisplayModes</code> has |
| * to be called. |
| */ |
| X11DisplayMode[] displayModes; |
| |
| /** The non-changeable display mode of this <code>GdkScreenGraphicsDevice |
| * </code>. This field gets initialized by the {@link #init()} method. If it |
| * is still <code>null</code> afterwards, the XRandR extension is available |
| * and display mode changes are possible. If it is non-null XRandR is not |
| * available, no display mode changes are possible and no other native |
| * method must be called. |
| */ |
| DisplayMode fixedDisplayMode; |
| |
| static |
| { |
| System.loadLibrary("gtkpeer"); |
| |
| initStaticState (); |
| } |
| |
| static native void initStaticState(); |
| |
| GdkScreenGraphicsDevice (GdkGraphicsEnvironment e) |
| { |
| super(); |
| env = e; |
| |
| configurations = new GdkGraphicsConfiguration[1]; |
| configurations[0] = new GdkGraphicsConfiguration(this); |
| } |
| |
| /** This method is called from the native side immediately after |
| * the constructor is run. |
| */ |
| void init() |
| { |
| fixedDisplayMode = nativeGetFixedDisplayMode(env); |
| } |
| |
| /** Depending on the availability of the XRandR extension the method returns |
| * the screens' non-changeable display mode or null, meaning that XRandR can |
| * handle display mode changes. |
| */ |
| native DisplayMode nativeGetFixedDisplayMode(GdkGraphicsEnvironment env); |
| |
| public int getType () |
| { |
| // Gdk manages only raster screens. |
| return GraphicsDevice.TYPE_RASTER_SCREEN; |
| } |
| |
| public String getIDstring () |
| { |
| if (idString == null) |
| idString = nativeGetIDString(); |
| |
| return idString; |
| } |
| |
| private native String nativeGetIDString(); |
| |
| public GraphicsConfiguration[] getConfigurations () |
| { |
| return (GraphicsConfiguration[]) configurations.clone(); |
| } |
| |
| public GraphicsConfiguration getDefaultConfiguration () |
| { |
| return configurations[0]; |
| } |
| |
| |
| /** |
| * Returns the current display mode of this device, or null if unknown. |
| * |
| * @return the current display mode |
| * @see #setDisplayMode(DisplayMode) |
| * @see #getDisplayModes() |
| * @since 1.4 |
| */ |
| public DisplayMode getDisplayMode() |
| { |
| if (fixedDisplayMode != null) |
| return fixedDisplayMode; |
| |
| synchronized (this) |
| { |
| if (displayModes == null) |
| displayModes = nativeGetDisplayModes(env); |
| } |
| |
| int index = nativeGetDisplayModeIndex(env); |
| int rate = nativeGetDisplayModeRate(env); |
| |
| return new DisplayMode(displayModes[index].width, |
| displayModes[index].height, |
| DisplayMode.BIT_DEPTH_MULTI, |
| rate); |
| } |
| |
| native int nativeGetDisplayModeIndex(GdkGraphicsEnvironment env); |
| |
| native int nativeGetDisplayModeRate(GdkGraphicsEnvironment env); |
| |
| public DisplayMode[] getDisplayModes() |
| { |
| if (fixedDisplayMode != null) |
| return new DisplayMode[] { fixedDisplayMode }; |
| |
| synchronized (this) |
| { |
| if (displayModes == null) |
| displayModes = nativeGetDisplayModes(env); |
| } |
| |
| ArrayList list = new ArrayList(); |
| for(int i=0;i<displayModes.length;i++) |
| for(int j=0;j<displayModes[i].rates.length;j++) |
| list.add(new DisplayMode(displayModes[i].width, |
| displayModes[i].height, |
| DisplayMode.BIT_DEPTH_MULTI, |
| displayModes[i].rates[j])); |
| |
| return (DisplayMode[]) list.toArray(new DisplayMode[list.size()]); |
| } |
| |
| native X11DisplayMode[] nativeGetDisplayModes(GdkGraphicsEnvironment env); |
| |
| /** |
| * Real fullscreen exclusive mode is not supported. |
| * |
| * @return <code>false</code> |
| * @since 1.4 |
| */ |
| public boolean isFullScreenSupported() |
| { |
| return true; |
| } |
| |
| public boolean isDisplayChangeSupported() |
| { |
| return fixedDisplayMode == null; |
| } |
| |
| public void setDisplayMode(DisplayMode dm) |
| { |
| if (fixedDisplayMode != null) |
| throw new UnsupportedOperationException("Cannnot change display mode."); |
| |
| if (dm == null) |
| throw new IllegalArgumentException("DisplayMode must not be null."); |
| |
| synchronized (this) |
| { |
| if (displayModes == null) |
| displayModes = nativeGetDisplayModes(env); |
| } |
| |
| for (int i=0; i<displayModes.length; i++) |
| if (displayModes[i].width == dm.getWidth() |
| && displayModes[i].height == dm.getHeight()) |
| { |
| synchronized (this) |
| { |
| nativeSetDisplayMode(env, |
| i, |
| (short) dm.getRefreshRate()); |
| |
| bounds = null; |
| } |
| |
| return; |
| } |
| |
| throw new IllegalArgumentException("Mode not supported by this device."); |
| } |
| |
| native void nativeSetDisplayMode(GdkGraphicsEnvironment env, |
| int index, short rate); |
| |
| /** A class that simply encapsulates the X11 display mode data. |
| */ |
| static class X11DisplayMode |
| { |
| short[] rates; |
| int width; |
| int height; |
| |
| X11DisplayMode(int width, int height, short[] rates) |
| { |
| this.width = width; |
| this.height = height; |
| this.rates = rates; |
| } |
| |
| } |
| |
| public void setFullScreenWindow(Window w) |
| { |
| // Bring old fullscreen window back into its original state. |
| if (fullscreenWindow != null && w != fullscreenWindow) |
| { |
| if (fullscreenWindow instanceof Frame) |
| { |
| // Decoration state can only be switched when the peer is |
| // non-existent. That means we have to dispose the |
| // Frame. |
| Frame f = (Frame) fullscreenWindow; |
| if (oldWindowDecorationState != f.isUndecorated()) |
| { |
| f.dispose(); |
| f.setUndecorated(oldWindowDecorationState); |
| } |
| } |
| |
| fullscreenWindow.setBounds(oldWindowBounds); |
| |
| if (!fullscreenWindow.isVisible()) |
| fullscreenWindow.setVisible(true); |
| } |
| |
| // If applicable remove decoration, then maximize the window and |
| // bring it to the foreground. |
| if (w != null) |
| { |
| if (w instanceof Frame) |
| { |
| Frame f = (Frame) w; |
| oldWindowDecorationState = f.isUndecorated(); |
| if (!oldWindowDecorationState) |
| { |
| f.dispose(); |
| f.setUndecorated(true); |
| } |
| } |
| |
| oldWindowBounds = w.getBounds(); |
| |
| DisplayMode dm = getDisplayMode(); |
| |
| w.setBounds(0, 0, dm.getWidth(), dm.getHeight()); |
| |
| if (!w.isVisible()) |
| w.setVisible(true); |
| |
| w.requestFocus(); |
| w.toFront(); |
| |
| } |
| |
| fullscreenWindow = w; |
| } |
| |
| public Window getFullScreenWindow() |
| { |
| return fullscreenWindow; |
| } |
| |
| Rectangle getBounds() |
| { |
| synchronized(this) |
| { |
| if (bounds == null) |
| bounds = nativeGetBounds(); |
| } |
| |
| return bounds; |
| } |
| |
| native Rectangle nativeGetBounds(); |
| |
| } |