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
1 /*
2  * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * Copyright (c) 2010 JogAmp Community. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * - Redistribution of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
32  *
33  */
34
35 package jogamp.newt.driver.macosx;
36
37 import javax.media.nativewindow.AbstractGraphicsConfiguration;
38 import javax.media.nativewindow.GraphicsConfigurationFactory;
39 import javax.media.nativewindow.NativeWindow;
40 import javax.media.nativewindow.NativeWindowException;
41 import javax.media.nativewindow.MutableSurface;
42 import javax.media.nativewindow.ScalableSurface;
43 import javax.media.nativewindow.VisualIDHolder;
44 import javax.media.nativewindow.util.Insets;
45 import javax.media.nativewindow.util.Point;
46 import javax.media.nativewindow.util.PointImmutable;
47
48 import jogamp.nativewindow.SurfaceScaleUtils;
49 import jogamp.nativewindow.macosx.OSXUtil;
50 import jogamp.newt.PointerIconImpl;
51 import jogamp.newt.ScreenImpl;
52 import jogamp.newt.WindowImpl;
53 import jogamp.newt.driver.DriverClearFocus;
54 import jogamp.newt.driver.DriverUpdatePosition;
55
56 import com.jogamp.newt.event.InputEvent;
57 import com.jogamp.newt.event.KeyEvent;
58 import com.jogamp.newt.event.MonitorEvent;
59 import com.jogamp.opengl.math.FloatUtil;
60
61 public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
62
63     static {
64         DisplayDriver.initSingleton();
65     }
66
67     public WindowDriver() {
68     }
69
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 };
75         }
76
77         if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
78             if( sendEvent ) {
79                 super.sizeChanged(defer, getWidth(), getHeight(), true);
80             } else {
81                 defineSize(getWidth(), getHeight());
82             }
83             return true;
84         } else {
85             return false;
86         }
87     }
88
89     private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) {
90         final float newPixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex());
91         if( DEBUG_IMPLEMENTATION ) {
92             System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+" -> "+newPixelScaleRaw);
93         }
94         return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw);
95     }
96
97     private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
98         final long handle = getWindowHandle();
99         if( 0 != handle ) {
100             final float newPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle);
101             if( DEBUG_IMPLEMENTATION ) {
102                 System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+" -> "+newPixelScaleRaw);
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();
113         if( DEBUG_IMPLEMENTATION ) {
114             System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), drop "+(0==handle));
115         }
116         if( 0 != handle ) {
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
132     @Override
133     protected void monitorModeChanged(MonitorEvent me, boolean success) {
134         updatePixelScaleByWindowHandle(false /* sendEvent*/); // send reshape event itself
135     }
136
137     @Override
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         }
175     }
176
177     @Override
178     protected void createNativeImpl() {
179         final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
180                 capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
181         if (null == cfg) {
182             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
183         }
184         setGraphicsConfiguration(cfg);
185         reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
186         if (0 == getWindowHandle()) {
187             throw new NativeWindowException("Error creating window");
188         }
189     }
190
191     @Override
192     protected void closeNativeImpl() {
193         try {
194             if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
195             final long handle = getWindowHandle();
196             visibleChanged(true, false);
197             setWindowHandle(0);
198             surfaceHandle = 0;
199             sscSurfaceHandle = 0;
200             isOffscreenInstance = false;
201             if (0 != handle) {
202                 OSXUtil.RunOnMainThread(false, new Runnable() {
203                    @Override
204                    public void run() {
205                        close0( handle );
206                    } } );
207             }
208         } catch (Throwable t) {
209             if(DEBUG_IMPLEMENTATION) {
210                 Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
211                 e.printStackTrace();
212             }
213         }
214     }
215
216     @Override
217     protected int lockSurfaceImpl() {
218         /**
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;
227         }
228         return LOCK_SURFACE_NOT_READY;
229     }
230
231     @Override
232     protected void unlockSurfaceImpl() {
233         /**
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!");
243             }
244         }
245     }
246
247     @Override
248     public final long getSurfaceHandle() {
249         return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
250     }
251
252     @Override
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) {
260                 OSXUtil.RunOnMainThread(false, new Runnable() {
261                     @Override
262                     public void run() {
263                         orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
264                     } } );
265             } /** this is done by recreation!
266               else if (isVisible()){
267                 OSXUtil.RunOnMainThread(false, new Runnable() {
268                     public void run() {
269                         orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
270                     } } );
271             } */
272         }
273     }
274
275     @Override
276     protected void setTitleImpl(final String title) {
277         OSXUtil.RunOnMainThread(false, new Runnable() {
278             @Override
279             public void run() {
280                 setTitle0(getWindowHandle(), title);
281             } } );
282     }
283
284     @Override
285     protected void requestFocusImpl(final boolean force) {
286         final boolean _isFullscreen = isFullscreen();
287         final boolean _isOffscreenInstance = isOffscreenInstance;
288         if(DEBUG_IMPLEMENTATION) {
289             System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
290         }
291         if(!_isOffscreenInstance) {
292             OSXUtil.RunOnMainThread(false, new Runnable() {
293                 @Override
294                 public void run() {
295                     requestFocus0(getWindowHandle(), force);
296                     if(_isFullscreen) {
297                         // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
298                         focusChanged(false, true);
299                     }
300                 } } );
301         } else {
302             focusChanged(false, true);
303         }
304     }
305
306     @Override
307     public final void clearFocus() {
308         if(DEBUG_IMPLEMENTATION) {
309             System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
310         }
311         if(!isOffscreenInstance) {
312             OSXUtil.RunOnMainThread(false, new Runnable() {
313                 @Override
314                 public void run() {
315                     resignFocus0(getWindowHandle());
316                 } } );
317         } else {
318             focusChanged(false, false);
319         }
320     }
321
322     private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
323
324     @Override
325     public void updatePosition(int x, int y) {
326         final long handle = getWindowHandle();
327         if( 0 != handle && !isOffscreenInstance ) {
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);
332             if(DEBUG_IMPLEMENTATION) {
333                 System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" ->  "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
334             }
335             OSXUtil.RunOnMainThread(false, new Runnable() {
336                 @Override
337                 public void run() {
338                     setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
339                 } } );
340             // no native event (fullscreen, some reparenting)
341             positionChanged(true, x, y);
342         }
343     }
344
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();
350             final boolean useParent = useParent(parent);
351             if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
352                 final int x=getX(), y=getY();
353                 final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
354                 if(DEBUG_IMPLEMENTATION) {
355                     System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" ->  "+p0S+" screen-client-pos");
356                 }
357                 OSXUtil.RunOnMainThread(false, new Runnable() {
358                     @Override
359                     public void run() {
360                         setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
361                     } } );
362             }
363         }
364         super.sizeChanged(defer, newWidth, newHeight, force);
365     }
366
367     @Override
368     protected boolean reconfigureWindowImpl(int x, int y, final int width, final int height, int flags) {
369         final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
370         isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
371         final PointImmutable pClientLevelOnSreen;
372         if( isOffscreenInstance ) {
373             x = 0; y = 0;
374             pClientLevelOnSreen = new Point(0, 0);
375         } else  {
376             final NativeWindow parent = getParent();
377             final boolean useParent = useParent(parent);
378             if( useParent ) {
379                 pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
380             } else {
381                 pClientLevelOnSreen = new Point(x, y);
382             }
383         }
384
385         final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
386         final boolean hasFocus = hasFocus();
387
388         if(DEBUG_IMPLEMENTATION) {
389             final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
390             final NativeWindow pWin = getParent();
391             final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
392             System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
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+
399                                "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus);
400             // Thread.dumpStack();
401         }
402
403         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
404             if ( !isOffscreenInstance ) {
405                 OSXUtil.RunOnMainThread(false, new Runnable() {
406                     @Override
407                     public void run() {
408                         orderOut0(getWindowHandle());
409                         visibleChanged(true, false);
410                     } } );
411             } else {
412                 visibleChanged(true, false);
413             }
414         }
415         if( 0 == getWindowHandle() && setVisible ||
416             0 != ( FLAG_CHANGE_DECORATION & flags) ||
417             0 != ( FLAG_CHANGE_PARENTING & flags) ||
418             0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
419             if(isOffscreenInstance) {
420                 createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
421             } else {
422                 createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
423                                     0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
424             }
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);
430             if( hasFocus ) {
431                 requestFocusImpl(true);
432             }
433         } else {
434             if( width>0 && height>0 ) {
435                 if( !isOffscreenInstance ) {
436                     OSXUtil.RunOnMainThread(false, new Runnable() {
437                         @Override
438                         public void run() {
439                             setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
440                         } } );
441                 } // else offscreen size is realized via recreation
442                 // no native event (fullscreen, some reparenting)
443                 positionChanged(true,  x, y);
444                 super.sizeChanged(true, width, height, false);
445             }
446             if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
447                 if( !isOffscreenInstance ) {
448                     OSXUtil.RunOnMainThread(false, new Runnable() {
449                         @Override
450                         public void run() {
451                             orderFront0(getWindowHandle());
452                             visibleChanged(true, true);
453                         } } );
454                 } else {
455                     visibleChanged(true, true);
456                 }
457             }
458             if( !isOffscreenInstance ) {
459                 setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
460             }
461         }
462         if(DEBUG_IMPLEMENTATION) {
463             System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());
464         }
465         return true;
466     }
467
468     @Override
469     protected Point getLocationOnScreenImpl(int x, int y) {
470         final NativeWindow parent = getParent();
471         final boolean useParent = useParent(parent);
472         return getLocationOnScreenImpl(x, y, parent, useParent);
473     }
474
475     private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
476         if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
477             return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y);
478         }
479
480         final Point p = new Point(x, y);
481         if( useParent ) {
482             p.translate( parent.getLocationOnScreen(null) );
483         }
484         return p;
485     }
486
487     @Override
488     protected void updateInsetsImpl(Insets insets) {
489         // nop - using event driven insetsChange(..)
490     }
491
492     /** Callback for native screen position change event of the client area. */
493     protected void screenPositionChanged(boolean defer, int newX, int newY) {
494         // passed coordinates are in screen position of the client area
495         if(getWindowHandle()!=0) {
496             final NativeWindow parent = getParent();
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                 }
501                 positionChanged(defer, newX, newY);
502             } else {
503                 // screen position -> rel child window position
504                 Point absPos = new Point(newX, newY);
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                 }
510                 positionChanged(defer, absPos.getX(), absPos.getY());
511             }
512         } else if(DEBUG_IMPLEMENTATION) {
513             System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
514         }
515     }
516
517     @Override
518     protected void setPointerIconImpl(final PointerIconImpl pi) {
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() {
524                     setPointerIcon0(getWindowHandle(), piHandle);
525                 } } );
526         }
527     }
528
529     @Override
530     protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
531         if( !isOffscreenInstance ) {
532             OSXUtil.RunOnMainThread(false, new Runnable() {
533                 @Override
534                 public void run() {
535                     setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
536                 } } );
537             return true;
538         }
539         return false;
540     }
541
542     @Override
543     protected boolean confinePointerImpl(final boolean confine) {
544         if( !isOffscreenInstance ) {
545             confinePointer0(getWindowHandle(), confine);
546             return true;
547         } // else may need offscreen solution ? FIXME
548         return false;
549     }
550
551     @Override
552     protected void warpPointerImpl(final int x, final int y) {
553         if( !isOffscreenInstance ) {
554             warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY());
555         } // else may need offscreen solution ? FIXME
556     }
557
558     @Override
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
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");
567     }
568
569     @Override
570     public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, short _keySym, char keyChar) {
571         throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
572     }
573
574     protected final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, char keyChar, char keySymChar) {
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
577         final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
578         final short keySym;
579         {
580             short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
581             keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
582         }
583         /**
584         {
585             final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
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)+
590                                ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
591                                ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
592         } */
593
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
596         switch(eventType) {
597             case KeyEvent.EVENT_KEY_RELEASED:
598                 if( isKeyCodeTracked(keyCode) ) {
599                     setKeyPressed(keyCode, false);
600                 }
601                 break;
602             case KeyEvent.EVENT_KEY_PRESSED:
603                 if( isKeyCodeTracked(keyCode) ) {
604                     if( setKeyPressed(keyCode, true) ) {
605                         // key was already pressed
606                         modifiers |= InputEvent.AUTOREPEAT_MASK;
607                         super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
608                     }
609                 }
610                 break;
611         }
612         super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
613     }
614
615     //----------------------------------------------------------------------
616     // Internals only
617     //
618
619     private void createWindow(final boolean offscreenInstance, final boolean recreate,
620                               final PointImmutable pS, final int width, final int height,
621                               final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
622
623         final long parentWinHandle = getParentWindowHandle();
624         final long preWinHandle = getWindowHandle();
625
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+
630                                ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
631                                ", surfaceHandle "+toHexString(surfaceHandle));
632             // Thread.dumpStack();
633         }
634
635         try {
636             if( 0 != preWinHandle ) {
637                 setWindowHandle(0);
638                 if( 0 == surfaceHandle ) {
639                     throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
640                 }
641                 OSXUtil.RunOnMainThread(false, new Runnable() {
642                     @Override
643                     public void run() {
644                         changeContentView0(parentWinHandle, preWinHandle, 0);
645                         close0( preWinHandle );
646                     } } );
647             } else {
648                 if( 0 != surfaceHandle ) {
649                     throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
650                 }
651                 surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
652                 if( 0 == surfaceHandle ) {
653                     throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
654                 }
655             }
656
657             final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
658                                                ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
659                                                NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
660                                                NSBackingStoreBuffered, surfaceHandle);
661             if ( newWin == 0 ) {
662                 throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
663             }
664             setWindowHandle( newWin );
665
666             final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
667             // Blocking initialization on main-thread!
668             OSXUtil.RunOnMainThread(true, new Runnable() {
669                 @Override
670                 public void run() {
671                     initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
672                                  isOpaque, visible && !offscreenInstance, surfaceHandle);
673                     if( offscreenInstance ) {
674                         orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
675                     } else {
676                         setTitle0(newWin, getTitle());
677                         setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
678                     }
679                 } } );
680         } catch (Exception ie) {
681             ie.printStackTrace();
682         }
683     }
684
685     protected static native boolean initIDs0();
686     private native long createView0(int x, int y, int w, int h);
687     private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
688     /** Must be called on Main-Thread */
689     private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale,
690                                     boolean opaque, boolean visible, long view);
691     private native void setPixelScale0(long window, long view, float reqPixelScale);
692     private native boolean lockSurface0(long window, long view);
693     private native boolean unlockSurface0(long window, long view);
694     /** Must be called on Main-Thread */
695     private native void requestFocus0(long window, boolean force);
696     /** Must be called on Main-Thread */
697     private native void resignFocus0(long window);
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(). */
699     private native void orderOut0(long window);
700     /** Must be called on Main-Thread */
701     private native void orderFront0(long window);
702     /** Must be called on Main-Thread */
703     private native void close0(long window);
704     /** Must be called on Main-Thread */
705     private native void setTitle0(long window, String title);
706     private native long contentView0(long window);
707     /** Must be called on Main-Thread */
708     private native void changeContentView0(long parentWindowOrView, long window, long view);
709     /** Must be called on Main-Thread */
710     private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
711     /** Must be called on Main-Thread */
712     private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
713     /** Must be called on Main-Thread */
714     private native void setAlwaysOnTop0(long window, boolean atop);
715     private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
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);
720
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
733     private volatile long surfaceHandle = 0;
734     private long sscSurfaceHandle = 0;
735     private boolean isOffscreenInstance = false;
736
737 }
http://JogAmp.org git info: FAQ, tutorial and man pages.