class Exception extends java.lang.Exception {
        public Exception(String message) { super(message); }
        public Exception(String message, Throwable cause) { super(message, cause); }
    }

    public static String[] getScreenDescriptions() {
        GraphicsDevice[] screens = getScreenDevices();
        String[] descriptions = new String[screens.length];
        for (int i = 0; i < screens.length; i++) {
            descriptions[i] = screens[i].getIDstring();
        }
        return descriptions;
    }
    public static DisplayMode getDisplayMode(int screenNumber) {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= 0 && screenNumber < screens.length) {
            return screens[screenNumber].getDisplayMode();
        } else {
            return null;
        }
    }
    public static double getGamma(int screenNumber) {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= 0 && screenNumber < screens.length) {
            return getGamma(screens[screenNumber]);
        } else {
            return 0.0;
        }
    }
    public static double getDefaultGamma() {
        return getGamma(getDefaultScreenDevice());
    }

    public static double getGamma(GraphicsDevice screen) {
        ColorSpace cs = screen.getDefaultConfiguration().getColorModel().getColorSpace();
        if (cs.isCS_sRGB()) {
            return 2.2;
        } else {
            try {
                return ((ICC_ProfileRGB)((ICC_ColorSpace)cs).getProfile()).getGamma(0);
            } catch (RuntimeException e) { }
        }
        return 0.0;
    }
    public static GraphicsDevice getScreenDevice(int screenNumber) throws Exception {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= screens.length) {
            throw new Exception("CanvasFrame Error: Screen number " + screenNumber + " not found. " +
                                "There are only " + screens.length + " screens.");
        }
        return screens[screenNumber];//.getDefaultConfiguration();
    }
    public static GraphicsDevice[] getScreenDevices() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
    }
    public static GraphicsDevice getDefaultScreenDevice() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    }

    public CanvasFrame(String title) {
        this(title, 0.0);
    }
    public CanvasFrame(String title, double gamma) {
        super(title);
        init(false, null, gamma);
    }

    public CanvasFrame(String title, GraphicsConfiguration gc) {
        this(title, gc, 0.0);
    }
    public CanvasFrame(String title, GraphicsConfiguration gc, double gamma) {
        super(title, gc);
        init(false, null, gamma);
    }

    public CanvasFrame(String title, int screenNumber, DisplayMode displayMode) throws Exception {
        this(title, screenNumber, displayMode, 0.0);
    }
    public CanvasFrame(String title, int screenNumber, DisplayMode displayMode, double gamma) throws Exception {
        super(title, getScreenDevice(screenNumber).getDefaultConfiguration());
        init(true, displayMode, gamma);
    }

    private void init(final boolean fullScreen, final DisplayMode displayMode, final double gamma) {
        Runnable r = new Runnable() { public void run() {<FILL_FUNCTION_BODY>

            KeyboardFocusManager.getCurrentKeyboardFocusManager().
                    addKeyEventDispatcher(keyEventDispatch);

            GraphicsDevice gd = getGraphicsConfiguration().getDevice();
            DisplayMode d = gd.getDisplayMode(), d2 = null;
            if (displayMode != null && d != null) {
                int w = displayMode.getWidth();
                int h = displayMode.getHeight();
                int b = displayMode.getBitDepth();
                int r = displayMode.getRefreshRate();
                d2 = new DisplayMode(w > 0 ? w : d.getWidth(),    h > 0 ? h : d.getHeight(),
                                     b > 0 ? b : d.getBitDepth(), r > 0 ? r : d.getRefreshRate());
            }
            if (fullScreen) {
                setUndecorated(true);
                getRootPane().setWindowDecorationStyle(JRootPane.NONE);
                setResizable(false);
                gd.setFullScreenWindow(CanvasFrame.this);
            } else {
                setLocationByPlatform(true);
            }
            if (d2 != null && !d2.equals(d)) {
                gd.setDisplayMode(d2);
            }
            double g = gamma == 0.0 ? getGamma(gd) : gamma;
            inverseGamma = g == 0.0 ? 1.0 : 1.0/g;

            // Must be called after the fullscreen stuff, but before
            // getting our BufferStrategy or even creating our Canvas
            setVisible(true);

            initCanvas(fullScreen, displayMode, gamma);
        
<methods>public void <init>() throws java.awt.HeadlessException,public void <init>(java.awt.GraphicsConfiguration) ,public void <init>(java.lang.String) throws java.awt.HeadlessException,public void <init>(java.lang.String, java.awt.GraphicsConfiguration) ,public javax.accessibility.AccessibleContext getAccessibleContext() ,public java.awt.Container getContentPane() ,public int getDefaultCloseOperation() ,public java.awt.Component getGlassPane() ,public java.awt.Graphics getGraphics() ,public javax.swing.JMenuBar getJMenuBar() ,public javax.swing.JLayeredPane getLayeredPane() ,public javax.swing.JRootPane getRootPane() ,public javax.swing.TransferHandler getTransferHandler() ,public static boolean isDefaultLookAndFeelDecorated() ,public void remove(java.awt.Component) ,public void repaint(long, int, int, int, int) ,public void setContentPane(java.awt.Container) ,public void setDefaultCloseOperation(int) ,public static void setDefaultLookAndFeelDecorated(boolean) ,public void setGlassPane(java.awt.Component) ,public void setIconImage(java.awt.Image) ,public void setJMenuBar(javax.swing.JMenuBar) ,public void setLayeredPane(javax.swing.JLayeredPane) ,public void setLayout(java.awt.LayoutManager) ,public void setTransferHandler(javax.swing.TransferHandler) ,public void update(java.awt.Graphics) <variables>protected javax.accessibility.AccessibleContext accessibleContext,private int defaultCloseOperation,private static final java.lang.Object defaultLookAndFeelDecoratedKey,protected javax.swing.JRootPane rootPane,protected boolean rootPaneCheckingEnabled,private javax.swing.TransferHandler transferHandler