[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/2php/processing/master/core/src/processing/awt/PSurfaceAWT.java [Back]  [Original]

/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
  Part of the Processing project - http://processing.org

  Copyright (c) 2014-15 The Processing Foundation

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation, version 2.1.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

package processing.awt;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
import processing.core.PImage;
import processing.core.PSurfaceNone;
import processing.event.KeyEvent;
import processing.event.MouseEvent;


public class PSurfaceAWT extends PSurfaceNone {
  GraphicsDevice displayDevice;

  // used for canvas to determine whether resizable or not
//  boolean resizable;  // default is false

  // Internally, we know it's always a JFrame (not just a Frame)
//  JFrame frame;
  // Trying Frame again with a11 to see if this avoids some Swing nastiness.
  // In the past, AWT Frames caused some problems on Windows and Linux,
  // but those may not be a problem for our reworked PSurfaceAWT class.
  Frame frame;

  // Note that x and y may not be zero, depending on the display configuration
  Rectangle screenRect;

  // Used for resizing, at least on Windows insets size changes when
  // frame.setResizable() is called, and in resize listener we need
  // to know what size the window was before.
  Insets currentInsets = new Insets(0, 0, 0, 0);

  // 3.0a5 didn't use strategy, and active was shut off during init() w/ retina
//  boolean useStrategy = true;

  Canvas canvas;
//  Component canvas;

//  PGraphics graphics;  // moved to PSurfaceNone

  int sketchWidth;
  int sketchHeight;


  public PSurfaceAWT(PGraphics graphics) {
    //this.graphics = graphics;
    super(graphics);

    /*
    if (checkRetina()) {
//      System.out.println("retina in use");

      // The active-mode rendering seems to be 2x slower, so disable it
      // with retina. On a non-retina machine, however, useActive seems
      // the only (or best) way to handle the rendering.
//      useActive = false;
//      canvas = new JPanel(true) {
//        @Override
//        public void paint(Graphics screen) {
////          if (!sketch.insideDraw) {
//          screen.drawImage(PSurfaceAWT.this.graphics.image, 0, 0, sketchWidth, sketchHeight, null);
////          }
//        }
//      };
      // Under 1.8 and the current 3.0a6 threading regime, active mode w/o
      // strategy is far faster, but perhaps only because it's blitting with
      // flicker--pushing pixels out before the screen has finished rendering.
//      useStrategy = false;
    }
    */
    canvas = new SmoothCanvas();
//    if (useStrategy) {
    //canvas.setIgnoreRepaint(true);
//    }

    // Pass tab key to the sketch, rather than moving between components
    canvas.setFocusTraversalKeysEnabled(false);

    canvas.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        if (!sketch.isLooping()) {
          // make sure this is a real resize event, not just initial setup
          // https://github.com/processing/processing/issues/3310
          Dimension canvasSize = canvas.getSize();
          if (canvasSize.width != sketch.sketchWidth() ||
              canvasSize.height != sketch.sketchHeight()) {
            sketch.redraw();
          }
        }
      }
    });
    addListeners();
  }


//  /**
//   * Handle grabbing the focus on startup. Other renderers can override this
//   * if handling needs to be different. For the AWT, the request is invoked
//   * later on the EDT. Other implementations may not require that, so the
//   * invokeLater() happens in here rather than requiring the caller to wrap it.
//   */
//  @Override
//  void requestFocus() {
////    System.out.println("requesFocus() outer " + EventQueue.isDispatchThread());
//    // for 2.0a6, moving this request to the EDT
//    EventQueue.invokeLater(new Runnable() {
//      public void run() {
//        // Call the request focus event once the image is sure to be on
//        // screen and the component is valid. The OpenGL renderer will
//        // request focus for its canvas inside beginDraw().
//        // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/FocusSpec.html
//        // Disabling for 0185, because it causes an assertion failure on OS X
//        // http://code.google.com/p/processing/issues/detail?id=258
//        //        requestFocus();
//
//        // Changing to this version for 0187
//        // http://code.google.com/p/processing/issues/detail?id=279
//        //requestFocusInWindow();
//
//        // For 3.0, just call this directly on the Canvas object
//        if (canvas != null) {
//          //System.out.println("requesting focus " + EventQueue.isDispatchThread());
//          //System.out.println("requesting focus " + frame.isVisible());
//          //canvas.requestFocusInWindow();
//          canvas.requestFocus();
//        }
//      }
//    });
//  }


  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


  public class SmoothCanvas extends Canvas {
    private Dimension oldSize = new Dimension(0, 0);
    private Dimension newSize = new Dimension(0, 0);


    // Turns out getParent() returns a JPanel on a JFrame. Yech.
    public Frame getFrame() {
      return frame;
    }


    @Override
    public Dimension getPreferredSize() {
      return new Dimension(sketchWidth, sketchHeight);
    }


    @Override
    public Dimension getMinimumSize() {
      return getPreferredSize();
    }


    @Override
    public Dimension getMaximumSize() {
      //return resizable ? super.getMaximumSize() : getPreferredSize();
      return frame.isResizable() ? super.getMaximumSize() : getPreferredSize();
    }


    @Override
    public void validate() {
      super.validate();
      newSize.width = getWidth();
      newSize.height = getHeight();
//      if (oldSize.equals(newSize)) {
////        System.out.println("validate() return " + oldSize);
//        return;
//      } else {
      if (!oldSize.equals(newSize)) {
//        System.out.println("validate() render old=" + oldSize + " -> new=" + newSize);
        oldSize = newSize;
        sketch.setSize(newSize.width, newSize.height);
//        try {
        render();
//        } catch (IllegalStateException ise) {
//          System.out.println(ise.getMessage());
//        }
      }
    }


    @Override
    public void update(Graphics g) {
//      System.out.println("updating");
      paint(g);
    }


    @Override
    public void paint(Graphics screen) {
//      System.out.println("painting");
//      if (useStrategy) {
      render();
      /*
      if (graphics != null) {
        System.out.println("drawing to screen " + canvas);
        screen.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
      }
      */

//      } else {
////        new Exception("painting").printStackTrace(System.out);
////        if (graphics.image != null) { // && !sketch.insideDraw) {
//        if (onscreen != null) {
////          synchronized (graphics.image) {
//          // Needs the width/height to be set so that retina images are properly scaled down
////          screen.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
//          synchronized (offscreenLock) {
//            screen.drawImage(onscreen, 0, 0, sketchWidth, sketchHeight, null);
//          }
//        }
//      }
    }
  }

    /*
    @Override
    public void addNotify() {
//      System.out.println("adding notify");
      super.addNotify();
      // prior to Java 7 on OS X, this no longer works [121222]
//    createBufferStrategy(2);
    }
    */


  synchronized protected void render() {
    if (canvas.isDisplayable() &&
        graphics.image != null) {
      if (canvas.getBufferStrategy() == null) {
        canvas.createBufferStrategy(2);
      }
      BufferStrategy strategy = canvas.getBufferStrategy();
      if (strategy != null) {
        // Render single frame
//        try {
        do {
          // The following loop ensures that the contents of the drawing buffer
          // are consistent in case the underlying surface was recreated
          do {
            Graphics2D draw = (Graphics2D) strategy.getDrawGraphics();
            // draw to width/height, since this may be a 2x image
            draw.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
            draw.dispose();
          } while (strategy.contentsRestored());

          // Display the buffer
          strategy.show();

          // Repeat the rendering if the drawing buffer was lost
        } while (strategy.contentsLost());
      }
    }
  }


  /*
  protected void blit() {
    // Other folks that call render() (i.e. paint()) are already on the EDT.
    // We need to be using the EDT since we're messing with the Canvas
    // object and BufferStrategy and friends.
    //EventQueue.invokeLater(new Runnable() {
    //public void run() {
    //((SmoothCanvas) canvas).render();
    //}
    //});

    if (useStrategy) {
      // Not necessary to be on the EDT to update BufferStrategy
      //((SmoothCanvas) canvas).render();
      render();
    } else {
      if (graphics.image != null) {
        BufferedImage graphicsImage = (BufferedImage) graphics.image;
        if (offscreen == null ||
          offscreen.getWidth() != graphicsImage.getWidth() ||
          offscreen.getHeight() != graphicsImage.getHeight()) {
          System.out.println("creating new image");
          offscreen = (BufferedImage)
            canvas.createImage(graphicsImage.getWidth(),
                               graphicsImage.getHeight());
//          off = offscreen.getGraphics();
        }
//        synchronized (offscreen) {
        Graphics2D off = (Graphics2D) offscreen.getGraphics();
//        off.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
        off.drawImage(graphicsImage, 0, 0, null);
//        }
        off.dispose();
        synchronized (offscreenLock) {
          BufferedImage temp = onscreen;
          onscreen = offscreen;
          offscreen = temp;
        }
        canvas.repaint();
      }
    }
  }
  */


  // what needs to happen here?
  @Override
  public void initOffscreen(PApplet sketch) {
    this.sketch = sketch;
  }

  /*
  public Frame initOffscreen() {
    Frame dummy = new Frame();
    dummy.pack();  // get legit AWT graphics
    // but don't show it
    return dummy;
  }
  */

  /*
  @Override
  public Component initComponent(PApplet sketch) {
    this.sketch = sketch;

    // needed for getPreferredSize() et al
    sketchWidth = sketch.sketchWidth();
    sketchHeight = sketch.sketchHeight();

    return canvas;
  }
  */


  @Override
  public void initFrame(final PApplet sketch) {/*, int backgroundColor,
                        int deviceIndex, boolean fullScreen, boolean spanDisplays) {*/
    this.sketch = sketch;

    GraphicsEnvironment environment =
      GraphicsEnvironment.getLocalGraphicsEnvironment();

    int displayNum = sketch.sketchDisplay();
//    System.out.println("display from sketch is " + displayNum);
    if (displayNum > 0) {  // if -1, use the default device
      GraphicsDevice[] devices = environment.getScreenDevices();
      if (displayNum 

Web Proxy Viewer  |  New URL  |  Original Page