1 /* 2 * Copyright (c) 2012, 2014, 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 26 package com.sun.glass.ui.monocle; 27 28 import com.sun.glass.events.MouseEvent; 29 import com.sun.glass.events.ViewEvent; 30 import com.sun.glass.events.WindowEvent; 31 import com.sun.glass.ui.Application; 32 import com.sun.glass.ui.Cursor; 33 import com.sun.glass.ui.Pixels; 34 import com.sun.glass.ui.Screen; 35 import com.sun.glass.ui.View; 36 import com.sun.glass.ui.Window; 37 38 39 final class MonocleWindow extends Window { 40 41 42 private static final int STATE_NORMAL = 0; 43 private static final int STATE_MINIMIZED = 1; 44 private static final int STATE_MAXIMIZED = 2; 45 private static final int STATE_FULLSCREEN = 3; 46 47 private int id; 48 private int state; 49 private int cachedX, cachedY, cachedW, cachedH; 50 private int minW, minH; 51 private int maxW = -1; 52 private int maxH = -1; 53 54 MonocleWindow(Window owner, Screen screen, int styleMask) { 55 super(owner, screen, styleMask); 56 } 57 58 MonocleWindow(long parent) { 59 super(parent); 60 } 61 62 @Override 63 protected void _toFront(long ptr) { 64 MonocleWindowManager.getInstance().toFront(this); 65 } 66 67 @Override 68 protected void _toBack(long ptr) { 69 MonocleWindowManager.getInstance().toBack(this); 70 71 } 72 73 /** 74 * 75 * w/h is the total window width/height including all its 76 * decorations (e.g. title bar). cw/ch is the "client", or 77 * interior width/height. Negative values for w/h/cw/ch are 78 * treated as "not set". For example: setBounds(x, y, xSet, 79 * ySet, 800, 600, -1, -1) will make the window 800x600 pixels. 80 * The client area available for drawing will be smaller, e.g. 81 * 792x580 - it depends on the window decorations on different 82 * platforms. setBounds(x, y, xSet, ySet, -1, -1, 800, 600) will 83 * make the window client size to be 800x600 pixels. The area 84 * for drawing (FX scene size) will be exactly 800x600, but the 85 * total window size including decorations will be slightly 86 * bigger. For undecorated windows w/h and cw/ch are obviously 87 * the same. 88 * 89 * As this is a void function the native code should trigger an 90 * event to notify the system on actual change 91 * 92 */ 93 @Override 94 protected void _setBounds(long nativeWindowPointer, 95 int x, int y, boolean xSet, boolean ySet, 96 int w, int h, int cw, int ch, 97 float xGravity, float yGravity) { 98 int width; 99 int height; 100 101 if (w > 0) { 102 //window width surpass window content width (cw) 103 width = w; 104 } else if (cw > 0) { 105 //content width changed 106 width = cw; 107 } else { 108 //no explicit request to change width, get default 109 width = getWidth(); 110 } 111 112 if (h > 0) { 113 //window height surpass window content height(ch) 114 height = h; 115 } else if (cw > 0) { 116 //content height changed 117 height = ch; 118 } else { 119 //no explicit request to change height, get default 120 height = getHeight(); 121 } 122 if (!xSet) { 123 x = getX(); 124 } 125 if (!ySet) { 126 y = getY(); 127 } 128 if (maxW >= 0) { 129 width = Math.min(width, maxW); 130 } 131 if (maxH >= 0) { 132 height = Math.min(height, maxH); 133 } 134 width = Math.max(width, minW); 135 height = Math.max(height, minH); 136 137 notifyResizeAndMove(x, y, width, height); 138 } 139 140 private void notifyResizeAndMove(int x, int y, int width, int height) { 141 MonocleView view = (MonocleView) getView(); 142 boolean repaintView = false; 143 144 if (getWidth() != width || getHeight() != height) { 145 notifyResize(WindowEvent.RESIZE, width, height); 146 if (view != null) { 147 view.notifyResize(width, height); 148 repaintView = true; 149 } 150 } 151 if (getX() != x || getY() != y) { 152 notifyMove(x, y); 153 if (view != null) { 154 repaintView = true; 155 } 156 } 157 if (repaintView) { 158 view.notifyRepaint(); 159 } 160 } 161 162 //creates the native window 163 @Override 164 protected long _createWindow(long NativeWindow, long NativeScreen, 165 int mask) { 166 id = MonocleWindowManager.getInstance().addWindow(this); 167 return id; 168 } 169 170 @Override 171 protected long _createChildWindow(long parent) { 172 throw new UnsupportedOperationException(); 173 } 174 175 @Override 176 protected boolean _close(long nativeWindowPointer) { 177 return MonocleWindowManager.getInstance().closeWindow(this); 178 } 179 180 @Override 181 protected boolean _setView(long nativeWindowPointer, View view) { 182 boolean result = true; 183 if (view != null) { 184 // the system assumes a resize notification to set the View 185 // sizes and to get the Scene to layout correctly. 186 ((MonocleView)view).notifyResize(getWidth(), getHeight()); 187 } 188 return result; 189 } 190 191 /** 192 * Returns the handle used to create a rendering context in Prism 193 */ 194 @Override 195 public long getNativeWindow() { 196 return id; 197 } 198 199 @Override 200 protected boolean _setMenubar(long ptr, long menubarPtr) { 201 return true; 202 } 203 204 @Override 205 protected boolean _minimize(long nativeWindowPointer, boolean minimize) { 206 int x = getX(); 207 int y = getY(); 208 int width = getWidth(); 209 int height = getHeight(); 210 if (minimize && !(state == STATE_MINIMIZED)) { 211 state = STATE_MINIMIZED; 212 cachedX = x; 213 cachedY = y; 214 cachedW = width; 215 cachedH = height; 216 // remove the window from the list of visible windows in the 217 // superclass 218 remove(this); 219 notifyResize(WindowEvent.MINIMIZE, width, height); 220 221 } else if (!minimize && state == STATE_MINIMIZED) { 222 state = STATE_NORMAL; 223 x = cachedX; 224 y = cachedY; 225 width = cachedW; 226 height = cachedH; 227 // this call will add the window back into the visible list of 228 // windows in the superclass 229 add(this); 230 notifyResize(WindowEvent.RESTORE, width, height); 231 } 232 return true; 233 } 234 235 @Override 236 protected boolean _maximize(long nativeWindowPointer, boolean maximize, 237 boolean wasMaximized) { 238 NativeScreen screen = NativePlatformFactory.getNativePlatform().getScreen(); 239 int x = getX(); 240 int y = getY(); 241 int width = getWidth(); 242 int height = getHeight(); 243 if (maximize && !wasMaximized) { 244 if (state == STATE_NORMAL) { 245 cachedX = x; 246 cachedY = y; 247 cachedW = width; 248 cachedH = height; 249 } 250 if (maxW >= 0) { 251 width = maxW; 252 x = Math.min(x, screen.getWidth() - width); 253 } else { 254 x = 0; 255 width = screen.getWidth(); 256 } 257 if (maxH >= 0) { 258 height = maxH; 259 y = Math.min(y, screen.getHeight() - height); 260 } else { 261 y = 0; 262 height = screen.getHeight(); 263 } 264 state = STATE_MAXIMIZED; 265 } else if (!maximize && wasMaximized) { 266 x = cachedX; 267 y = cachedY; 268 width = cachedW; 269 height = cachedH; 270 state = STATE_NORMAL; 271 } 272 notifyResizeAndMove(x, y, width, height); 273 return true; 274 } 275 276 void setFullScreen(boolean fullscreen) { 277 NativeScreen screen = NativePlatformFactory.getNativePlatform().getScreen(); 278 int x = getX(); 279 int y = getY(); 280 int width = getWidth(); 281 int height = getHeight(); 282 if (fullscreen) { 283 if (state == STATE_NORMAL) { 284 cachedX = x; 285 cachedY = y; 286 cachedW = width; 287 cachedH = height; 288 } 289 x = 0; 290 y = 0; 291 width = screen.getWidth(); 292 height = screen.getHeight(); 293 MonocleView view = (MonocleView) getView(); 294 if (view != null) { 295 view.notifyView(ViewEvent.FULLSCREEN_ENTER); 296 } 297 state = STATE_FULLSCREEN; 298 } else { 299 x = cachedX; 300 y = cachedY; 301 width = cachedW; 302 height = cachedH; 303 MonocleView view = (MonocleView) getView(); 304 if (view != null) { 305 view.notifyView(ViewEvent.FULLSCREEN_EXIT); 306 } 307 state = STATE_NORMAL; 308 } 309 notifyResizeAndMove(x, y, width, height); 310 } 311 312 private float cachedAlpha = 1; 313 @Override 314 protected boolean _setVisible(long ptr, boolean visible) { 315 if (visible) { 316 setAlpha(cachedAlpha); 317 } else { 318 cachedAlpha = getAlpha(); 319 setAlpha(0); 320 } 321 322 return true; 323 } 324 325 @Override 326 protected boolean _setResizable(long ptr, boolean resizable){ 327 return true; 328 } 329 330 @Override 331 protected boolean _requestFocus(long ptr, int event) { 332 return MonocleWindowManager.getInstance().requestFocus(this); 333 } 334 335 @Override 336 protected void _setFocusable(long ptr, boolean isFocusable){} 337 338 @Override 339 protected boolean _setTitle(long ptr, String title) { 340 return true; 341 } 342 343 @Override 344 protected void _setLevel(long ptr, int level) {} 345 346 @Override 347 protected void _setAlpha(long ptr, float alpha) {} 348 349 @Override 350 protected boolean _setBackground(long ptr, float r, float g, float b) { 351 return true; 352 } 353 354 @Override 355 protected void _setEnabled(long ptr, boolean enabled){ 356 if (!enabled && 357 (this == MonocleWindowManager.getInstance().getFocusedWindow())) { 358 MonocleView view = (MonocleView)getView(); 359 try { 360 view.notifyMouse(MouseEvent.EXIT, MouseEvent.BUTTON_NONE, 361 0, 0, 0, 0, 0, false, false); 362 } catch (RuntimeException e) { 363 Application.reportException(e); 364 } 365 } 366 } 367 368 @Override 369 protected boolean _setMinimumSize(long ptr, int width, int height) { 370 minW = width; 371 minH = height; 372 return true; 373 } 374 375 @Override 376 protected boolean _setMaximumSize(long ptr, int width, int height) { 377 maxW = width; 378 maxH = height; 379 return true; 380 } 381 382 @Override 383 protected void _setIcon(long ptr, Pixels pixels){} 384 385 @Override 386 protected boolean _grabFocus(long ptr) { 387 return MonocleWindowManager.getInstance().grabFocus(this); 388 } 389 390 @Override 391 protected void _ungrabFocus(long ptr) { 392 MonocleWindowManager.getInstance().ungrabFocus(this); 393 } 394 395 /** 396 * The functions below are used when the platform support modality natively. 397 * Currently only GTK is using it. This functionality is disabled by 398 * default. In order to enable it this class need to override Window:: 399 * supportsPlatformModality() to return true. 400 * 401 */ 402 @Override 403 protected void _enterModal(long ptr) { 404 throw new UnsupportedOperationException(); 405 } 406 407 @Override 408 protected void _enterModalWithWindow(long dialog, long window) { 409 throw new UnsupportedOperationException(); 410 } 411 412 @Override 413 protected void _exitModal(long ptr) { 414 throw new UnsupportedOperationException(); 415 } 416 417 @Override 418 protected void notifyClose() { 419 super.notifyClose(); 420 close(); 421 } 422 423 @Override 424 protected void notifyDestroy() { 425 super.notifyDestroy(); 426 MonocleWindowManager.getInstance().repaintAll(); 427 } 428 429 @Override 430 protected void notifyFocus(int event) { 431 super.notifyFocus(event); 432 } 433 434 protected void _notifyFocusUngrab() { 435 notifyFocusUngrab(); 436 } 437 438 void _notifyFocusDisabled() { 439 notifyFocusDisabled(); 440 } 441 442 //************************************************************** 443 444 @Override protected void _setCursor(long ptr, Cursor cursor) { 445 ((MonocleCursor) cursor).applyCursor(); 446 } 447 448 @Override protected int _getEmbeddedX(long ptr) { 449 return 0; 450 } 451 @Override protected int _getEmbeddedY(long ptr) { 452 return 0; 453 } 454 455 @Override 456 protected void _requestInput(long ptr, String text, int type, double width, double height, 457 double Mxx, double Mxy, double Mxz, double Mxt, 458 double Myx, double Myy, double Myz, double Myt, 459 double Mzx, double Mzy, double Mzz, double Mzt) { 460 throw new UnsupportedOperationException("Not supported yet."); 461 } 462 463 @Override 464 protected void _releaseInput(long ptr) { 465 throw new UnsupportedOperationException("Not supported yet."); 466 } 467 468 }