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 }