Jogamp
07d31acfd5ab347cbe912fde28e03b93b53ae83d
[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 int[] setSurfaceScale(final int[] result, final int[] pixelScale) {
139         SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null);
140         if( null != result ) {
141             System.arraycopy(reqPixelScale, 0, result, 0, 2);
142         }
143
144         final int[] resPixelScale;
145         if( isNativeValid() ) {
146             if( isOffscreenInstance ) {
147                 final NativeWindow pWin = getParent();
148                 if( pWin instanceof ScalableSurface ) {
149                     final ScalableSurface sSurf = (ScalableSurface)pWin;
150                     sSurf.setSurfaceScale(result, reqPixelScale);
151                     final int[] pPixelScale = sSurf.getSurfaceScale(new int[2]);
152                     updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0]); // HiDPI: uniformPixelScale
153                 } else {
154                     // just notify updated pixelScale if offscreen
155                     SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale);
156                     updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0]); // HiDPI: uniformPixelScale
157                 }
158             } else {
159                 // set pixelScale in native code, will issue an update PixelScale
160                 OSXUtil.RunOnMainThread(true, new Runnable() {
161                     @Override
162                     public void run() {
163                         setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale
164                     }
165                 } );
166             }
167             resPixelScale = hasPixelScale;
168         } else {
169             hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
170             hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
171             resPixelScale = reqPixelScale;
172         }
173         if( DEBUG_IMPLEMENTATION ) {
174             System.err.println("WindowDriver.setPixelScale: "+pixelScale[0]+"x"+pixelScale[1]+" (req) -> "+
175                                 reqPixelScale[0]+"x"+reqPixelScale[1]+" (validated) -> "+
176                                 resPixelScale[0]+"x"+resPixelScale[1]+" (result) - realized "+isNativeValid());
177         }
178         return result;
179     }
180
181     @Override
182     protected void createNativeImpl() {
183         final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
184                 capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
185         if (null == cfg) {
186             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
187         }
188         setGraphicsConfiguration(cfg);
189         reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
190         if (0 == getWindowHandle()) {
191             throw new NativeWindowException("Error creating window");
192         }
193     }
194
195     @Override
196     protected void closeNativeImpl() {
197         try {
198             if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
199             final long handle = getWindowHandle();
200             visibleChanged(true, false);
201             setWindowHandle(0);
202             surfaceHandle = 0;
203             sscSurfaceHandle = 0;
204             isOffscreenInstance = false;
205             if (0 != handle) {
206                 OSXUtil.RunOnMainThread(false, new Runnable() {
207                    @Override
208                    public void run() {
209                        close0( handle );
210                    } } );
211             }
212         } catch (Throwable t) {
213             if(DEBUG_IMPLEMENTATION) {
214                 Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
215                 e.printStackTrace();
216             }
217         }
218     }
219
220     @Override
221     protected int lockSurfaceImpl() {
222         /**
223          * if( isOffscreenInstance ) {
224          *    return LOCK_SUCCESS;
225          * }
226          */
227         final long w = getWindowHandle();
228         final long v = surfaceHandle;
229         if( 0 != v && 0 != w ) {
230             return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
231         }
232         return LOCK_SURFACE_NOT_READY;
233     }
234
235     @Override
236     protected void unlockSurfaceImpl() {
237         /**
238          * if( isOffscreenInstance ) {
239          *    return;
240          * }
241          */
242         final long w = getWindowHandle();
243         final long v = surfaceHandle;
244         if(0 != w && 0 != v) {
245             if( !unlockSurface0(w, v) ) {
246                 throw new NativeWindowException("Failed to unlock surface, probably not locked!");
247             }
248         }
249     }
250
251     @Override
252     public final long getSurfaceHandle() {
253         return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
254     }
255
256     @Override
257     public void setSurfaceHandle(long surfaceHandle) {
258         if(DEBUG_IMPLEMENTATION) {
259             System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
260         }
261         sscSurfaceHandle = surfaceHandle;
262         if (isNativeValid()) {
263             if (0 != sscSurfaceHandle) {
264                 OSXUtil.RunOnMainThread(false, new Runnable() {
265                     @Override
266                     public void run() {
267                         orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
268                     } } );
269             } /** this is done by recreation!
270               else if (isVisible()){
271                 OSXUtil.RunOnMainThread(false, new Runnable() {
272                     public void run() {
273                         orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
274                     } } );
275             } */
276         }
277     }
278
279     @Override
280     protected void setTitleImpl(final String title) {
281         OSXUtil.RunOnMainThread(false, new Runnable() {
282             @Override
283             public void run() {
284                 setTitle0(getWindowHandle(), title);
285             } } );
286     }
287
288     @Override
289     protected void requestFocusImpl(final boolean force) {
290         final boolean _isFullscreen = isFullscreen();
291         final boolean _isOffscreenInstance = isOffscreenInstance;
292         if(DEBUG_IMPLEMENTATION) {
293             System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
294         }
295         if(!_isOffscreenInstance) {
296             OSXUtil.RunOnMainThread(false, new Runnable() {
297                 @Override
298                 public void run() {
299                     requestFocus0(getWindowHandle(), force);
300                     if(_isFullscreen) {
301                         // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
302                         focusChanged(false, true);
303                     }
304                 } } );
305         } else {
306             focusChanged(false, true);
307         }
308     }
309
310     @Override
311     public final void clearFocus() {
312         if(DEBUG_IMPLEMENTATION) {
313             System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
314         }
315         if(!isOffscreenInstance) {
316             OSXUtil.RunOnMainThread(false, new Runnable() {
317                 @Override
318                 public void run() {
319                     resignFocus0(getWindowHandle());
320                 } } );
321         } else {
322             focusChanged(false, false);
323         }
324     }
325
326     private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
327
328     @Override
329     public void updatePosition(int x, int y) {
330         final long handle = getWindowHandle();
331         if( 0 != handle && !isOffscreenInstance ) {
332             final NativeWindow parent = getParent();
333             final boolean useParent = useParent(parent);
334             final int pX=parent.getX(), pY=parent.getY();
335             final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
336             if(DEBUG_IMPLEMENTATION) {
337                 System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" ->  "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
338             }
339             OSXUtil.RunOnMainThread(false, new Runnable() {
340                 @Override
341                 public void run() {
342                     setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
343                 } } );
344             // no native event (fullscreen, some reparenting)
345             positionChanged(true, x, y);
346         }
347     }
348
349     @Override
350     protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
351         final long handle = getWindowHandle();
352         if( 0 != handle && !isOffscreenInstance ) {
353             final NativeWindow parent = getParent();
354             final boolean useParent = useParent(parent);
355             if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
356                 final int x=getX(), y=getY();
357                 final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
358                 if(DEBUG_IMPLEMENTATION) {
359                     System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" ->  "+p0S+" screen-client-pos");
360                 }
361                 OSXUtil.RunOnMainThread(false, new Runnable() {
362                     @Override
363                     public void run() {
364                         setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
365                     } } );
366             }
367         }
368         super.sizeChanged(defer, newWidth, newHeight, force);
369     }
370
371     @Override
372     protected boolean reconfigureWindowImpl(int x, int y, final int width, final int height, int flags) {
373         final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
374         isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
375         final PointImmutable pClientLevelOnSreen;
376         if( isOffscreenInstance ) {
377             x = 0; y = 0;
378             pClientLevelOnSreen = new Point(0, 0);
379         } else  {
380             final NativeWindow parent = getParent();
381             final boolean useParent = useParent(parent);
382             if( useParent ) {
383                 pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
384             } else {
385                 pClientLevelOnSreen = new Point(x, y);
386             }
387         }
388
389         final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
390         final boolean hasFocus = hasFocus();
391
392         if(DEBUG_IMPLEMENTATION) {
393             final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
394             final NativeWindow pWin = getParent();
395             final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
396             System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
397                                ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
398                                ",\n\t   this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
399                                ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
400                                ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
401                                ", ioi: "+_isOffscreenInstance+
402                                ") -> "+isOffscreenInstance+
403                                "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus);
404             // Thread.dumpStack();
405         }
406
407         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
408             if ( !isOffscreenInstance ) {
409                 OSXUtil.RunOnMainThread(false, new Runnable() {
410                     @Override
411                     public void run() {
412                         orderOut0(getWindowHandle());
413                         visibleChanged(true, false);
414                     } } );
415             } else {
416                 visibleChanged(true, false);
417             }
418         }
419         if( 0 == getWindowHandle() && setVisible ||
420             0 != ( FLAG_CHANGE_DECORATION & flags) ||
421             0 != ( FLAG_CHANGE_PARENTING & flags) ||
422             0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
423             if(isOffscreenInstance) {
424                 createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
425             } else {
426                 createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
427                                     0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
428             }
429             // no native event (fullscreen, some reparenting)
430             positionChanged(false,  x, y);
431             updatePixelScaleByWindowHandle(false /* sendEvent */);
432             super.sizeChanged(false, width, height, true);
433             visibleChanged(false, setVisible);
434             if( hasFocus ) {
435                 requestFocusImpl(true);
436             }
437         } else {
438             if( width>0 && height>0 ) {
439                 if( !isOffscreenInstance ) {
440                     OSXUtil.RunOnMainThread(false, new Runnable() {
441                         @Override
442                         public void run() {
443                             setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
444                         } } );
445                 } // else offscreen size is realized via recreation
446                 // no native event (fullscreen, some reparenting)
447                 positionChanged(true,  x, y);
448                 super.sizeChanged(true, width, height, false);
449             }
450             if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
451                 if( !isOffscreenInstance ) {
452                     OSXUtil.RunOnMainThread(false, new Runnable() {
453                         @Override
454                         public void run() {
455                             orderFront0(getWindowHandle());
456                             visibleChanged(true, true);
457                         } } );
458                 } else {
459                     visibleChanged(true, true);
460                 }
461             }
462             if( !isOffscreenInstance ) {
463                 setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
464             }
465         }
466         if(DEBUG_IMPLEMENTATION) {
467             System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());
468         }
469         return true;
470     }
471
472     @Override
473     protected Point getLocationOnScreenImpl(int x, int y) {
474         final NativeWindow parent = getParent();
475         final boolean useParent = useParent(parent);
476         return getLocationOnScreenImpl(x, y, parent, useParent);
477     }
478
479     private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
480         if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
481             return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y);
482         }
483
484         final Point p = new Point(x, y);
485         if( useParent ) {
486             p.translate( parent.getLocationOnScreen(null) );
487         }
488         return p;
489     }
490
491     @Override
492     protected void updateInsetsImpl(Insets insets) {
493         // nop - using event driven insetsChange(..)
494     }
495
496     /** Callback for native screen position change event of the client area. */
497     protected void screenPositionChanged(boolean defer, int newX, int newY) {
498         // passed coordinates are in screen position of the client area
499         if(getWindowHandle()!=0) {
500             final NativeWindow parent = getParent();
501             if( null == parent || isOffscreenInstance ) {
502                 if(DEBUG_IMPLEMENTATION) {
503                     System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
504                 }
505                 positionChanged(defer, newX, newY);
506             } else {
507                 // screen position -> rel child window position
508                 Point absPos = new Point(newX, newY);
509                 Point parentOnScreen = parent.getLocationOnScreen(null);
510                 absPos.translate( parentOnScreen.scale(-1, -1) );
511                 if(DEBUG_IMPLEMENTATION) {
512                     System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
513                 }
514                 positionChanged(defer, absPos.getX(), absPos.getY());
515             }
516         } else if(DEBUG_IMPLEMENTATION) {
517             System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
518         }
519     }
520
521     @Override
522     protected void setPointerIconImpl(final PointerIconImpl pi) {
523         if( !isOffscreenInstance ) {
524             final long piHandle = null != pi ? pi.validatedHandle() : 0;
525             OSXUtil.RunOnMainThread(true, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle !
526                 @Override
527                 public void run() {
528                     setPointerIcon0(getWindowHandle(), piHandle);
529                 } } );
530         }
531     }
532
533     @Override
534     protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
535         if( !isOffscreenInstance ) {
536             OSXUtil.RunOnMainThread(false, new Runnable() {
537                 @Override
538                 public void run() {
539                     setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
540                 } } );
541             return true;
542         }
543         return false;
544     }
545
546     @Override
547     protected boolean confinePointerImpl(final boolean confine) {
548         if( !isOffscreenInstance ) {
549             confinePointer0(getWindowHandle(), confine);
550             return true;
551         } // else may need offscreen solution ? FIXME
552         return false;
553     }
554
555     @Override
556     protected void warpPointerImpl(final int x, final int y) {
557         if( !isOffscreenInstance ) {
558             warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY());
559         } // else may need offscreen solution ? FIXME
560     }
561
562     @Override
563     protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
564                                       final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
565         super.doMouseEvent(enqueue, wait, eventType, modifiers, x * getPixelScaleX(), y * getPixelScaleY(), button, rotationXYZ, rotationScale);
566     }
567
568     @Override
569     public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
570         throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
571     }
572
573     @Override
574     public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, short _keySym, char keyChar) {
575         throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
576     }
577
578     protected final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, char keyChar, char keySymChar) {
579         // Note that we send the key char for the key code on this
580         // platform -- we do not get any useful key codes out of the system
581         final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
582         final short keySym;
583         {
584             short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
585             keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
586         }
587         /**
588         {
589             final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
590             System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
591                                ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
592                                ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
593                                ", mods "+toHexString(modifiers)+
594                                ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
595                                ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
596         } */
597
598         // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
599         // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
600         switch(eventType) {
601             case KeyEvent.EVENT_KEY_RELEASED:
602                 if( isKeyCodeTracked(keyCode) ) {
603                     setKeyPressed(keyCode, false);
604                 }
605                 break;
606             case KeyEvent.EVENT_KEY_PRESSED:
607                 if( isKeyCodeTracked(keyCode) ) {
608                     if( setKeyPressed(keyCode, true) ) {
609                         // key was already pressed
610                         modifiers |= InputEvent.AUTOREPEAT_MASK;
611                         super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
612                     }
613                 }
614                 break;
615         }
616         super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
617     }
618
619     //----------------------------------------------------------------------
620     // Internals only
621     //
622
623     private void createWindow(final boolean offscreenInstance, final boolean recreate,
624                               final PointImmutable pS, final int width, final int height,
625                               final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
626
627         final long parentWinHandle = getParentWindowHandle();
628         final long preWinHandle = getWindowHandle();
629
630         if(DEBUG_IMPLEMENTATION) {
631             System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
632                                ": offscreen "+offscreenInstance+", recreate "+recreate+
633                                ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
634                                ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
635                                ", surfaceHandle "+toHexString(surfaceHandle));
636             // Thread.dumpStack();
637         }
638
639         try {
640             if( 0 != preWinHandle ) {
641                 setWindowHandle(0);
642                 if( 0 == surfaceHandle ) {
643                     throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
644                 }
645                 OSXUtil.RunOnMainThread(false, new Runnable() {
646                     @Override
647                     public void run() {
648                         changeContentView0(parentWinHandle, preWinHandle, 0);
649                         close0( preWinHandle );
650                     } } );
651             } else {
652                 if( 0 != surfaceHandle ) {
653                     throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
654                 }
655                 surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
656                 if( 0 == surfaceHandle ) {
657                     throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
658                 }
659             }
660
661             final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
662                                                ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
663                                                NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
664                                                NSBackingStoreBuffered, surfaceHandle);
665             if ( newWin == 0 ) {
666                 throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
667             }
668             setWindowHandle( newWin );
669
670             final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
671             // Blocking initialization on main-thread!
672             OSXUtil.RunOnMainThread(true, new Runnable() {
673                 @Override
674                 public void run() {
675                     initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
676                                  isOpaque, visible && !offscreenInstance, surfaceHandle);
677                     if( offscreenInstance ) {
678                         orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
679                     } else {
680                         setTitle0(newWin, getTitle());
681                         setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
682                     }
683                 } } );
684         } catch (Exception ie) {
685             ie.printStackTrace();
686         }
687     }
688
689     protected static native boolean initIDs0();
690     private native long createView0(int x, int y, int w, int h);
691     private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
692     /** Must be called on Main-Thread */
693     private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale,
694                                     boolean opaque, boolean visible, long view);
695     private native void setPixelScale0(long window, long view, float reqPixelScale);
696     private native boolean lockSurface0(long window, long view);
697     private native boolean unlockSurface0(long window, long view);
698     /** Must be called on Main-Thread */
699     private native void requestFocus0(long window, boolean force);
700     /** Must be called on Main-Thread */
701     private native void resignFocus0(long window);
702     /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
703     private native void orderOut0(long window);
704     /** Must be called on Main-Thread */
705     private native void orderFront0(long window);
706     /** Must be called on Main-Thread */
707     private native void close0(long window);
708     /** Must be called on Main-Thread */
709     private native void setTitle0(long window, String title);
710     private native long contentView0(long window);
711     /** Must be called on Main-Thread */
712     private native void changeContentView0(long parentWindowOrView, long window, long view);
713     /** Must be called on Main-Thread */
714     private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
715     /** Must be called on Main-Thread */
716     private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
717     /** Must be called on Main-Thread */
718     private native void setAlwaysOnTop0(long window, boolean atop);
719     private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
720     private static native void setPointerIcon0(long windowHandle, long handle);
721     private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
722     private static native void confinePointer0(long windowHandle, boolean confine);
723     private static native void warpPointer0(long windowHandle, int x, int y);
724
725     // Window styles
726     private static final int NSBorderlessWindowMask     = 0;
727     private static final int NSTitledWindowMask         = 1 << 0;
728     private static final int NSClosableWindowMask       = 1 << 1;
729     private static final int NSMiniaturizableWindowMask = 1 << 2;
730     private static final int NSResizableWindowMask      = 1 << 3;
731
732     // Window backing store types
733     private static final int NSBackingStoreRetained     = 0;
734     private static final int NSBackingStoreNonretained  = 1;
735     private static final int NSBackingStoreBuffered     = 2;
736
737     private volatile long surfaceHandle = 0;
738     private long sscSurfaceHandle = 0;
739     private boolean isOffscreenInstance = false;
740
741 }
http://JogAmp.org git info: FAQ, tutorial and man pages.