JOGL v2.6.0
JOGL, High-Performance Graphics Binding for Java™ (public API).
NewtCanvasSWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2012 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.newt.swt;
30
31import com.jogamp.common.util.locks.RecursiveLock;
32import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
33import com.jogamp.nativewindow.AbstractGraphicsDevice;
34import com.jogamp.nativewindow.AbstractGraphicsScreen;
35import com.jogamp.nativewindow.Capabilities;
36import com.jogamp.nativewindow.CapabilitiesImmutable;
37import com.jogamp.nativewindow.GraphicsConfigurationFactory;
38import com.jogamp.nativewindow.NativeSurface;
39import com.jogamp.nativewindow.NativeWindow;
40import com.jogamp.nativewindow.NativeWindowException;
41import com.jogamp.nativewindow.NativeWindowFactory;
42import com.jogamp.nativewindow.NativeWindowHolder;
43import com.jogamp.nativewindow.SurfaceUpdatedListener;
44import com.jogamp.nativewindow.WindowClosingProtocol;
45import com.jogamp.nativewindow.util.Insets;
46import com.jogamp.nativewindow.util.InsetsImmutable;
47import com.jogamp.nativewindow.util.Point;
48import com.jogamp.opengl.GLCapabilities;
49
50import jogamp.nativewindow.macosx.OSXUtil;
51import jogamp.newt.Debug;
52import jogamp.newt.swt.SWTEDTUtil;
53
54import org.eclipse.swt.SWT;
55import org.eclipse.swt.SWTException;
56import org.eclipse.swt.graphics.Color;
57import org.eclipse.swt.widgets.Canvas;
58import org.eclipse.swt.widgets.Composite;
59import org.eclipse.swt.widgets.Event;
60import org.eclipse.swt.widgets.Listener;
61
62import com.jogamp.nativewindow.swt.SWTAccessor;
63import com.jogamp.newt.Display;
64import com.jogamp.newt.Window;
65import com.jogamp.newt.event.WindowEvent;
66import com.jogamp.newt.util.EDTUtil;
67
68/**
69 * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting.
70 * <p>
71 * Implementation allows use of custom {@link GLCapabilities}.
72 * </p>
73 */
74public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowClosingProtocol {
75 private static final boolean DEBUG = Debug.debug("Window");
76
77 private final int iHashCode;
78 private final AbstractGraphicsScreen screen;
79
80 private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
81 private final WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
82 private volatile org.eclipse.swt.graphics.Rectangle clientAreaPixels, clientAreaWindow;
83 /** pixelScale = pixelUnit / windowUnix */
84 private volatile float[] pixelScale = new float[] { 1f, 1f };
85
86 private volatile SWTNativeWindow nativeWindow;
87 private volatile Window newtChild = null;
88 private volatile boolean newtChildReady = false; // ready if SWTEDTUtil is set and newtChild parented
89 private volatile boolean postSetSize = false; // pending resize
90 private volatile boolean postSetPos = false; // pending pos
91
92 /**
93 * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
94 * on the SWT thread.
95 *
96 * <p>
97 * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
98 * via {@link Display#setEDTUtil(EDTUtil)}.
99 * </p>
100 *
101 * @param parent the SWT composite
102 * @param style additional styles to SWT#NO_BACKGROUND
103 * @param child optional preassigned {@link #Window}, maybe null
104 * @return a new instance
105 */
106 public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) {
107 final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
108 parent.getDisplay().syncExec( new Runnable() {
109 @Override
110 public void run() {
111 res[0] = new NewtCanvasSWT( parent, style, child);
112 }
113 });
114 return res[0];
115 }
116
117 private final String shortName() { return "NewtCanvasSWT("+toHexString(iHashCode)+")"; }
118
119 /**
120 * Instantiates a NewtCanvas with a NEWT child.
121 *
122 * <p>
123 * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
124 * via {@link Display#setEDTUtil(EDTUtil)}.
125 * </p>
126 *
127 * @param parent the SWT composite
128 * @param style additional styles to SWT#NO_BACKGROUND
129 * @param child optional preassigned {@link #Window}, maybe null
130 */
131 public NewtCanvasSWT(final Composite parent, final int style, final Window child) {
132 super(parent, style | SWT.NO_BACKGROUND);
133 iHashCode = this.hashCode();
134
135 SWTAccessor.setRealized(this, true);
136
137 clientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
138 clientAreaWindow = getClientArea();
139 if( 0 < clientAreaWindow.width && 0 < clientAreaWindow.height ) {
140 pixelScale[0] = clientAreaPixels.width / clientAreaWindow.width;
141 pixelScale[1] = clientAreaPixels.height / clientAreaWindow.height;
142 } else {
143 pixelScale[0] = 1f;
144 pixelScale[1] = 1f;
145 }
146
147 final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
148 screen = SWTAccessor.getScreen(device, -1 /* default */);
149 nativeWindow = null;
150
151 // Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization
152 // Minimal action required: setBackground of the parent canvas before reparenting!
153 setBackground(new Color(parent.getDisplay(), 255, 255, 255));
154
155 if(null != child) {
156 setNEWTChild(child);
157 }
158 if(DEBUG) {
159 final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
160 System.err.println("NewtCanvasSWT: "+
161 ", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+
162 ", pixel "+clientAreaPixels.x+"/"+clientAreaPixels.y+" "+clientAreaPixels.width+"x"+clientAreaPixels.height+
163 ", window "+clientAreaWindow.x+"/"+clientAreaWindow.y+" "+clientAreaWindow.width+"x"+clientAreaWindow.height+
164 ", scale "+pixelScale[0]+"/"+pixelScale[1]+
165 " - surfaceHandle 0x"+Long.toHexString(nsh));
166 }
167
168 addListener (SWT.Paint, swtListener);
169 addListener (SWT.Move, swtListener);
170 addListener (SWT.Show, swtListener);
171 addListener (SWT.Hide, swtListener);
172 addListener (SWT.Resize, swtListener);
173 addListener (SWT.Dispose, swtListener);
174 addListener (SWT.Activate, swtListener);
175 addListener (SWT.Deactivate, swtListener);
176 addListener (SWT.FocusIn, swtListener);
177 addListener (SWT.FocusOut, swtListener);
178 }
179
180 /**
181 * Return scaled-up value {@code scaleUp} using {@link SWTAccessor#deviceZoomScaleUp(int)}
182 * for all non-native DPI autoscale platforms, currently !{@link SWTAccessor#isOSX}.
183 * <p>
184 * Return passthrough value {@code passthrough} unchanged
185 * for all native DPI autoscale platforms, currently {@link SWTAccessor#isOSX}.
186 * </p>
187 * <p>
188 * See {@link #setNewtChildSize(Rectangle)}
189 * </p>
190 * @param scaleUp value to be used for non-native DPI autoscale platforms for upscale
191 * @param passthrough value to be used for native DPI autoscale platforms for passthrough
192 */
193 private final int newtScaleUp(final int scaleUp, final int passthrough) {
194 if( !SWTAccessor.isOSX ) {
195 return SWTAccessor.deviceZoomScaleUp(scaleUp);
196 } else {
197 return passthrough;
198 }
199 }
200 private final Listener swtListener = new Listener () {
201 @Override
202 public void handleEvent (final Event event) {
203 switch (event.type) {
204 case SWT.Paint:
205 if( DEBUG ) {
206 System.err.println(shortName()+".Event.PAINT, "+event);
207 // Cannot invoke "com.jogamp.newt.Window.getDelegatedWindow()" because the return value of "com.jogamp.newt.swt.NewtCanvasSWT.access$200(com.jogamp.newt.swt.NewtCanvasSWT)" is null
208 // System.err.println(shortName()+".Event.PAINT, "+newtChild.getDelegatedWindow().toSimpleString());
209 }
210 if( validateNative() && newtChildReady ) {
211 if( postSetSize ) {
212 newtChild.setSize(clientAreaWindow.width, clientAreaWindow.height);
213 newtChild.setSurfaceScale(pixelScale);
214 postSetSize = false;
215 }
216 if( postSetPos ) {
217 newtChild.setPosition(clientAreaWindow.x, clientAreaWindow.y);
218 postSetPos = false;
219 }
220 newtChild.windowRepaint(0, 0, clientAreaPixels.width, clientAreaPixels.height);
221 }
222 break;
223 case SWT.Move:
224 if( DEBUG ) {
225 System.err.println(shortName()+".Event.MOVE, "+event);
226 // System.err.println(shortName()+".Event.MOVE, "+newtChild.getDelegatedWindow().toSimpleString());
227 }
228 break;
229 case SWT.Show:
230 if( DEBUG ) {
231 System.err.println(shortName()+".Event.SHOW, "+event);
232 // System.err.println(shortName()+".Event.SHOW, "+newtChild.getDelegatedWindow().toSimpleString());
233 }
234 if( newtChildReady ) {
235 newtChild.setVisible(true /* wait */, true /* visible */);
236 }
237 break;
238 case SWT.Hide:
239 if( DEBUG ) {
240 System.err.println(shortName()+".Event.HIDE, "+event);
241 // System.err.println(shortName()+".Event.HIDE, "+newtChild.getDelegatedWindow().toSimpleString());
242 }
243 if( newtChildReady ) {
244 newtChild.setVisible(true /* wait */, false /* visible */);
245 }
246 break;
247 case SWT.Resize:
248 if( DEBUG ) {
249 System.err.println(shortName()+".Event.RESIZE, "+event);
250 // System.err.println(shortName()+".Event.RESIZE, "+newtChild.getDelegatedWindow().toSimpleString());
251 }
252 if( isNativeValid() ) {
253 // ensure this is being called if already valid
255 } else {
257 }
258 break;
259 case SWT.Dispose:
260 if( DEBUG ) {
261 System.err.println(shortName()+".Event.DISPOSE, "+event);
262 // Cannot invoke "com.jogamp.newt.Window.getDelegatedWindow()" because the return value of "com.jogamp.newt.swt.NewtCanvasSWT.access$200(com.jogamp.newt.swt.NewtCanvasSWT)" is null
263 // System.err.println(shortName()+".Event.DISPOSE, "+newtChild.getDelegatedWindow().toSimpleString());
264 }
265 NewtCanvasSWT.this.dispose();
266 break;
267 case SWT.Activate: // receives focus ??
268 if( DEBUG ) {
269 System.err.println(shortName()+".Event.ACTIVATE, "+event);
270 // System.err.println(shortName()+".Event.ACTIVATE, "+newtChild.getDelegatedWindow().toSimpleString());
271 }
272 break;
273 case SWT.Deactivate: // lost focus ??
274 if( DEBUG ) {
275 System.err.println(shortName()+".Event.DEACTIVATE, "+event);
276 // System.err.println(shortName()+".Event.DEACTIVATE, "+newtChild.getDelegatedWindow().toSimpleString());
277 }
278 break;
279 case SWT.FocusIn: // receives focus
280 if( DEBUG ) {
281 System.err.println(shortName()+".Event.FOCUS_IN, "+event);
282 // System.err.println(shortName()+".Event.FOCUS_IN, "+newtChild.getDelegatedWindow().toSimpleString());
283 }
284 if( newtChildReady ) {
285 newtChild.requestFocus(false /* wait */);
286 }
287 break;
288 case SWT.FocusOut: // lost focus
289 if( DEBUG ) {
290 System.err.println(shortName()+".Event.FOCUS_OUT, "+event);
291 // System.err.println(shortName()+".Event.FOCUS_OUT, "+newtChild.getDelegatedWindow().toSimpleString());
292 }
293 // we lack newtChild.releaseFocus(..) as this should be handled by the WM
294 break;
295 default:
296 if( DEBUG ) {
297 System.err.println(shortName()+".Event.misc: "+event.type+", "+event);
298 // System.err.println(shortName()+".Event.misc: "+newtChild.getDelegatedWindow().toSimpleString());
299 }
300 }
301 }
302 };
303
304 @Override
305 public void setBounds(final int x, final int y, final int width, final int height) {
306 super.setBounds(x, y, width, height);
307 if( DEBUG ) {
308 System.err.println(shortName()+".setBounds: "+x+"/"+y+" "+width+"x"+height);
309 }
311 }
312
313 protected final boolean isNativeValid() { return null != nativeWindow; }
314
315 protected final boolean validateNative() {
316 if( null != nativeWindow ) {
317 return true; // already valid
318 }
320 final org.eclipse.swt.graphics.Rectangle nClientAreaWindow = clientAreaWindow;
321 if(0 >= nClientAreaWindow.width || 0 >= nClientAreaWindow.height) {
322 return false;
323 }
324 screen.getDevice().open();
325
326 /* Native handle for the control, used to associate with GLContext */
327 final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
328 final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
329 final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
330 if(DEBUG) {
331 System.err.println(shortName()+".validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
332 }
333 if( visualIDValid ) {
334 /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
335 * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
336 final CapabilitiesImmutable caps = new Capabilities();
338 final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
339 if(DEBUG) {
340 System.err.println(shortName()+".validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
341 // Thread.dumpStack();
342 }
343 if (null == config) {
344 throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
345 }
346
347 nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
348 reparentWindow( true );
349 }
350 return null != nativeWindow;
351 }
352
353 protected final void updatePosSizeCheck() {
354 final org.eclipse.swt.graphics.Rectangle oClientAreaWindow = clientAreaWindow;
355 final org.eclipse.swt.graphics.Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
356 final org.eclipse.swt.graphics.Rectangle nClientAreaWindow = getClientArea();
357 final boolean sizeChanged, posChanged;
358 {
359 sizeChanged = nClientAreaWindow.width != oClientAreaWindow.width || nClientAreaWindow.height != oClientAreaWindow.height;
360 posChanged = nClientAreaWindow.x != oClientAreaWindow.x || nClientAreaWindow.y != oClientAreaWindow.y;
361 if( sizeChanged || posChanged ) {
362 clientAreaPixels = nClientAreaPixels;
363 clientAreaWindow = nClientAreaWindow;
364 if( 0 < nClientAreaWindow.width && 0 < nClientAreaWindow.height ) {
365 pixelScale[0] = nClientAreaPixels.width / nClientAreaWindow.width;
366 pixelScale[1] = nClientAreaPixels.height / nClientAreaWindow.height;
367 } else {
368 pixelScale[0] = 1f;
369 pixelScale[1] = 1f;
370 }
371 }
372 }
373 if(DEBUG) {
374 final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
375 System.err.println(shortName()+".updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+
376 ", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+
377 ", pixel "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+
378 ", window "+nClientAreaWindow.x+"/"+nClientAreaWindow.y+" "+nClientAreaWindow.width+"x"+nClientAreaWindow.height+
379 ", scale "+pixelScale[0]+"/"+pixelScale[1]+
380 " - surfaceHandle 0x"+Long.toHexString(nsh));
381 }
382 if( sizeChanged ) {
383 if( newtChildReady ) {
384 newtChild.setSize(nClientAreaWindow.width, nClientAreaWindow.height);
385 newtChild.setSurfaceScale(pixelScale);
386 } else {
387 postSetSize = true;
388 }
389 }
390 if( posChanged ) {
391 if( newtChildReady ) {
392 newtChild.setPosition(nClientAreaWindow.x, nClientAreaWindow.y);
393 } else {
394 postSetPos = true;
395 }
396 }
397 if( DEBUG ) {
398 System.err.println(shortName()+".updatePosSizeCheck.X END");
399 }
400 }
401
402 @Override
403 public void update() {
404 // don't paint background etc .. nop avoids flickering
405 }
406
407 /**
408 * Destroys this resource:
409 * <ul>
410 * <li> Make the NEWT Child invisible </li>
411 * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
412 * <li> Issues <code>destroy()</code> on the NEWT Child</li>
413 * <li> Remove reference to the NEWT Child</li>
414 * </ul>
415 * @see Window#destroy()
416 * @throws SWTException If this method is not called
417 * {@link SWTAccessor#isOnSWTThread(org.eclipse.swt.widgets.Display) from the SWT thread},
418 * an {@link SWTException} is thrown for compliance across platforms.
419 * User may utilize {@link SWTAccessor#invokeOnSWTThread(org.eclipse.swt.widgets.Display, boolean, Runnable)}.
420 */
421 @Override
422 public void dispose() throws SWTException {
423 if( !SWTAccessor.isOnSWTThread( getDisplay() ) ) {
424 throw new SWTException("Invalid thread access");
425 }
426 removeListener (SWT.Paint, swtListener);
427 removeListener (SWT.Move, swtListener);
428 removeListener (SWT.Show, swtListener);
429 removeListener (SWT.Hide, swtListener);
430 removeListener (SWT.Resize, swtListener);
431 removeListener (SWT.Dispose, swtListener);
432 removeListener (SWT.Activate, swtListener);
433 removeListener (SWT.Deactivate, swtListener);
434 removeListener (SWT.FocusIn, swtListener);
435 removeListener (SWT.FocusOut, swtListener);
436
437 if( null != newtChild ) {
438 if(DEBUG) {
439 System.err.println(shortName()+".dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
440 ",\n\t"+newtChild);
441 }
442 configureNewtChild(false);
443 newtChild.setVisible(false);
444 newtChild.reparentWindow(null, -1, -1, 0 /* hint */);
445 newtChild.destroy();
446 newtChild = null;
447 }
448 screen.getDevice().close();
449 nativeWindow = null;
450 super.dispose();
451 }
452
453 /**
454 * {@inheritDoc}
455 * @return this SWT Canvas {@link NativeWindow} representation, may be null in case it has not been realized
456 */
457 @Override
458 public NativeWindow getNativeWindow() { return nativeWindow; }
459
460 /**
461 * {@inheritDoc}
462 * @return this SWT Canvas {@link NativeSurface} representation, may be null in case it has not been realized
463 */
464 @Override
465 public NativeSurface getNativeSurface() { return nativeWindow; }
466
467 @Override
469 return closingMode;
470 }
471
472 @Override
474 return closingMode; // TODO: implement!
475 }
476
477
478 boolean isParent() {
479 return null!=newtChild ;
480 }
481
482 boolean isFullscreen() {
483 return null != newtChild && newtChild.isFullscreen();
484 }
485
486 /**
487 * Sets a new NEWT child, provoking reparenting.
488 * <p>
489 * A previously detached <code>newChild</code> will be released to top-level status
490 * and made invisible.
491 * </p>
492 * <p>
493 * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
494 * produced much cleaner visual results.
495 * </p>
496 * <p>
497 * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
498 * via {@link Display#setEDTUtil(EDTUtil)}.
499 * </p>
500 * @return the previous attached newt child.
501 *
502 * @throws SWTException If this method is not called
503 * {@link SWTAccessor#isOnSWTThread(org.eclipse.swt.widgets.Display) from the SWT thread},
504 * an {@link SWTException} is thrown for compliance across platforms.
505 * User may utilize {@link SWTAccessor#invokeOnSWTThread(org.eclipse.swt.widgets.Display, boolean, Runnable)}.
506 */
507 public Window setNEWTChild(final Window newChild) throws SWTException {
508 if( !SWTAccessor.isOnSWTThread( getDisplay() ) ) {
509 throw new SWTException("Invalid thread access");
510 }
511
512 // if( org.eclipse.swt.widgets.Display.s)
513 final Window prevChild = newtChild;
514 if(DEBUG) {
515 System.err.println(shortName()+".setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
516 }
517 // remove old one
518 if(null != newtChild) {
519 reparentWindow( false );
520 newtChild = null;
521 }
522 // add new one, reparent only if ready
523 newtChild = newChild;
524 if(null != nativeWindow && null != newChild) {
525 reparentWindow( true );
526 }
527 return prevChild;
528 }
529
530 /** @return the current NEWT child */
532 return newtChild;
533 }
534
535 @Override
536 public boolean setParent(final Composite parent) {
537 return super.setParent(parent);
538 }
539
540 /* package */ void configureNewtChild(final boolean attach) {
541 newtChildReady = attach;
542 if( null != newtChild ) {
543 newtChild.setKeyboardFocusHandler(null);
544 if(attach) {
545 newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
546 } else {
547 newtChild.setFocusAction(null);
548 newtChild.setDefaultCloseOperation(newtChildClosingMode);
549 }
550 }
551 }
552
553 void reparentWindow(final boolean add) {
554 if( null == newtChild ) {
555 return; // nop
556 }
557 if(DEBUG) {
558 System.err.println(shortName()+".reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
559 }
560
561 newtChild.setFocusAction(null); // no AWT focus traversal ..
562 if(add) {
564
565 // set SWT EDT and start it
566 {
567 final Display newtDisplay = newtChild.getScreen().getDisplay();
568 final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay());
569 edtUtil.start();
570 newtDisplay.setEDTUtil( edtUtil );
571 }
572
573 newtChild.setSize(clientAreaWindow.width, clientAreaWindow.height);
574 newtChild.reparentWindow(nativeWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
575 newtChild.setPosition(clientAreaWindow.x, clientAreaWindow.y);
576 newtChild.setVisible(true);
577 configureNewtChild(true);
578 newtChild.setSurfaceScale(pixelScale); // ensure this to be set after creation, otherwise updatePosSizeCheck is being used
579 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
580
581 // force this SWT Canvas to be focus-able,
582 // since it is completely covered by the newtChild (z-order).
583 setEnabled(true);
584 } else {
585 configureNewtChild(false);
586 newtChild.setVisible(false);
587 newtChild.reparentWindow(null, -1, -1, 0 /* hints */);
588 }
589 if(DEBUG) {
590 System.err.println(shortName()+".reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
591 }
592 }
593
594 private final void requestFocusNEWTChild() {
595 if( newtChildReady ) {
596 newtChild.setFocusAction(null);
597 newtChild.requestFocus();
598 }
599 }
600
601 @Override
602 public boolean forceFocus() {
603 final boolean res = NewtCanvasSWT.super.forceFocus();
604 requestFocusNEWTChild();
605 return res;
606 }
607
608 private class SWTNativeWindow implements NativeWindow {
609 private final AbstractGraphicsConfiguration config;
610 private final long nativeWindowHandle;
611 private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
612
613 public SWTNativeWindow(final AbstractGraphicsConfiguration config, final long nativeWindowHandle) {
614 this.config = config;
615 this.nativeWindowHandle = nativeWindowHandle;
616 if( SWTAccessor.isOSX ) {
617 this.insets = OSXUtil.GetInsets(nativeWindowHandle);
618 } else {
619 this.insets = new Insets(0, 0, 0, 0);
620 }
621 }
622
623 @Override
624 public RecursiveLock getLock() { return null; }
625
626 @Override
627 public int lockSurface() throws NativeWindowException, RuntimeException {
628 return NativeSurface.LOCK_SUCCESS;
629 }
630
631 @Override
632 public void unlockSurface() { }
633
634 @Override
635 public boolean isSurfaceLockedByOtherThread() {
636 return false;
637 }
638
639 @Override
640 public Thread getSurfaceLockOwner() {
641 return null;
642 }
643
644 @Override
645 public boolean surfaceSwap() {
646 return false;
647 }
648
649 @Override
650 public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
651
652 @Override
653 public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
654 }
655
656 @Override
657 public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
658
659 @Override
660 public long getSurfaceHandle() {
661 return 0;
662 }
663
664 @Override
665 public int getX() {
666 return 0;
667 }
668
669 @Override
670 public int getY() {
671 return 0;
672 }
673
674 @Override
675 public int getWidth() {
676 return newtScaleUp(clientAreaWindow.width, clientAreaWindow.width);
677 }
678
679 @Override
680 public int getHeight() {
681 return newtScaleUp(clientAreaWindow.height, clientAreaWindow.height);
682 }
683
684 @Override
685 public final com.jogamp.nativewindow.util.Rectangle getBounds() {
686 return new com.jogamp.nativewindow.util.Rectangle(getX(), getY(), getWidth(), getHeight());
687 }
688
689 @Override
690 public final com.jogamp.nativewindow.util.Rectangle getSurfaceBounds() {
691 return new com.jogamp.nativewindow.util.Rectangle(getX(), getY(),
692 getSurfaceWidth(), getSurfaceHeight());
693 }
694
695 @Override
696 public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
697 pixelUnitsAndResult[0] /= pixelScale[0];
698 pixelUnitsAndResult[1] /= pixelScale[1];
699 return pixelUnitsAndResult;
700 }
701
702 @Override
703 public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
704 windowUnitsAndResult[0] *= pixelScale[0];
705 windowUnitsAndResult[1] *= pixelScale[1];
706 return windowUnitsAndResult;
707 }
708
709 @Override
710 public int getSurfaceWidth() {
711 return newtScaleUp(clientAreaWindow.width, clientAreaPixels.width);
712 }
713
714 @Override
715 public int getSurfaceHeight() {
716 return newtScaleUp(clientAreaWindow.height, clientAreaPixels.height);
717 }
718
719 @Override
720 public final NativeSurface getNativeSurface() { return this; }
721
722 @Override
723 public AbstractGraphicsConfiguration getGraphicsConfiguration() {
724 return config;
725 }
726
727 @Override
728 public long getDisplayHandle() {
729 return config.getScreen().getDevice().getHandle();
730 }
731
732 @Override
733 public int getScreenIndex() {
734 return config.getScreen().getIndex();
735 }
736
737 @Override
738 public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { }
739
740 @Override
741 public void destroy() { }
742
743 @Override
744 public NativeWindow getParent() {
745 return null;
746 }
747
748 @Override
749 public long getWindowHandle() {
750 return nativeWindowHandle;
751 }
752
753 @Override
754 public InsetsImmutable getInsets() {
755 return insets;
756 }
757
758 @Override
759 public Point getLocationOnScreen(final Point point) {
760 final Point los = NativeWindowFactory.getLocationOnScreen(this); // client window location on screen
761 if(null!=point) {
762 return point.translate(los);
763 } else {
764 return los;
765 }
766 }
767
768 @Override
769 public boolean hasFocus() {
770 return isFocusControl();
771 }
772 };
773
774 static String newtWinHandleToHexString(final Window w) {
775 return null != w ? toHexString(w.getWindowHandle()) : "nil";
776 }
777 static String toHexString(final long l) {
778 return "0x"+Long.toHexString(l);
779 }
780}
781
Specifies a set of capabilities that a window's rendering context must support, such as color depth p...
Provides the mechanism by which the graphics configuration for a window can be chosen before the wind...
final AbstractGraphicsConfiguration chooseGraphicsConfiguration(final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen screen, final int nativeVisualID)
static GraphicsConfigurationFactory getFactory(final AbstractGraphicsDevice device, final CapabilitiesImmutable caps)
Returns the graphics configuration factory for use with the given device and capability.
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the NativeW...
static boolean isNativeVisualIDValidForProcessing(final int visualID)
Returns true if the given visualID is valid for further processing, i.e.
static boolean isOnSWTThread(final org.eclipse.swt.widgets.Display display)
Return true if the current thread is the SWT UI thread, otherwise false.
static long getWindowHandle(final Control swtControl)
static Rectangle getClientAreaInPixels(final Scrollable s)
Returns the unscaled Scrollable#getClientArea() in pixels.
static int deviceZoomScaleUp(final int v)
Returns SWT derived scaled-up value v, based on DPIUtil#getDeviceZoom() only, not considering higher-...
static AbstractGraphicsDevice getDevice(final Control swtControl)
static AbstractGraphicsScreen getScreen(final AbstractGraphicsDevice device, final int screen)
static int getNativeVisualID(final AbstractGraphicsDevice device, final long windowHandle)
static void setRealized(final Control swtControl, final boolean realize)
abstract EDTUtil getEDTUtil()
abstract Display getDisplay()
SWT Canvas containing a NEWT Window using native parenting.
NativeWindow getNativeWindow()
Returns the associated NativeWindow of this NativeWindowHolder, which is identical to getNativeSurfac...
static NewtCanvasSWT create(final Composite parent, final int style, final Window child)
Creates an instance using NewtCanvasSWT(Composite, int, Window) on the SWT thread.
void dispose()
Destroys this resource:
boolean setParent(final Composite parent)
void setBounds(final int x, final int y, final int width, final int height)
NewtCanvasSWT(final Composite parent, final int style, final Window child)
Instantiates a NewtCanvas with a NEWT child.
WindowClosingMode getDefaultCloseOperation()
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
Window setNEWTChild(final Window newChild)
Sets a new NEWT child, provoking reparenting.
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
Window closing mode if triggered by toolkit close operation.
DISPOSE_ON_CLOSE
Dispose resources on native window close operation.
A marker interface describing a graphics configuration, visual, or pixel format in a toolkit-independ...
AbstractGraphicsScreen getScreen()
Return the screen this graphics configuration is valid for.
A interface describing a graphics device in a toolkit-independent manner.
boolean close()
Optionally closing the device if handle is not null.
long getHandle()
Returns the native handle of the underlying native device, if such thing exist.
boolean open()
Optionally [re]opening the device if handle is null.
A interface describing a graphics screen in a toolkit-independent manner.
int getIndex()
Returns the screen index this graphics screen is valid for.
AbstractGraphicsDevice getDevice()
Return the device this graphics configuration is valid for.
Specifies an immutable set of capabilities that a window's rendering context must support,...
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
long getSurfaceHandle()
Returns the handle to the surface for this NativeSurface.
Accessor interface for implementing classes with ownership of a NativeWindow via an is-a or has-a rel...
Extend the NativeSurface interface with windowing information such as window-handle,...
boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
Protocol for handling window closing events.
WindowClosingMode setDefaultCloseOperation(WindowClosingMode op)
Immutable insets representing rectangular window decoration insets on all four edges in window units.
Specifying NEWT's Window functionality:
Definition: Window.java:115
void sendWindowEvent(int eventType)
Send a WindowEvent to all WindowListener.
void setKeyboardFocusHandler(KeyListener l)
Sets a KeyListener allowing focus traversal with a covered window toolkit like AWT.
ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints)
Change this window's parent window.
boolean windowRepaint(int x, int y, int width, int height)
Trigger window repaint while passing the dirty region in pixel units.
void requestFocus()
Request focus for this native window.
void setFocusAction(FocusRunnable focusAction)
Sets a FocusRunnable, which FocusRunnable#run() method is executed before the native focus is request...
void setSize(int width, int height)
Sets the size of the window's client area in window units, excluding decorations.
void setVisible(boolean visible)
Calls setVisible(true, visible), i.e.
void setPosition(int x, int y)
Sets the location of the window's client area excluding insets (window decorations) in window units.
void destroy()
Destroys this window incl.releasing all related resources.