1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.sun.glass.ui;
  26 
  27 import java.security.AccessController;
  28 import java.security.PrivilegedAction;
  29 import java.util.Arrays;
  30 import java.util.Collections;
  31 import java.util.List;
  32 
  33 public final class Screen {
  34 
  35     // the list of attached screens provided by native.
  36     // screens[0] is the default/main Screen
  37     private static volatile List<Screen> screens = null ;
  38 
  39     // If dpiOverride is non-zero, use its value as screen DPI
  40     private static final int dpiOverride;
  41 
  42     static {
  43         dpiOverride = AccessController.doPrivileged((PrivilegedAction<Integer>) () -> Integer.getInteger("com.sun.javafx.screenDPI", 0)).intValue();
  44     }
  45 
  46     public static class EventHandler {
  47         public void handleSettingsChanged() {
  48         }
  49     }
  50 
  51     public static double getVideoRefreshPeriod() {
  52         Application.checkEventThread();
  53         return Application.GetApplication().staticScreen_getVideoRefreshPeriod();
  54     }
  55 
  56     /**
  57      * Could be called from any thread
  58      * @return the main screen
  59      */
  60     public static Screen getMainScreen() {
  61         return getScreens().get(0);
  62     }
  63 
  64     /**
  65      * Could be called from any thread
  66      * @return list of all available screens
  67      */
  68     public static List<Screen> getScreens() {
  69         if (screens == null) {
  70             throw new RuntimeException("Internal graphics not initialized yet");
  71         }
  72 
  73         return screens;
  74     }
  75 
  76     private static EventHandler eventHandler;
  77 
  78     private volatile long ptr;
  79     private volatile int adapter;
  80 
  81     private final int depth;
  82 
  83     private final int x;
  84     private final int y;
  85     private final int width;
  86     private final int height;
  87 
  88     private final int visibleX;
  89     private final int visibleY;
  90     private final int visibleWidth;
  91     private final int visibleHeight;
  92 
  93     private final int resolutionX;
  94     private final int resolutionY;
  95 
  96     private final float uiScale;
  97     private final float renderScale;
  98 
  99     protected Screen(
 100             long nativePtr,
 101 
 102             int depth,
 103             int x,
 104             int y,
 105             int width,
 106             int height,
 107 
 108             int visibleX,
 109             int visibleY,
 110             int visibleWidth,
 111             int visibleHeight,
 112 
 113             int resolutionX,
 114             int resolutionY,
 115 
 116             float renderScale
 117             ) {
 118         this(nativePtr,
 119              depth, x, y, width, height,
 120              visibleX, visibleY, visibleWidth, visibleHeight,
 121              resolutionX, resolutionY,
 122              1.0f, renderScale);
 123     }
 124 
 125     protected Screen(
 126             long nativePtr,
 127 
 128             int depth,
 129             int x,
 130             int y,
 131             int width,
 132             int height,
 133 
 134             int visibleX,
 135             int visibleY,
 136             int visibleWidth,
 137             int visibleHeight,
 138 
 139             int resolutionX,
 140             int resolutionY,
 141 
 142             float uiScale,
 143             float renderScale
 144             ) {
 145         this.ptr = nativePtr;
 146 
 147         this.depth = depth;
 148 
 149         this.x = x;
 150         this.y = y;
 151         this.width = width;
 152         this.height = height;
 153 
 154         this.visibleX = visibleX;
 155         this.visibleY = visibleY;
 156         this.visibleWidth = visibleWidth;
 157         this.visibleHeight = visibleHeight;
 158 
 159         if (dpiOverride > 0) {
 160             this.resolutionX = this.resolutionY = dpiOverride;
 161         } else {
 162             this.resolutionX = resolutionX;
 163             this.resolutionY = resolutionY;
 164         }
 165 
 166         this.uiScale = uiScale;
 167         this.renderScale = renderScale;
 168     }
 169 
 170     /**
 171      * Could be called from any thread
 172      */
 173     public int getDepth() {
 174         return this.depth;
 175     }
 176 
 177     /**
 178      * Could be called from any thread
 179      */
 180     public int getX() {
 181         return this.x;
 182     }
 183 
 184     /**
 185      * Could be called from any thread
 186      */
 187     public int getY() {
 188         return this.y;
 189     }
 190 
 191     /**
 192      * Could be called from any thread
 193      */
 194     public int getWidth() {
 195         return this.width;
 196     }
 197 
 198     /**
 199      * Could be called from any thread
 200      */
 201     public int getHeight() {
 202         return this.height;
 203     }
 204 
 205     /**
 206      * Could be called from any thread
 207      */
 208     public int getVisibleX() {
 209         return this.visibleX;
 210     }
 211 
 212     /**
 213      * Could be called from any thread
 214      */
 215     public int getVisibleY() {
 216         return this.visibleY;
 217     }
 218 
 219     /**
 220      * Could be called from any thread
 221      */
 222     public int getVisibleWidth() {
 223         return this.visibleWidth;
 224     }
 225 
 226     /**
 227      * Could be called from any thread
 228      */
 229     public int getVisibleHeight() {
 230         return this.visibleHeight;
 231     }
 232 
 233     /**
 234      * Could be called from any thread
 235      */
 236     public int getResolutionX() {
 237         return this.resolutionX;
 238     }
 239 
 240     /**
 241      * Could be called from any thread
 242      */
 243     public int getResolutionY() {
 244         return this.resolutionY;
 245     }
 246 
 247     /**
 248      * Returns the scaling of the UI (window sizes and event coordinates)
 249      * on the screen.
 250      * Could be called from any thread
 251      */
 252     public float getUIScale() {
 253         return this.uiScale;
 254     }
 255 
 256     /**
 257      * Returns the recommended scaling for rendering an image for this
 258      * screen, potentially larger than {@link #getUIScale()}.
 259      * Could be called from any thread
 260      */
 261     public float getRenderScale() {
 262         return this.renderScale;
 263     }
 264 
 265     /**
 266      * Could be called from any thread
 267      */
 268     public long getNativeScreen() {
 269         return this.ptr;
 270     }
 271 
 272     private void dispose() {
 273         this.ptr = 0L;
 274     }
 275 
 276     public int getAdapterOrdinal() {
 277         return this.adapter;
 278     }
 279 
 280     public void setAdapterOrdinal(int adapter) {
 281         this.adapter = adapter;
 282     }
 283 
 284     public static void setEventHandler(EventHandler eh) {
 285         Application.checkEventThread();
 286         eventHandler = eh;
 287     }
 288 
 289     /**
 290      * Called from native when the Screen definitions change.
 291      */
 292     public static void notifySettingsChanged() {
 293         // Save the old screens in order to dispose them later
 294         List<Screen> oldScreens = screens;
 295 
 296         // Get the new screens
 297         initScreens();
 298 
 299         if (eventHandler != null) {
 300             eventHandler.handleSettingsChanged();
 301         }
 302 
 303         // Update the screen for each window to match the new instance.
 304         // Note that if a window has moved to another screen, the window
 305         // will be notified separately of that from native code and the
 306         // new screen will be updated there
 307         List<Window> windows = Window.getWindows();
 308         for (Window w : windows) {
 309             Screen oldScreen = w.getScreen();
 310             for (Screen newScreen : screens) {
 311                 if (oldScreen.getNativeScreen() == newScreen.getNativeScreen()) {
 312                     w.setScreen(newScreen);
 313                     break;
 314                 }
 315             }
 316         }
 317 
 318         // Dispose the old screens
 319         if (oldScreens != null) {
 320             for (Screen screen : oldScreens) {
 321                 screen.dispose();
 322             }
 323         }
 324     }
 325 
 326     static void initScreens() {
 327         Application.checkEventThread();
 328         Screen[] newScreens = Application.GetApplication().staticScreen_getScreens();
 329         if (newScreens == null) {
 330             throw new RuntimeException("Internal graphics failed to initialize");
 331         }
 332         screens = Collections.unmodifiableList(Arrays.asList(newScreens));
 333     }
 334 
 335     @Override public String toString() {
 336         return  "Screen:"+"\n"+
 337                 "    ptr:"+getNativeScreen()+"\n"+
 338                 "    adapter:"+getAdapterOrdinal()+"\n"+
 339                 "    depth:"+getDepth()+"\n"+
 340                 "    x:"+getX()+"\n"+
 341                 "    y:"+getY()+"\n"+
 342                 "    width:"+getWidth()+"\n"+
 343                 "    height:"+getHeight()+"\n"+
 344                 "    visibleX:"+getVisibleX()+"\n"+
 345                 "    visibleY:"+getVisibleY()+"\n"+
 346                 "    visibleWidth:"+getVisibleWidth()+"\n"+
 347                 "    visibleHeight:"+getVisibleHeight()+"\n"+
 348                 "    uiScale:"+getUIScale()+"\n"+
 349                 "    RenderScale:"+getRenderScale()+"\n"+
 350                 "    resolutionX:"+getResolutionX()+"\n"+
 351                 "    resolutionY:"+getResolutionY()+"\n";
 352     }
 353 
 354     @Override public boolean equals(Object o) {
 355         if (this == o) return true;
 356         if (o == null || getClass() != o.getClass()) return false;
 357 
 358         Screen screen = (Screen) o;
 359         return ptr == screen.ptr
 360                 && adapter == screen.adapter
 361                 && depth == screen.depth
 362                 && x == screen.x
 363                 && y == screen.y
 364                 && width == screen.width
 365                 && height == screen.height
 366                 && visibleX == screen.visibleX
 367                 && visibleY == screen.visibleY
 368                 && visibleWidth == screen.visibleWidth
 369                 && visibleHeight == screen.visibleHeight
 370                 && resolutionX == screen.resolutionX
 371                 && resolutionY == screen.resolutionY
 372                 && Float.compare(screen.uiScale, uiScale) == 0
 373                 && Float.compare(screen.renderScale, renderScale) == 0;
 374     }
 375 
 376     @Override public int hashCode() {
 377         int result = 17;
 378         result = 31 * result + (int) (ptr ^ (ptr >>> 32));
 379         result = 31 * result + adapter;
 380         result = 31 * result + depth;
 381         result = 31 * result + x;
 382         result = 31 * result + y;
 383         result = 31 * result + width;
 384         result = 31 * result + height;
 385         result = 31 * result + visibleX;
 386         result = 31 * result + visibleY;
 387         result = 31 * result + visibleWidth;
 388         result = 31 * result + visibleHeight;
 389         result = 31 * result + resolutionX;
 390         result = 31 * result + resolutionY;
 391         result = 31 * result + (uiScale != +0.0f ? Float.floatToIntBits(uiScale) : 0);
 392         result = 31 * result + (renderScale != +0.0f ? Float.floatToIntBits(renderScale) : 0);
 393         return result;
 394     }
 395 }