189 190 private final Window owner; 191 private final long parent; 192 private final int styleMask; 193 private final boolean isDecorated; 194 private boolean shouldStartUndecoratedMove = false; 195 196 private View view = null; 197 private Screen screen = null; 198 private MenuBar menubar = null; 199 private String title = ""; 200 private UndecoratedMoveResizeHelper helper = null; 201 202 private int state = State.NORMAL; 203 private int level = Level.NORMAL; 204 private int x = 0; 205 private int y = 0; 206 private int width = 0; 207 private int height = 0; 208 private float alpha = 1.0f; 209 private float platformScale = 1.0f; 210 private float renderScale = 1.0f; 211 212 // This is a workaround for RT-15970: as for embedded windows we don't 213 // receive any MOVE notifications from the native platform, we poll 214 // the window location on screen from timer and post synthetic events 215 // if it has changed 216 private Timer embeddedLocationTimer = null; 217 private int lastKnownEmbeddedX = 0; 218 private int lastKnownEmbeddedY = 0; 219 220 private volatile boolean isResizable = false; 221 private volatile boolean isVisible = false; 222 private volatile boolean isFocused = false; 223 private volatile boolean isFocusable = true; 224 private volatile boolean isModal = false; 225 226 // Indicates how many times setEnabled(false) has been called. 227 // A value of 0 means the window is enabled. 228 private volatile int disableCount = 0; 229 230 private int minimumWidth = 0, minimumHeight = 0; 252 throw new RuntimeException("The functional type should be NORMAL, POPUP, or UTILITY, but not a combination of these"); 253 } 254 255 if (((styleMask & UNIFIED) != 0) 256 && !Application.GetApplication().supportsUnifiedWindows()) { 257 styleMask &= ~UNIFIED; 258 } 259 260 if (((styleMask & TRANSPARENT) != 0) 261 && !Application.GetApplication().supportsTransparentWindows()) { 262 styleMask &= ~TRANSPARENT; 263 } 264 265 266 this.owner = owner; 267 this.parent = 0L; 268 this.styleMask = styleMask; 269 this.isDecorated = (this.styleMask & Window.TITLED) != 0; 270 271 this.screen = screen != null ? screen : Screen.getMainScreen(); 272 273 this.ptr = _createWindow(owner != null ? owner.getNativeHandle() : 0L, 274 this.screen.getNativeScreen(), this.styleMask); 275 if (this.ptr == 0L) { 276 throw new RuntimeException("could not create platform window"); 277 } 278 } 279 280 protected abstract long _createChildWindow(long parent); 281 /** 282 * Constructs a child window of the specified native parent window. 283 */ 284 protected Window(long parent) { 285 Application.checkEventThread(); 286 this.owner = null; 287 this.parent = parent; 288 this.styleMask = Window.UNTITLED; 289 this.isDecorated = false; 290 291 // Note: we can't always catch screen changes when parent is moved... 449 Application.checkEventThread(); 450 checkNotClosed(); 451 _minimize(this.ptr, minimize); 452 //XXX: this is synchronous? On X11 this may not work 453 return isMinimized(); 454 } 455 456 public boolean isMaximized() { 457 Application.checkEventThread(); 458 return (this.state == State.MAXIMIZED); 459 } 460 461 protected abstract boolean _maximize(long ptr, boolean maximize, boolean wasMaximized); 462 public boolean maximize(final boolean maximize) { 463 Application.checkEventThread(); 464 checkNotClosed(); 465 _maximize(ptr, maximize, isMaximized()); 466 return isMaximized(); 467 } 468 469 public void setPlatformScale(float platformScale) { 470 if (!PrismSettings.allowHiDPIScaling) return; 471 this.platformScale = platformScale; 472 } 473 474 /** 475 * Return the scale used to communicate window locations, sizes, and event 476 * coordinates to/from the platform. 477 * @return the platform scaling for screen locations 478 */ 479 public final float getPlatformScale() { 480 return platformScale; 481 } 482 483 public void setRenderScale(float renderScale) { 484 if (!PrismSettings.allowHiDPIScaling) return; 485 this.renderScale = renderScale; 486 } 487 488 /** 489 * Return the scale that should be used to render content on this window. 490 * This is usually similar to the platform scale, but may be different 491 * depending on how the platform manages events vs. rendering buffers 492 * and/or whether the system can handle non-integer rendering scales. 493 * @return the pixel scaling to be used during rendering 494 */ 495 public final float getRenderScale() { 496 return renderScale; 497 } 498 499 public float getOutputScale() { 500 return platformScale; 501 } 502 503 protected abstract int _getEmbeddedX(long ptr); 504 protected abstract int _getEmbeddedY(long ptr); 505 506 private void checkScreenLocation() { 507 this.x = _getEmbeddedX(ptr); 508 this.y = _getEmbeddedY(ptr); 509 if ((this.x != lastKnownEmbeddedX) || (this.y != lastKnownEmbeddedY)) { 510 lastKnownEmbeddedX = this.x; 511 lastKnownEmbeddedY = this.y; 512 handleWindowEvent(System.nanoTime(), WindowEvent.MOVE); 513 } 514 } 515 516 public int getX() { 517 Application.checkEventThread(); 518 return this.x; 519 } 520 1177 protected void notifyDestroy() { 1178 // Mac is known to send multiple WillClose notifications for some reason 1179 if (this.ptr == 0) { 1180 return; 1181 } 1182 1183 handleWindowEvent(System.nanoTime(), WindowEvent.DESTROY); 1184 1185 this.ptr = 0; 1186 1187 // Do this after setting ptr to 0 to avoid a call to _setVisible() 1188 setVisible(false); 1189 } 1190 1191 protected void notifyMove(final int x, final int y) { 1192 this.x = x; 1193 this.y = y; 1194 handleWindowEvent(System.nanoTime(), WindowEvent.MOVE); 1195 } 1196 1197 protected void notifyMoveToAnotherScreen(Screen newScreen) { 1198 setScreen(newScreen); 1199 } 1200 1201 /** 1202 * type values: 1203 * - WindowEvent.RESIZE 1204 * - WindowEvent.MINIMIZE 1205 * - WindowEvent.MAXIMIZE 1206 * - WindowEvent.RESTORE 1207 */ 1208 protected void notifyResize(final int type, final int width, final int height) { 1209 if (type == WindowEvent.MINIMIZE) { 1210 this.state = State.MINIMIZED; 1211 } else { 1212 if (type == WindowEvent.MAXIMIZE) { 1213 this.state = State.MAXIMIZED; 1214 } else { // WindowEvent.RESIZE or WindowEvent.RESTORE 1215 this.state = State.NORMAL; 1216 } | 189 190 private final Window owner; 191 private final long parent; 192 private final int styleMask; 193 private final boolean isDecorated; 194 private boolean shouldStartUndecoratedMove = false; 195 196 private View view = null; 197 private Screen screen = null; 198 private MenuBar menubar = null; 199 private String title = ""; 200 private UndecoratedMoveResizeHelper helper = null; 201 202 private int state = State.NORMAL; 203 private int level = Level.NORMAL; 204 private int x = 0; 205 private int y = 0; 206 private int width = 0; 207 private int height = 0; 208 private float alpha = 1.0f; 209 private float platformScaleX = 1.0f; 210 private float platformScaleY = 1.0f; 211 private float outputScaleX = 1.0f; 212 private float outputScaleY = 1.0f; 213 private float renderScaleX = 1.0f; 214 private float renderScaleY = 1.0f; 215 216 // This is a workaround for RT-15970: as for embedded windows we don't 217 // receive any MOVE notifications from the native platform, we poll 218 // the window location on screen from timer and post synthetic events 219 // if it has changed 220 private Timer embeddedLocationTimer = null; 221 private int lastKnownEmbeddedX = 0; 222 private int lastKnownEmbeddedY = 0; 223 224 private volatile boolean isResizable = false; 225 private volatile boolean isVisible = false; 226 private volatile boolean isFocused = false; 227 private volatile boolean isFocusable = true; 228 private volatile boolean isModal = false; 229 230 // Indicates how many times setEnabled(false) has been called. 231 // A value of 0 means the window is enabled. 232 private volatile int disableCount = 0; 233 234 private int minimumWidth = 0, minimumHeight = 0; 256 throw new RuntimeException("The functional type should be NORMAL, POPUP, or UTILITY, but not a combination of these"); 257 } 258 259 if (((styleMask & UNIFIED) != 0) 260 && !Application.GetApplication().supportsUnifiedWindows()) { 261 styleMask &= ~UNIFIED; 262 } 263 264 if (((styleMask & TRANSPARENT) != 0) 265 && !Application.GetApplication().supportsTransparentWindows()) { 266 styleMask &= ~TRANSPARENT; 267 } 268 269 270 this.owner = owner; 271 this.parent = 0L; 272 this.styleMask = styleMask; 273 this.isDecorated = (this.styleMask & Window.TITLED) != 0; 274 275 this.screen = screen != null ? screen : Screen.getMainScreen(); 276 if (PrismSettings.allowHiDPIScaling) { 277 this.platformScaleX = this.screen.getPlatformScaleX(); 278 this.platformScaleY = this.screen.getPlatformScaleY(); 279 this.outputScaleX = this.screen.getRecommendedOutputScaleX(); 280 this.outputScaleY = this.screen.getRecommendedOutputScaleY(); 281 } 282 283 this.ptr = _createWindow(owner != null ? owner.getNativeHandle() : 0L, 284 this.screen.getNativeScreen(), this.styleMask); 285 if (this.ptr == 0L) { 286 throw new RuntimeException("could not create platform window"); 287 } 288 } 289 290 protected abstract long _createChildWindow(long parent); 291 /** 292 * Constructs a child window of the specified native parent window. 293 */ 294 protected Window(long parent) { 295 Application.checkEventThread(); 296 this.owner = null; 297 this.parent = parent; 298 this.styleMask = Window.UNTITLED; 299 this.isDecorated = false; 300 301 // Note: we can't always catch screen changes when parent is moved... 459 Application.checkEventThread(); 460 checkNotClosed(); 461 _minimize(this.ptr, minimize); 462 //XXX: this is synchronous? On X11 this may not work 463 return isMinimized(); 464 } 465 466 public boolean isMaximized() { 467 Application.checkEventThread(); 468 return (this.state == State.MAXIMIZED); 469 } 470 471 protected abstract boolean _maximize(long ptr, boolean maximize, boolean wasMaximized); 472 public boolean maximize(final boolean maximize) { 473 Application.checkEventThread(); 474 checkNotClosed(); 475 _maximize(ptr, maximize, isMaximized()); 476 return isMaximized(); 477 } 478 479 protected void notifyScaleChanged(float platformScaleX, float platformScaleY, 480 float outputScaleX, float outputScaleY) 481 { 482 if (!PrismSettings.allowHiDPIScaling) return; 483 this.platformScaleX = platformScaleX; 484 this.platformScaleY = platformScaleY; 485 this.outputScaleX = outputScaleX; 486 this.outputScaleY = outputScaleY; 487 notifyRescale(); 488 } 489 490 /** 491 * Return the horizontal scale used to communicate window locations, 492 * sizes, and event coordinates to/from the platform. 493 * @return the horizontal platform scaling for screen locations 494 */ 495 public final float getPlatformScaleX() { 496 return platformScaleX; 497 } 498 499 /** 500 * Return the vertical scale used to communicate window locations, 501 * sizes, and event coordinates to/from the platform. 502 * @return the vertical platform scaling for screen locations 503 */ 504 public final float getPlatformScaleY() { 505 return platformScaleY; 506 } 507 508 public void setRenderScaleX(float renderScaleX) { 509 if (!PrismSettings.allowHiDPIScaling) return; 510 this.renderScaleX = renderScaleX; 511 } 512 513 public void setRenderScaleY(float renderScaleY) { 514 if (!PrismSettings.allowHiDPIScaling) return; 515 this.renderScaleY = renderScaleY; 516 } 517 518 /** 519 * Return the horizontal scale used for rendering the back buffer. 520 * @return the horizontal scaling for rendering 521 */ 522 public final float getRenderScaleX() { 523 return renderScaleX; 524 } 525 526 /** 527 * Return the vertical scale used for rendering to the back buffer. 528 * @return the vertical scaling for rendering 529 */ 530 public final float getRenderScaleY() { 531 return renderScaleY; 532 } 533 534 public float getOutputScaleX() { 535 return outputScaleX; 536 } 537 538 public float getOutputScaleY() { 539 return outputScaleY; 540 } 541 542 protected abstract int _getEmbeddedX(long ptr); 543 protected abstract int _getEmbeddedY(long ptr); 544 545 private void checkScreenLocation() { 546 this.x = _getEmbeddedX(ptr); 547 this.y = _getEmbeddedY(ptr); 548 if ((this.x != lastKnownEmbeddedX) || (this.y != lastKnownEmbeddedY)) { 549 lastKnownEmbeddedX = this.x; 550 lastKnownEmbeddedY = this.y; 551 handleWindowEvent(System.nanoTime(), WindowEvent.MOVE); 552 } 553 } 554 555 public int getX() { 556 Application.checkEventThread(); 557 return this.x; 558 } 559 1216 protected void notifyDestroy() { 1217 // Mac is known to send multiple WillClose notifications for some reason 1218 if (this.ptr == 0) { 1219 return; 1220 } 1221 1222 handleWindowEvent(System.nanoTime(), WindowEvent.DESTROY); 1223 1224 this.ptr = 0; 1225 1226 // Do this after setting ptr to 0 to avoid a call to _setVisible() 1227 setVisible(false); 1228 } 1229 1230 protected void notifyMove(final int x, final int y) { 1231 this.x = x; 1232 this.y = y; 1233 handleWindowEvent(System.nanoTime(), WindowEvent.MOVE); 1234 } 1235 1236 protected void notifyRescale() { 1237 handleWindowEvent(System.nanoTime(), WindowEvent.RESCALE); 1238 } 1239 1240 protected void notifyMoveToAnotherScreen(Screen newScreen) { 1241 setScreen(newScreen); 1242 } 1243 1244 /** 1245 * type values: 1246 * - WindowEvent.RESIZE 1247 * - WindowEvent.MINIMIZE 1248 * - WindowEvent.MAXIMIZE 1249 * - WindowEvent.RESTORE 1250 */ 1251 protected void notifyResize(final int type, final int width, final int height) { 1252 if (type == WindowEvent.MINIMIZE) { 1253 this.state = State.MINIMIZED; 1254 } else { 1255 if (type == WindowEvent.MAXIMIZE) { 1256 this.state = State.MAXIMIZED; 1257 } else { // WindowEvent.RESIZE or WindowEvent.RESTORE 1258 this.state = State.NORMAL; 1259 } |