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 platformX;
  89     private final int platformY;
  90     private final int platformWidth;
  91     private final int platformHeight;
  92 
  93     private final int visibleX;
  94     private final int visibleY;
  95     private final int visibleWidth;
  96     private final int visibleHeight;
  97 
  98     private final int resolutionX;
  99     private final int resolutionY;
 100 
 101     private final float platformScaleX;
 102     private final float platformScaleY;
 103     private final float outputScaleX;
 104     private final float outputScaleY;
 105 
 106     public Screen(
 107             long nativePtr,
 108 
 109             int depth,
 110             int x,
 111             int y,
 112             int width,
 113             int height,
 114 
 115             int platformX,
 116             int platformY,
 117             int platformWidth,
 118             int platformHeight,
 119 
 120             int visibleX,
 121             int visibleY,
 122             int visibleWidth,
 123             int visibleHeight,
 124 
 125             int resolutionX,
 126             int resolutionY,
 127 
 128             float platformScaleX,
 129             float platformScaleY,
 130             float outputScaleX,
 131             float outputScaleY
 132             ) {
 133         this.ptr = nativePtr;
 134 
 135         this.depth = depth;
 136 
 137         this.x = x;
 138         this.y = y;
 139         this.width = width;
 140         this.height = height;
 141 
 142         this.platformX = platformX;
 143         this.platformY = platformY;
 144         this.platformWidth = platformWidth;
 145         this.platformHeight = platformHeight;
 146 
 147         this.visibleX = visibleX;
 148         this.visibleY = visibleY;
 149         this.visibleWidth = visibleWidth;
 150         this.visibleHeight = visibleHeight;
 151 
 152         if (dpiOverride > 0) {
 153             this.resolutionX = this.resolutionY = dpiOverride;
 154         } else {
 155             this.resolutionX = resolutionX;
 156             this.resolutionY = resolutionY;
 157         }
 158 
 159         this.platformScaleX = platformScaleX;
 160         this.platformScaleY = platformScaleY;
 161         this.outputScaleX = outputScaleX;
 162         this.outputScaleY = outputScaleY;
 163     }
 164 
 165     /**
 166      * Could be called from any thread
 167      */
 168     public int getDepth() {
 169         return this.depth;
 170     }
 171 
 172     /**
 173      * Could be called from any thread
 174      */
 175     public int getX() {
 176         return this.x;
 177     }
 178 
 179     /**
 180      * Could be called from any thread
 181      */
 182     public int getY() {
 183         return this.y;
 184     }
 185 
 186     /**
 187      * Could be called from any thread
 188      */
 189     public int getWidth() {
 190         return this.width;
 191     }
 192 
 193     /**
 194      * Could be called from any thread
 195      */
 196     public int getHeight() {
 197         return this.height;
 198     }
 199 
 200     /**
 201      * Could be called from any thread
 202      */
 203     public int getPlatformX() {
 204         return this.platformX;
 205     }
 206 
 207     /**
 208      * Could be called from any thread
 209      */
 210     public int getPlatformY() {
 211         return this.platformY;
 212     }
 213 
 214     /**
 215      * Could be called from any thread
 216      */
 217     public int getPlatformWidth() {
 218         return this.platformWidth;
 219     }
 220 
 221     /**
 222      * Could be called from any thread
 223      */
 224     public int getPlatformHeight() {
 225         return this.platformHeight;
 226     }
 227 
 228     /**
 229      * Returns the horizontal scaling of the UI (window sizes and event
 230      * coordinates) from FX logical units to the platform units.
 231      * Could be called from any thread
 232      * @return platform X scaling
 233      */
 234     public float getPlatformScaleX() {
 235         return this.platformScaleX;
 236     }
 237 
 238     /**
 239      * Returns the vertical scaling of the UI (window sizes and event
 240      * coordinates) from FX logical units to the platform units.
 241      * Could be called from any thread
 242      * @return platform Y scaling
 243      */
 244     public float getPlatformScaleY() {
 245         return this.platformScaleY;
 246     }
 247 
 248     /**
 249      * Returns the recommended horizontal scaling for the rendered frames.
 250      * Could be called from any thread
 251      * @return recommended render X scaling
 252      */
 253     public float getRecommendedOutputScaleX() {
 254         return this.outputScaleX;
 255     }
 256 
 257     /**
 258      * Returns the recommended vertical scaling for the rendered frames.
 259      * Could be called from any thread
 260      * @return recommended render Y scaling
 261      */
 262     public float getRecommendedOutputScaleY() {
 263         return this.outputScaleY;
 264     }
 265 
 266     /**
 267      * Could be called from any thread
 268      */
 269     public int getVisibleX() {
 270         return this.visibleX;
 271     }
 272 
 273     /**
 274      * Could be called from any thread
 275      */
 276     public int getVisibleY() {
 277         return this.visibleY;
 278     }
 279 
 280     /**
 281      * Could be called from any thread
 282      */
 283     public int getVisibleWidth() {
 284         return this.visibleWidth;
 285     }
 286 
 287     /**
 288      * Could be called from any thread
 289      */
 290     public int getVisibleHeight() {
 291         return this.visibleHeight;
 292     }
 293 
 294     /**
 295      * Could be called from any thread
 296      */
 297     public int getResolutionX() {
 298         return this.resolutionX;
 299     }
 300 
 301     /**
 302      * Could be called from any thread
 303      */
 304     public int getResolutionY() {
 305         return this.resolutionY;
 306     }
 307 
 308     /**
 309      * Could be called from any thread
 310      */
 311     public long getNativeScreen() {
 312         return this.ptr;
 313     }
 314 
 315     private void dispose() {
 316         this.ptr = 0L;
 317     }
 318 
 319     public int getAdapterOrdinal() {
 320         return this.adapter;
 321     }
 322 
 323     public void setAdapterOrdinal(int adapter) {
 324         this.adapter = adapter;
 325     }
 326 
 327     public static void setEventHandler(EventHandler eh) {
 328         Application.checkEventThread();
 329         eventHandler = eh;
 330     }
 331 
 332     /**
 333      * Called from native when the Screen definitions change.
 334      */
 335     public static void notifySettingsChanged() {
 336         // Save the old screens in order to dispose them later
 337         List<Screen> oldScreens = screens;
 338 
 339         // Get the new screens
 340         initScreens();
 341 
 342         if (eventHandler != null) {
 343             eventHandler.handleSettingsChanged();
 344         }
 345 
 346         // Update the screen for each window to match the new instance.
 347         // Note that if a window has moved to another screen, the window
 348         // will be notified separately of that from native code and the
 349         // new screen will be updated there
 350         List<Window> windows = Window.getWindows();
 351         for (Window w : windows) {
 352             Screen oldScreen = w.getScreen();
 353             for (Screen newScreen : screens) {
 354                 if (oldScreen.getNativeScreen() == newScreen.getNativeScreen()) {
 355                     w.setScreen(newScreen);
 356                     break;
 357                 }
 358             }
 359         }
 360 
 361         // Dispose the old screens
 362         if (oldScreens != null) {
 363             for (Screen screen : oldScreens) {
 364                 screen.dispose();
 365             }
 366         }
 367     }
 368 
 369     static void initScreens() {
 370         Application.checkEventThread();
 371         Screen[] newScreens = Application.GetApplication().staticScreen_getScreens();
 372         if (newScreens == null) {
 373             throw new RuntimeException("Internal graphics failed to initialize");
 374         }
 375         screens = Collections.unmodifiableList(Arrays.asList(newScreens));
 376     }
 377 
 378     @Override public String toString() {
 379         return  "Screen:"+"\n"+
 380                 "    ptr:"+getNativeScreen()+"\n"+
 381                 "    adapter:"+getAdapterOrdinal()+"\n"+
 382                 "    depth:"+getDepth()+"\n"+
 383                 "    x:"+getX()+"\n"+
 384                 "    y:"+getY()+"\n"+
 385                 "    width:"+getWidth()+"\n"+
 386                 "    height:"+getHeight()+"\n"+
 387                 "    platformX:"+getPlatformX()+"\n"+
 388                 "    platformY:"+getPlatformY()+"\n"+
 389                 "    platformWidth:"+getPlatformWidth()+"\n"+
 390                 "    platformHeight:"+getPlatformHeight()+"\n"+
 391                 "    visibleX:"+getVisibleX()+"\n"+
 392                 "    visibleY:"+getVisibleY()+"\n"+
 393                 "    visibleWidth:"+getVisibleWidth()+"\n"+
 394                 "    visibleHeight:"+getVisibleHeight()+"\n"+
 395                 "    platformScaleX:"+getPlatformScaleX()+"\n"+
 396                 "    platformScaleY:"+getPlatformScaleY()+"\n"+
 397                 "    outputScaleX:"+getRecommendedOutputScaleX()+"\n"+
 398                 "    outputScaleY:"+getRecommendedOutputScaleY()+"\n"+
 399                 "    resolutionX:"+getResolutionX()+"\n"+
 400                 "    resolutionY:"+getResolutionY()+"\n";
 401     }
 402 
 403     @Override public boolean equals(Object o) {
 404         if (this == o) return true;
 405         if (o == null || getClass() != o.getClass()) return false;
 406 
 407         Screen screen = (Screen) o;
 408         return ptr == screen.ptr
 409                 && adapter == screen.adapter
 410                 && depth == screen.depth
 411                 && x == screen.x
 412                 && y == screen.y
 413                 && width == screen.width
 414                 && height == screen.height
 415                 && visibleX == screen.visibleX
 416                 && visibleY == screen.visibleY
 417                 && visibleWidth == screen.visibleWidth
 418                 && visibleHeight == screen.visibleHeight
 419                 && resolutionX == screen.resolutionX
 420                 && resolutionY == screen.resolutionY
 421                 && Float.compare(screen.platformScaleX, platformScaleX) == 0
 422                 && Float.compare(screen.platformScaleY, platformScaleY) == 0
 423                 && Float.compare(screen.outputScaleX, outputScaleX) == 0
 424                 && Float.compare(screen.outputScaleY, outputScaleY) == 0;
 425     }
 426 
 427     @Override public int hashCode() {
 428         int result = 17;
 429         result = 31 * result + (int) (ptr ^ (ptr >>> 32));
 430         result = 31 * result + adapter;
 431         result = 31 * result + depth;
 432         result = 31 * result + x;
 433         result = 31 * result + y;
 434         result = 31 * result + width;
 435         result = 31 * result + height;
 436         result = 31 * result + visibleX;
 437         result = 31 * result + visibleY;
 438         result = 31 * result + visibleWidth;
 439         result = 31 * result + visibleHeight;
 440         result = 31 * result + resolutionX;
 441         result = 31 * result + resolutionY;
 442         result = 31 * result + (platformScaleX != +0.0f ? Float.floatToIntBits(platformScaleX) : 0);
 443         result = 31 * result + (platformScaleY != +0.0f ? Float.floatToIntBits(platformScaleY) : 0);
 444         result = 31 * result + (outputScaleX != +0.0f ? Float.floatToIntBits(outputScaleX) : 0);
 445         result = 31 * result + (outputScaleY != +0.0f ? Float.floatToIntBits(outputScaleY) : 0);
 446         return result;
 447     }
 448 }