Jogamp
Bug 741 HiDPI: Add ScalableSurface interface to get/set pixelScale w/ full OSX impl.
[jogl.git] / src / newt / classes / jogamp / newt / driver / macosx / WindowDriver.java
CommitLineData
a959c53b
KR
1/*
2 * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
018c7e86 3 * Copyright (c) 2010 JogAmp Community. All rights reserved.
5e9c02bc 4 *
a959c53b
KR
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
5e9c02bc 8 *
a959c53b
KR
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
5e9c02bc 11 *
a959c53b
KR
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
5e9c02bc 15 *
a959c53b
KR
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
5e9c02bc 19 *
a959c53b
KR
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
5e9c02bc 32 *
a959c53b
KR
33 */
34
4dbb8731 35package jogamp.newt.driver.macosx;
a959c53b 36
bafd9b99 37import javax.media.nativewindow.AbstractGraphicsConfiguration;
7eaeacc4
SG
38import javax.media.nativewindow.GraphicsConfigurationFactory;
39import javax.media.nativewindow.NativeWindow;
40import javax.media.nativewindow.NativeWindowException;
20bf031d 41import javax.media.nativewindow.MutableSurface;
2571ed0b 42import javax.media.nativewindow.ScalableSurface;
00bef950 43import javax.media.nativewindow.VisualIDHolder;
018c7e86 44import javax.media.nativewindow.util.Insets;
18bf27fa 45import javax.media.nativewindow.util.Point;
96c50e94 46import javax.media.nativewindow.util.PointImmutable;
a959c53b 47
2571ed0b 48import jogamp.nativewindow.SurfaceScaleUtils;
6f2f5cc9 49import jogamp.nativewindow.macosx.OSXUtil;
fcc0e739 50import jogamp.newt.PointerIconImpl;
56d60b36 51import jogamp.newt.ScreenImpl;
7eaeacc4 52import jogamp.newt.WindowImpl;
8a985f86 53import jogamp.newt.driver.DriverClearFocus;
d3df9b40 54import jogamp.newt.driver.DriverUpdatePosition;
7eaeacc4 55
646714d3 56import com.jogamp.newt.event.InputEvent;
7eaeacc4 57import com.jogamp.newt.event.KeyEvent;
56d60b36
SG
58import com.jogamp.newt.event.MonitorEvent;
59import com.jogamp.opengl.math.FloatUtil;
7eaeacc4 60
a694cadc 61public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
5e9c02bc 62
a959c53b 63 static {
a694cadc 64 DisplayDriver.initSingleton();
a959c53b
KR
65 }
66
a694cadc 67 public WindowDriver() {
56d60b36
SG
68 }
69
2571ed0b
SG
70 private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float pixelScaleRaw) {
71 final int[] pixelScaleInt;
72 {
73 final int ps = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int) pixelScaleRaw;
74 pixelScaleInt = new int[] { ps, ps };
56d60b36 75 }
2571ed0b
SG
76
77 if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
56d60b36 78 if( sendEvent ) {
d149c554 79 super.sizeChanged(defer, getWidth(), getHeight(), true);
56d60b36 80 } else {
d149c554 81 defineSize(getWidth(), getHeight());
56d60b36 82 }
2571ed0b
SG
83 return true;
84 } else {
85 return false;
56d60b36 86 }
56d60b36
SG
87 }
88
89 private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) {
90 final float newPixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex());
91 if( DEBUG_IMPLEMENTATION ) {
2571ed0b 92 System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+" -> "+newPixelScaleRaw);
56d60b36
SG
93 }
94 return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw);
95 }
96
97 private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
2571ed0b
SG
98 final long handle = getWindowHandle();
99 if( 0 != handle ) {
100 final float newPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle);
56d60b36 101 if( DEBUG_IMPLEMENTATION ) {
2571ed0b 102 System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+" -> "+newPixelScaleRaw);
56d60b36
SG
103 }
104 return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw);
105 } else {
106 return false;
107 }
108 }
109
110 /** Called from native code */
111 protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw) {
112 final long handle = getWindowHandle();
2571ed0b
SG
113 if( DEBUG_IMPLEMENTATION ) {
114 System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), drop "+(0==handle));
115 }
56d60b36 116 if( 0 != handle ) {
56d60b36
SG
117 updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw);
118 }
119 }
120
121 @Override
122 protected final void instantiationFinished() {
123 updatePixelScaleByScreenIdx(false /* sendEvent*/);
124 }
125
126 @Override
127 protected void setScreen(ScreenImpl newScreen) { // never null !
128 super.setScreen(newScreen);
129 updatePixelScaleByScreenIdx(false /* sendEvent*/); // caller (reparent, ..) will send reshape event
130 }
131
2790c756
SG
132 @Override
133 protected void monitorModeChanged(MonitorEvent me, boolean success) {
134 updatePixelScaleByWindowHandle(false /* sendEvent*/); // send reshape event itself
135 }
56d60b36
SG
136
137 @Override
2571ed0b
SG
138 public final void setSurfaceScale(final int[] pixelScale) {
139 SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null);
140
141 final int[] resPixelScale;
142 if( isNativeValid() ) {
143 if( isOffscreenInstance ) {
144 final NativeWindow pWin = getParent();
145 if( pWin instanceof ScalableSurface ) {
146 final ScalableSurface sSurf = (ScalableSurface)pWin;
147 sSurf.setSurfaceScale(reqPixelScale);
148 final int[] pPixelScale = sSurf.getSurfaceScale(new int[2]);
149 updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0]); // HiDPI: uniformPixelScale
150 } else {
151 // just notify updated pixelScale if offscreen
152 SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale);
153 updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0]); // HiDPI: uniformPixelScale
154 }
155 } else {
156 // set pixelScale in native code, will issue an update PixelScale
157 OSXUtil.RunOnMainThread(true, new Runnable() {
158 @Override
159 public void run() {
160 setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale
161 }
162 } );
163 }
164 resPixelScale = hasPixelScale;
165 } else {
166 hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
167 hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
168 resPixelScale = reqPixelScale;
169 }
170 if( DEBUG_IMPLEMENTATION ) {
171 System.err.println("WindowDriver.setPixelScale: "+pixelScale[0]+"x"+pixelScale[1]+" (req) -> "+
172 reqPixelScale[0]+"x"+reqPixelScale[1]+" (validated) -> "+
173 resPixelScale[0]+"x"+resPixelScale[1]+" (result) - realized "+isNativeValid());
174 }
a959c53b 175 }
5e9c02bc 176
5d6cbbcc 177 @Override
6e599a26 178 protected void createNativeImpl() {
00bef950
SG
179 final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
180 capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
bafd9b99 181 if (null == cfg) {
a959c53b
KR
182 throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
183 }
bafd9b99 184 setGraphicsConfiguration(cfg);
d149c554 185 reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
187e0b76
SG
186 if (0 == getWindowHandle()) {
187 throw new NativeWindowException("Error creating window");
188 }
a959c53b
KR
189 }
190
5d6cbbcc 191 @Override
63be4a40 192 protected void closeNativeImpl() {
ede9386d 193 try {
b32c65e2 194 if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
5e9c02bc 195 final long handle = getWindowHandle();
9dcd8bba 196 visibleChanged(true, false);
4e0eb391
SG
197 setWindowHandle(0);
198 surfaceHandle = 0;
199 sscSurfaceHandle = 0;
9dcd8bba 200 isOffscreenInstance = false;
4e0eb391 201 if (0 != handle) {
88291cd5 202 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 203 @Override
8edaa978
SG
204 public void run() {
205 close0( handle );
206 } } );
a959c53b 207 }
ede9386d 208 } catch (Throwable t) {
5e9c02bc 209 if(DEBUG_IMPLEMENTATION) {
77413854 210 Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
ede9386d
SG
211 e.printStackTrace();
212 }
a959c53b
KR
213 }
214 }
5e9c02bc 215
10c696f7 216 @Override
7eaeacc4 217 protected int lockSurfaceImpl() {
5e9c02bc 218 /**
81cbcdc8
SG
219 * if( isOffscreenInstance ) {
220 * return LOCK_SUCCESS;
221 * }
222 */
223 final long w = getWindowHandle();
224 final long v = surfaceHandle;
225 if( 0 != v && 0 != w ) {
226 return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
8a985f86 227 }
81cbcdc8 228 return LOCK_SURFACE_NOT_READY;
7eaeacc4
SG
229 }
230
231 @Override
232 protected void unlockSurfaceImpl() {
5e9c02bc 233 /**
81cbcdc8
SG
234 * if( isOffscreenInstance ) {
235 * return;
236 * }
237 */
238 final long w = getWindowHandle();
239 final long v = surfaceHandle;
240 if(0 != w && 0 != v) {
241 if( !unlockSurface0(w, v) ) {
242 throw new NativeWindowException("Failed to unlock surface, probably not locked!");
d10c7916 243 }
8a985f86 244 }
7eaeacc4 245 }
5e9c02bc 246
7eaeacc4 247 @Override
0feca163 248 public final long getSurfaceHandle() {
7e81956d 249 return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
a959c53b
KR
250 }
251
4dd44b98 252 @Override
7e81956d
SG
253 public void setSurfaceHandle(long surfaceHandle) {
254 if(DEBUG_IMPLEMENTATION) {
255 System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
256 }
257 sscSurfaceHandle = surfaceHandle;
258 if (isNativeValid()) {
259 if (0 != sscSurfaceHandle) {
1a1557cd 260 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 261 @Override
1a1557cd
SG
262 public void run() {
263 orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
264 } } );
5e9c02bc 265 } /** this is done by recreation!
7e81956d 266 else if (isVisible()){
1a1557cd
SG
267 OSXUtil.RunOnMainThread(false, new Runnable() {
268 public void run() {
269 orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
270 } } );
7e81956d 271 } */
5e9c02bc 272 }
7e81956d
SG
273 }
274
10c696f7 275 @Override
1d333a77 276 protected void setTitleImpl(final String title) {
88291cd5 277 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 278 @Override
88291cd5
SG
279 public void run() {
280 setTitle0(getWindowHandle(), title);
281 } } );
a959c53b 282 }
a959c53b 283
7d5c51b6 284 @Override
1a1557cd 285 protected void requestFocusImpl(final boolean force) {
0237bde0
SG
286 final boolean _isFullscreen = isFullscreen();
287 final boolean _isOffscreenInstance = isOffscreenInstance;
88291cd5 288 if(DEBUG_IMPLEMENTATION) {
0237bde0 289 System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
88291cd5 290 }
0237bde0 291 if(!_isOffscreenInstance) {
1a1557cd 292 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 293 @Override
1a1557cd
SG
294 public void run() {
295 requestFocus0(getWindowHandle(), force);
0237bde0
SG
296 if(_isFullscreen) {
297 // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
298 focusChanged(false, true);
299 }
1a1557cd 300 } } );
8a985f86
SG
301 } else {
302 focusChanged(false, true);
303 }
304 }
5e9c02bc 305
7d5c51b6 306 @Override
8a985f86
SG
307 public final void clearFocus() {
308 if(DEBUG_IMPLEMENTATION) {
6f2f5cc9 309 System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
8a985f86
SG
310 }
311 if(!isOffscreenInstance) {
1a1557cd 312 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 313 @Override
1a1557cd
SG
314 public void run() {
315 resignFocus0(getWindowHandle());
316 } } );
8a985f86
SG
317 } else {
318 focusChanged(false, false);
319 }
a959c53b 320 }
5e9c02bc 321
ec50802d 322 private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
5e9c02bc 323
7d5c51b6 324 @Override
ec50802d 325 public void updatePosition(int x, int y) {
af384deb
SG
326 final long handle = getWindowHandle();
327 if( 0 != handle && !isOffscreenInstance ) {
ec50802d
SG
328 final NativeWindow parent = getParent();
329 final boolean useParent = useParent(parent);
330 final int pX=parent.getX(), pY=parent.getY();
331 final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
af384deb 332 if(DEBUG_IMPLEMENTATION) {
ec50802d 333 System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
af384deb 334 }
81cbcdc8 335 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 336 @Override
81cbcdc8 337 public void run() {
ec50802d 338 setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
81cbcdc8 339 } } );
af384deb 340 // no native event (fullscreen, some reparenting)
ec50802d 341 positionChanged(true, x, y);
d3df9b40 342 }
5e9c02bc
HH
343 }
344
af384deb
SG
345 @Override
346 protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
347 final long handle = getWindowHandle();
348 if( 0 != handle && !isOffscreenInstance ) {
349 final NativeWindow parent = getParent();
ec50802d 350 final boolean useParent = useParent(parent);
d149c554 351 if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
ec50802d
SG
352 final int x=getX(), y=getY();
353 final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
af384deb 354 if(DEBUG_IMPLEMENTATION) {
ec50802d 355 System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos");
af384deb 356 }
81cbcdc8 357 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 358 @Override
81cbcdc8 359 public void run() {
ec50802d 360 setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
81cbcdc8 361 } } );
af384deb
SG
362 }
363 }
364 super.sizeChanged(defer, newWidth, newHeight, force);
365 }
5e9c02bc 366
af384deb 367 @Override
56d60b36 368 protected boolean reconfigureWindowImpl(int x, int y, final int width, final int height, int flags) {
4dd44b98
SG
369 final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
370 isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
7d5c51b6
SG
371 final PointImmutable pClientLevelOnSreen;
372 if( isOffscreenInstance ) {
56d60b36 373 x = 0; y = 0;
7d5c51b6
SG
374 pClientLevelOnSreen = new Point(0, 0);
375 } else {
af384deb 376 final NativeWindow parent = getParent();
ec50802d 377 final boolean useParent = useParent(parent);
af384deb 378 if( useParent ) {
ec50802d 379 pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
5e9c02bc 380 } else {
af384deb
SG
381 pClientLevelOnSreen = new Point(x, y);
382 }
7d5c51b6 383 }
5e9c02bc 384
2571ed0b
SG
385 final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
386 final boolean hasFocus = hasFocus();
387
fa35bd75 388 if(DEBUG_IMPLEMENTATION) {
4dd44b98
SG
389 final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
390 final NativeWindow pWin = getParent();
391 final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
7d5c51b6 392 System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
4dd44b98
SG
393 ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
394 ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
395 ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
396 ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
397 ", ioi: "+_isOffscreenInstance+
398 ") -> "+isOffscreenInstance+
2571ed0b 399 "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus);
81cbcdc8 400 // Thread.dumpStack();
fa35bd75 401 }
5e9c02bc 402
ec50802d 403 if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
d3df9b40 404 if ( !isOffscreenInstance ) {
1a1557cd 405 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 406 @Override
1a1557cd
SG
407 public void run() {
408 orderOut0(getWindowHandle());
409 visibleChanged(true, false);
410 } } );
411 } else {
412 visibleChanged(true, false);
fa35bd75 413 }
d3df9b40 414 }
ec50802d 415 if( 0 == getWindowHandle() && setVisible ||
d3df9b40
SG
416 0 != ( FLAG_CHANGE_DECORATION & flags) ||
417 0 != ( FLAG_CHANGE_PARENTING & flags) ||
418 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
4dd44b98 419 if(isOffscreenInstance) {
fcd59768 420 createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
4dd44b98 421 } else {
fcd59768 422 createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
1a1557cd
SG
423 0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
424 }
fcd59768
SG
425 // no native event (fullscreen, some reparenting)
426 positionChanged(false, x, y);
427 updatePixelScaleByWindowHandle(false /* sendEvent */);
428 super.sizeChanged(false, width, height, true);
429 visibleChanged(false, setVisible);
2571ed0b
SG
430 if( hasFocus ) {
431 requestFocusImpl(true);
432 }
1a1557cd 433 } else {
5e9c02bc 434 if( width>0 && height>0 ) {
1a1557cd
SG
435 if( !isOffscreenInstance ) {
436 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 437 @Override
1a1557cd 438 public void run() {
ec50802d 439 setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
1a1557cd
SG
440 } } );
441 } // else offscreen size is realized via recreation
442 // no native event (fullscreen, some reparenting)
443 positionChanged(true, x, y);
56d60b36 444 super.sizeChanged(true, width, height, false);
1a1557cd 445 }
ec50802d 446 if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
5e9c02bc 447 if( !isOffscreenInstance ) {
1a1557cd 448 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 449 @Override
1a1557cd
SG
450 public void run() {
451 orderFront0(getWindowHandle());
452 visibleChanged(true, true);
453 } } );
454 } else {
455 visibleChanged(true, true);
456 }
4dd44b98 457 }
81cbcdc8 458 if( !isOffscreenInstance ) {
1a1557cd 459 setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
7e81956d 460 }
ede9386d 461 }
7d5c51b6 462 if(DEBUG_IMPLEMENTATION) {
5e9c02bc 463 System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());
7d5c51b6 464 }
18bf27fa
SG
465 return true;
466 }
467
af384deb 468 @Override
18bf27fa 469 protected Point getLocationOnScreenImpl(int x, int y) {
6f2f5cc9 470 final NativeWindow parent = getParent();
ec50802d
SG
471 final boolean useParent = useParent(parent);
472 return getLocationOnScreenImpl(x, y, parent, useParent);
473 }
5e9c02bc 474
ec50802d 475 private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
6f2f5cc9 476 if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
759d9067 477 return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y);
6f2f5cc9 478 }
5e9c02bc 479
6f2f5cc9 480 final Point p = new Point(x, y);
6f2f5cc9 481 if( useParent ) {
ec50802d 482 p.translate( parent.getLocationOnScreen(null) );
d3df9b40 483 }
6f2f5cc9 484 return p;
a959c53b 485 }
5e9c02bc 486
af384deb 487 @Override
d4670328
SG
488 protected void updateInsetsImpl(Insets insets) {
489 // nop - using event driven insetsChange(..)
29b675c2 490 }
5e9c02bc 491
7d5c51b6 492 /** Callback for native screen position change event of the client area. */
5e9c02bc 493 protected void screenPositionChanged(boolean defer, int newX, int newY) {
ebfaa126 494 // passed coordinates are in screen position of the client area
5e9c02bc 495 if(getWindowHandle()!=0) {
ebfaa126 496 final NativeWindow parent = getParent();
81cbcdc8
SG
497 if( null == parent || isOffscreenInstance ) {
498 if(DEBUG_IMPLEMENTATION) {
499 System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
500 }
7d5c51b6
SG
501 positionChanged(defer, newX, newY);
502 } else {
503 // screen position -> rel child window position
5e9c02bc 504 Point absPos = new Point(newX, newY);
81cbcdc8
SG
505 Point parentOnScreen = parent.getLocationOnScreen(null);
506 absPos.translate( parentOnScreen.scale(-1, -1) );
507 if(DEBUG_IMPLEMENTATION) {
508 System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
509 }
7d5c51b6 510 positionChanged(defer, absPos.getX(), absPos.getY());
ebfaa126 511 }
81cbcdc8
SG
512 } else if(DEBUG_IMPLEMENTATION) {
513 System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
ebfaa126 514 }
aeffc47f 515 }
5e9c02bc 516
aeffc47f 517 @Override
e7ffa68b 518 protected void setPointerIconImpl(final PointerIconImpl pi) {
fcc0e739
SG
519 if( !isOffscreenInstance ) {
520 final long piHandle = null != pi ? pi.validatedHandle() : 0;
521 OSXUtil.RunOnMainThread(true, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle !
522 @Override
523 public void run() {
69b5adb3 524 setPointerIcon0(getWindowHandle(), piHandle);
fcc0e739 525 } } );
bec29cf9 526 }
e7ffa68b
SG
527 }
528
529 @Override
aeffc47f 530 protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
5e9c02bc 531 if( !isOffscreenInstance ) {
fcc0e739
SG
532 OSXUtil.RunOnMainThread(false, new Runnable() {
533 @Override
534 public void run() {
69b5adb3 535 setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
fcc0e739 536 } } );
58756bbd 537 return true;
bec29cf9 538 }
8a985f86 539 return false;
aeffc47f
SG
540 }
541
542 @Override
543 protected boolean confinePointerImpl(final boolean confine) {
5e9c02bc 544 if( !isOffscreenInstance ) {
69b5adb3
SG
545 confinePointer0(getWindowHandle(), confine);
546 return true;
21439c34 547 } // else may need offscreen solution ? FIXME
8a985f86 548 return false;
aeffc47f 549 }
5e9c02bc 550
aeffc47f
SG
551 @Override
552 protected void warpPointerImpl(final int x, final int y) {
5e9c02bc 553 if( !isOffscreenInstance ) {
56d60b36 554 warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY());
21439c34 555 } // else may need offscreen solution ? FIXME
aeffc47f 556 }
5e9c02bc 557
85338858 558 @Override
56d60b36
SG
559 protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
560 final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
561 super.doMouseEvent(enqueue, wait, eventType, modifiers, x * getPixelScaleX(), y * getPixelScaleY(), button, rotationXYZ, rotationScale);
562 }
563
564 @Override
85338858
SG
565 public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
566 throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
e8f45dad 567 }
5e9c02bc 568
85338858 569 @Override
d2fc229b 570 public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, short _keySym, char keyChar) {
5e9c02bc 571 throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
d2fc229b 572 }
5e9c02bc 573
d2fc229b 574 protected final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, char keyChar, char keySymChar) {
aeffc47f
SG
575 // Note that we send the key char for the key code on this
576 // platform -- we do not get any useful key codes out of the system
85338858 577 final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
d2fc229b
SG
578 final short keySym;
579 {
b13868b6 580 short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
d2fc229b
SG
581 keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
582 }
88291cd5
SG
583 /**
584 {
85338858 585 final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
d2fc229b
SG
586 System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
587 ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
588 ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
589 ", mods "+toHexString(modifiers)+
88291cd5
SG
590 ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
591 ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
85338858 592 } */
5e9c02bc 593
bdfb7481
SG
594 // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
595 // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
bc933c6e 596 switch(eventType) {
bc933c6e 597 case KeyEvent.EVENT_KEY_RELEASED:
70d58b03 598 if( isKeyCodeTracked(keyCode) ) {
b13868b6 599 setKeyPressed(keyCode, false);
2f9c77a3 600 }
2f9c77a3
SG
601 break;
602 case KeyEvent.EVENT_KEY_PRESSED:
70d58b03 603 if( isKeyCodeTracked(keyCode) ) {
b13868b6 604 if( setKeyPressed(keyCode, true) ) {
70d58b03 605 // key was already pressed
70d58b03 606 modifiers |= InputEvent.AUTOREPEAT_MASK;
d2fc229b 607 super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
2f9c77a3 608 }
2f9c77a3 609 }
2f9c77a3 610 break;
bc933c6e 611 }
d2fc229b 612 super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
2f9c77a3 613 }
bc933c6e 614
aeffc47f
SG
615 //----------------------------------------------------------------------
616 // Internals only
5e9c02bc
HH
617 //
618
619 private void createWindow(final boolean offscreenInstance, final boolean recreate,
fcd59768
SG
620 final PointImmutable pS, final int width, final int height,
621 final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
ede9386d 622
c2a4905e
SG
623 final long parentWinHandle = getParentWindowHandle();
624 final long preWinHandle = getWindowHandle();
5e9c02bc 625
1a1557cd
SG
626 if(DEBUG_IMPLEMENTATION) {
627 System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
628 ": offscreen "+offscreenInstance+", recreate "+recreate+
629 ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
c2a4905e
SG
630 ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
631 ", surfaceHandle "+toHexString(surfaceHandle));
1a1557cd
SG
632 // Thread.dumpStack();
633 }
ede9386d
SG
634
635 try {
c2a4905e 636 if( 0 != preWinHandle ) {
e5ab9757 637 setWindowHandle(0);
81cbcdc8
SG
638 if( 0 == surfaceHandle ) {
639 throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
5e9c02bc 640 }
88291cd5 641 OSXUtil.RunOnMainThread(false, new Runnable() {
f1ae8ddb 642 @Override
81cbcdc8 643 public void run() {
c2a4905e
SG
644 changeContentView0(parentWinHandle, preWinHandle, 0);
645 close0( preWinHandle );
81cbcdc8 646 } } );
e5ab9757 647 } else {
81cbcdc8
SG
648 if( 0 != surfaceHandle ) {
649 throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
5e9c02bc 650 }
2571ed0b 651 surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
81cbcdc8
SG
652 if( 0 == surfaceHandle ) {
653 throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
654 }
e5ab9757 655 }
5e9c02bc
HH
656
657 final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
81cbcdc8
SG
658 ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
659 NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
6ebf649d 660 NSBackingStoreBuffered, surfaceHandle);
81cbcdc8
SG
661 if ( newWin == 0 ) {
662 throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
7e81956d 663 }
81cbcdc8 664 setWindowHandle( newWin );
5e9c02bc 665
81cbcdc8 666 final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
5e9c02bc 667 // Blocking initialization on main-thread!
c2a4905e 668 OSXUtil.RunOnMainThread(true, new Runnable() {
f1ae8ddb 669 @Override
81cbcdc8 670 public void run() {
2571ed0b 671 initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
0237bde0 672 isOpaque, visible && !offscreenInstance, surfaceHandle);
81cbcdc8 673 if( offscreenInstance ) {
c2a4905e 674 orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
81cbcdc8
SG
675 } else {
676 setTitle0(newWin, getTitle());
1a1557cd 677 setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
81cbcdc8
SG
678 }
679 } } );
ede9386d
SG
680 } catch (Exception ie) {
681 ie.printStackTrace();
a959c53b 682 }
e5ab9757 683 }
5e9c02bc 684
6e599a26 685 protected static native boolean initIDs0();
2571ed0b 686 private native long createView0(int x, int y, int w, int h);
6ebf649d 687 private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
8edaa978 688 /** Must be called on Main-Thread */
2571ed0b 689 private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale,
56d60b36 690 boolean opaque, boolean visible, long view);
2571ed0b 691 private native void setPixelScale0(long window, long view, float reqPixelScale);
81cbcdc8
SG
692 private native boolean lockSurface0(long window, long view);
693 private native boolean unlockSurface0(long window, long view);
1a1557cd 694 /** Must be called on Main-Thread */
cac4e2e3 695 private native void requestFocus0(long window, boolean force);
1a1557cd 696 /** Must be called on Main-Thread */
7bb5885f 697 private native void resignFocus0(long window);
ec50802d 698 /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
6e599a26 699 private native void orderOut0(long window);
1a1557cd 700 /** Must be called on Main-Thread */
cac4e2e3 701 private native void orderFront0(long window);
8edaa978 702 /** Must be called on Main-Thread */
a959c53b 703 private native void close0(long window);
1a1557cd 704 /** Must be called on Main-Thread */
a959c53b 705 private native void setTitle0(long window, String title);
6e599a26 706 private native long contentView0(long window);
8edaa978 707 /** Must be called on Main-Thread */
81cbcdc8 708 private native void changeContentView0(long parentWindowOrView, long window, long view);
1a1557cd 709 /** Must be called on Main-Thread */
ec50802d 710 private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
5e9c02bc 711 /** Must be called on Main-Thread */
ec50802d 712 private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
1a1557cd 713 /** Must be called on Main-Thread */
e5ab9757 714 private native void setAlwaysOnTop0(long window, boolean atop);
7b8e2ef5 715 private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
69b5adb3
SG
716 private static native void setPointerIcon0(long windowHandle, long handle);
717 private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
718 private static native void confinePointer0(long windowHandle, boolean confine);
719 private static native void warpPointer0(long windowHandle, int x, int y);
5e9c02bc 720
8a985f86
SG
721 // Window styles
722 private static final int NSBorderlessWindowMask = 0;
723 private static final int NSTitledWindowMask = 1 << 0;
724 private static final int NSClosableWindowMask = 1 << 1;
725 private static final int NSMiniaturizableWindowMask = 1 << 2;
726 private static final int NSResizableWindowMask = 1 << 3;
727
728 // Window backing store types
729 private static final int NSBackingStoreRetained = 0;
730 private static final int NSBackingStoreNonretained = 1;
731 private static final int NSBackingStoreBuffered = 2;
732
04707d3c
SG
733 private volatile long surfaceHandle = 0;
734 private long sscSurfaceHandle = 0;
735 private boolean isOffscreenInstance = false;
5e9c02bc 736
a959c53b 737}
http://JogAmp.org git info: FAQ, tutorial and man pages.