JOGL v2.6.0-rc-20250712
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 * Set's the NEWT {@link Window}'s size using {@link Window#setSize(int, int)}.
182 * <p>
183 * For all non-native DPI autoscale platforms method uses {@link SWTAccessor#deviceZoomScaleUp(Point)},
184 * which multiplies the given {@link Rectangle} size with {@link SWTAccessor#getDeviceZoomScalingFactor()}
185 * to emulate DPI scaling, see Bug 1422.
186 * </p>
187 * <p>
188 * Otherwise this method uses the given {@link Rectangle} as-is.
189 * </p>
190 * <p>
191 * Currently native DPI autoscale platforms are
192 * <ul>
193 * <li>{@link SWTAccessor#isOSX}</li>
194 * </ul>
195 * hence the emulated DPI scaling is enabled for all other platforms.
196 * </p>
197 * @param r containing desired size
198 */
199 private final void setNewtChildSize(final org.eclipse.swt.graphics.Rectangle r) {
200 if( !SWTAccessor.isOSX ) {
201 final Point p = SWTAccessor.deviceZoomScaleUp(new Point(r.width, r.height));
202 newtChild.setSize(p.getX(), p.getY());
203 } else {
204 newtChild.setSize(r.width, r.height);
205 }
206 }
207 /**
208 * Return scaled-up value {@code scaleUp} using {@link SWTAccessor#deviceZoomScaleUp(int)}
209 * for all non-native DPI autoscale platforms, currently !{@link SWTAccessor#isOSX}.
210 * <p>
211 * Return passthrough value {@code passthrough} unchanged
212 * for all native DPI autoscale platforms, currently {@link SWTAccessor#isOSX}.
213 * </p>
214 * <p>
215 * See {@link #setNewtChildSize(Rectangle)}
216 * </p>
217 * @param scaleUp value to be used for non-native DPI autoscale platforms for upscale
218 * @param passthrough value to be used for native DPI autoscale platforms for passthrough
219 */
220 private final int newtScaleUp(final int scaleUp, final int passthrough) {
221 if( !SWTAccessor.isOSX ) {
222 return SWTAccessor.deviceZoomScaleUp(scaleUp);
223 } else {
224 return passthrough;
225 }
226 }
227 private final Listener swtListener = new Listener () {
228 @Override
229 public void handleEvent (final Event event) {
230 switch (event.type) {
231 case SWT.Paint:
232 if( DEBUG ) {
233 System.err.println(shortName()+".Event.PAINT, "+event);
234 // 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
235 // System.err.println(shortName()+".Event.PAINT, "+newtChild.getDelegatedWindow().toSimpleString());
236 }
237 if( validateNative() && newtChildReady ) {
238 if( postSetSize ) {
239 setNewtChildSize(clientAreaWindow);
240 postSetSize = false;
241 }
242 if( postSetPos ) {
243 newtChild.setPosition(clientAreaWindow.x, clientAreaWindow.y);
244 postSetPos = false;
245 }
246 newtChild.windowRepaint(0, 0, clientAreaPixels.width, clientAreaPixels.height);
247 }
248 break;
249 case SWT.Move:
250 if( DEBUG ) {
251 System.err.println(shortName()+".Event.MOVE, "+event);
252 // System.err.println(shortName()+".Event.MOVE, "+newtChild.getDelegatedWindow().toSimpleString());
253 }
254 break;
255 case SWT.Show:
256 if( DEBUG ) {
257 System.err.println(shortName()+".Event.SHOW, "+event);
258 // System.err.println(shortName()+".Event.SHOW, "+newtChild.getDelegatedWindow().toSimpleString());
259 }
260 if( newtChildReady ) {
261 newtChild.setVisible(true /* wait */, true /* visible */);
262 }
263 break;
264 case SWT.Hide:
265 if( DEBUG ) {
266 System.err.println(shortName()+".Event.HIDE, "+event);
267 // System.err.println(shortName()+".Event.HIDE, "+newtChild.getDelegatedWindow().toSimpleString());
268 }
269 if( newtChildReady ) {
270 newtChild.setVisible(true /* wait */, false /* visible */);
271 }
272 break;
273 case SWT.Resize:
274 if( DEBUG ) {
275 System.err.println(shortName()+".Event.RESIZE, "+event);
276 // System.err.println(shortName()+".Event.RESIZE, "+newtChild.getDelegatedWindow().toSimpleString());
277 }
278 if( isNativeValid() ) {
279 // ensure this is being called if already valid
281 } else {
283 }
284 break;
285 case SWT.Dispose:
286 if( DEBUG ) {
287 System.err.println(shortName()+".Event.DISPOSE, "+event);
288 // 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
289 // System.err.println(shortName()+".Event.DISPOSE, "+newtChild.getDelegatedWindow().toSimpleString());
290 }
291 NewtCanvasSWT.this.dispose();
292 break;
293 case SWT.Activate: // receives focus ??
294 if( DEBUG ) {
295 System.err.println(shortName()+".Event.ACTIVATE, "+event);
296 // System.err.println(shortName()+".Event.ACTIVATE, "+newtChild.getDelegatedWindow().toSimpleString());
297 }
298 break;
299 case SWT.Deactivate: // lost focus ??
300 if( DEBUG ) {
301 System.err.println(shortName()+".Event.DEACTIVATE, "+event);
302 // System.err.println(shortName()+".Event.DEACTIVATE, "+newtChild.getDelegatedWindow().toSimpleString());
303 }
304 break;
305 case SWT.FocusIn: // receives focus
306 if( DEBUG ) {
307 System.err.println(shortName()+".Event.FOCUS_IN, "+event);
308 // System.err.println(shortName()+".Event.FOCUS_IN, "+newtChild.getDelegatedWindow().toSimpleString());
309 }
310 if( newtChildReady ) {
311 newtChild.requestFocus(false /* wait */);
312 }
313 break;
314 case SWT.FocusOut: // lost focus
315 if( DEBUG ) {
316 System.err.println(shortName()+".Event.FOCUS_OUT, "+event);
317 // System.err.println(shortName()+".Event.FOCUS_OUT, "+newtChild.getDelegatedWindow().toSimpleString());
318 }
319 // we lack newtChild.releaseFocus(..) as this should be handled by the WM
320 break;
321 default:
322 if( DEBUG ) {
323 System.err.println(shortName()+".Event.misc: "+event.type+", "+event);
324 // System.err.println(shortName()+".Event.misc: "+newtChild.getDelegatedWindow().toSimpleString());
325 }
326 }
327 }
328 };
329
330 @Override
331 public void setBounds(final int x, final int y, final int width, final int height) {
332 super.setBounds(x, y, width, height);
333 if( DEBUG ) {
334 System.err.println(shortName()+".setBounds: "+x+"/"+y+" "+width+"x"+height);
335 }
337 }
338
339 protected final boolean isNativeValid() { return null != nativeWindow; }
340
341 protected final boolean validateNative() {
342 if( null != nativeWindow ) {
343 return true; // already valid
344 }
346 final org.eclipse.swt.graphics.Rectangle nClientAreaWindow = clientAreaWindow;
347 if(0 >= nClientAreaWindow.width || 0 >= nClientAreaWindow.height) {
348 return false;
349 }
350 screen.getDevice().open();
351
352 /* Native handle for the control, used to associate with GLContext */
353 final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
354 final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
355 final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
356 if(DEBUG) {
357 System.err.println(shortName()+".validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
358 }
359 if( visualIDValid ) {
360 /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
361 * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
362 final CapabilitiesImmutable caps = new Capabilities();
364 final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
365 if(DEBUG) {
366 System.err.println(shortName()+".validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
367 // Thread.dumpStack();
368 }
369 if (null == config) {
370 throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
371 }
372
373 nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
374 reparentWindow( true );
375 }
376 return null != nativeWindow;
377 }
378
379 protected final void updatePosSizeCheck() {
380 final org.eclipse.swt.graphics.Rectangle oClientAreaWindow = clientAreaWindow;
381 final org.eclipse.swt.graphics.Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
382 final org.eclipse.swt.graphics.Rectangle nClientAreaWindow = getClientArea();
383 final boolean sizeChanged, posChanged;
384 {
385 sizeChanged = nClientAreaWindow.width != oClientAreaWindow.width || nClientAreaWindow.height != oClientAreaWindow.height;
386 posChanged = nClientAreaWindow.x != oClientAreaWindow.x || nClientAreaWindow.y != oClientAreaWindow.y;
387 if( sizeChanged || posChanged ) {
388 clientAreaPixels = nClientAreaPixels;
389 clientAreaWindow = nClientAreaWindow;
390 if( 0 < nClientAreaWindow.width && 0 < nClientAreaWindow.height ) {
391 pixelScale[0] = nClientAreaPixels.width / nClientAreaWindow.width;
392 pixelScale[1] = nClientAreaPixels.height / nClientAreaWindow.height;
393 } else {
394 pixelScale[0] = 1f;
395 pixelScale[1] = 1f;
396 }
397 }
398 }
399 if(DEBUG) {
400 final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
401 System.err.println(shortName()+".updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+
402 ", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+
403 ", pixel "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+
404 ", window "+nClientAreaWindow.x+"/"+nClientAreaWindow.y+" "+nClientAreaWindow.width+"x"+nClientAreaWindow.height+
405 ", scale "+pixelScale[0]+"/"+pixelScale[1]+
406 " - surfaceHandle 0x"+Long.toHexString(nsh));
407 }
408 if( sizeChanged ) {
409 if( newtChildReady ) {
410 setNewtChildSize(nClientAreaWindow);
411 newtChild.setSurfaceScale(pixelScale);
412 } else {
413 postSetSize = true;
414 }
415 }
416 if( posChanged ) {
417 if( newtChildReady ) {
418 newtChild.setPosition(nClientAreaWindow.x, nClientAreaWindow.y);
419 } else {
420 postSetPos = true;
421 }
422 }
423 if( DEBUG ) {
424 System.err.println(shortName()+".updatePosSizeCheck.X END");
425 }
426 }
427
428 @Override
429 public void update() {
430 // don't paint background etc .. nop avoids flickering
431 }
432
433 /**
434 * Destroys this resource:
435 * <ul>
436 * <li> Make the NEWT Child invisible </li>
437 * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
438 * <li> Issues <code>destroy()</code> on the NEWT Child</li>
439 * <li> Remove reference to the NEWT Child</li>
440 * </ul>
441 * @see Window#destroy()
442 * @throws SWTException If this method is not called
443 * {@link SWTAccessor#isOnSWTThread(org.eclipse.swt.widgets.Display) from the SWT thread},
444 * an {@link SWTException} is thrown for compliance across platforms.
445 * User may utilize {@link SWTAccessor#invokeOnSWTThread(org.eclipse.swt.widgets.Display, boolean, Runnable)}.
446 */
447 @Override
448 public void dispose() throws SWTException {
449 if( !SWTAccessor.isOnSWTThread( getDisplay() ) ) {
450 throw new SWTException("Invalid thread access");
451 }
452 removeListener (SWT.Paint, swtListener);
453 removeListener (SWT.Move, swtListener);
454 removeListener (SWT.Show, swtListener);
455 removeListener (SWT.Hide, swtListener);
456 removeListener (SWT.Resize, swtListener);
457 removeListener (SWT.Dispose, swtListener);
458 removeListener (SWT.Activate, swtListener);
459 removeListener (SWT.Deactivate, swtListener);
460 removeListener (SWT.FocusIn, swtListener);
461 removeListener (SWT.FocusOut, swtListener);
462
463 if( null != newtChild ) {
464 if(DEBUG) {
465 System.err.println(shortName()+".dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
466 ",\n\t"+newtChild);
467 }
468 configureNewtChild(false);
469 newtChild.setVisible(false);
470 newtChild.reparentWindow(null, -1, -1, 0 /* hint */);
471 newtChild.destroy();
472 newtChild = null;
473 }
474 screen.getDevice().close();
475 nativeWindow = null;
476 super.dispose();
477 }
478
479 /**
480 * {@inheritDoc}
481 * @return this SWT Canvas {@link NativeWindow} representation, may be null in case it has not been realized
482 */
483 @Override
484 public NativeWindow getNativeWindow() { return nativeWindow; }
485
486 /**
487 * {@inheritDoc}
488 * @return this SWT Canvas {@link NativeSurface} representation, may be null in case it has not been realized
489 */
490 @Override
491 public NativeSurface getNativeSurface() { return nativeWindow; }
492
493 @Override
495 return closingMode;
496 }
497
498 @Override
500 return closingMode; // TODO: implement!
501 }
502
503
504 boolean isParent() {
505 return null!=newtChild ;
506 }
507
508 boolean isFullscreen() {
509 return null != newtChild && newtChild.isFullscreen();
510 }
511
512 /**
513 * Sets a new NEWT child, provoking reparenting.
514 * <p>
515 * A previously detached <code>newChild</code> will be released to top-level status
516 * and made invisible.
517 * </p>
518 * <p>
519 * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
520 * produced much cleaner visual results.
521 * </p>
522 * <p>
523 * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
524 * via {@link Display#setEDTUtil(EDTUtil)}.
525 * </p>
526 * @return the previous attached newt child.
527 *
528 * @throws SWTException If this method is not called
529 * {@link SWTAccessor#isOnSWTThread(org.eclipse.swt.widgets.Display) from the SWT thread},
530 * an {@link SWTException} is thrown for compliance across platforms.
531 * User may utilize {@link SWTAccessor#invokeOnSWTThread(org.eclipse.swt.widgets.Display, boolean, Runnable)}.
532 */
533 public Window setNEWTChild(final Window newChild) throws SWTException {
534 if( !SWTAccessor.isOnSWTThread( getDisplay() ) ) {
535 throw new SWTException("Invalid thread access");
536 }
537
538 // if( org.eclipse.swt.widgets.Display.s)
539 final Window prevChild = newtChild;
540 if(DEBUG) {
541 System.err.println(shortName()+".setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
542 }
543 // remove old one
544 if(null != newtChild) {
545 reparentWindow( false );
546 newtChild = null;
547 }
548 // add new one, reparent only if ready
549 newtChild = newChild;
550 if(null != nativeWindow && null != newChild) {
551 reparentWindow( true );
552 }
553 return prevChild;
554 }
555
556 /** @return the current NEWT child */
558 return newtChild;
559 }
560
561 @Override
562 public boolean setParent(final Composite parent) {
563 return super.setParent(parent);
564 }
565
566 /* package */ void configureNewtChild(final boolean attach) {
567 newtChildReady = attach;
568 if( null != newtChild ) {
569 newtChild.setKeyboardFocusHandler(null);
570 if(attach) {
571 newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
572 } else {
573 newtChild.setFocusAction(null);
574 newtChild.setDefaultCloseOperation(newtChildClosingMode);
575 }
576 }
577 }
578
579 void reparentWindow(final boolean add) {
580 if( null == newtChild ) {
581 return; // nop
582 }
583 if(DEBUG) {
584 System.err.println(shortName()+".reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
585 }
586
587 newtChild.setFocusAction(null); // no AWT focus traversal ..
588 if(add) {
590
591 // set SWT EDT and start it
592 {
593 final Display newtDisplay = newtChild.getScreen().getDisplay();
594 final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay());
595 edtUtil.start();
596 newtDisplay.setEDTUtil( edtUtil );
597 }
598
599 setNewtChildSize(clientAreaWindow);
600 newtChild.reparentWindow(nativeWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
601 newtChild.setPosition(clientAreaWindow.x, clientAreaWindow.y);
602 newtChild.setVisible(true);
603 configureNewtChild(true);
604 newtChild.setSurfaceScale(pixelScale); // ensure this to be set after creation, otherwise updatePosSizeCheck is being used
605 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
606
607 // force this SWT Canvas to be focus-able,
608 // since it is completely covered by the newtChild (z-order).
609 setEnabled(true);
610 } else {
611 configureNewtChild(false);
612 newtChild.setVisible(false);
613 newtChild.reparentWindow(null, -1, -1, 0 /* hints */);
614 }
615 if(DEBUG) {
616 System.err.println(shortName()+".reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
617 }
618 }
619
620 private final void requestFocusNEWTChild() {
621 if( newtChildReady ) {
622 newtChild.setFocusAction(null);
623 newtChild.requestFocus();
624 }
625 }
626
627 @Override
628 public boolean forceFocus() {
629 final boolean res = NewtCanvasSWT.super.forceFocus();
630 requestFocusNEWTChild();
631 return res;
632 }
633
634 private class SWTNativeWindow implements NativeWindow {
635 private final AbstractGraphicsConfiguration config;
636 private final long nativeWindowHandle;
637 private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
638
639 public SWTNativeWindow(final AbstractGraphicsConfiguration config, final long nativeWindowHandle) {
640 this.config = config;
641 this.nativeWindowHandle = nativeWindowHandle;
642 if( SWTAccessor.isOSX ) {
643 this.insets = OSXUtil.GetInsets(nativeWindowHandle);
644 } else {
645 this.insets = new Insets(0, 0, 0, 0);
646 }
647 }
648
649 @Override
650 public RecursiveLock getLock() { return null; }
651
652 @Override
653 public int lockSurface() throws NativeWindowException, RuntimeException {
654 return NativeSurface.LOCK_SUCCESS;
655 }
656
657 @Override
658 public void unlockSurface() { }
659
660 @Override
661 public boolean isSurfaceLockedByOtherThread() {
662 return false;
663 }
664
665 @Override
666 public Thread getSurfaceLockOwner() {
667 return null;
668 }
669
670 @Override
671 public boolean surfaceSwap() {
672 return false;
673 }
674
675 @Override
676 public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
677
678 @Override
679 public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
680 }
681
682 @Override
683 public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
684
685 @Override
686 public long getSurfaceHandle() {
687 return 0;
688 }
689
690 @Override
691 public int getX() {
692 return 0;
693 }
694
695 @Override
696 public int getY() {
697 return 0;
698 }
699
700 @Override
701 public int getWidth() {
702 return newtScaleUp(clientAreaWindow.width, clientAreaWindow.width);
703 }
704
705 @Override
706 public int getHeight() {
707 return newtScaleUp(clientAreaWindow.height, clientAreaWindow.height);
708 }
709
710 @Override
711 public final com.jogamp.nativewindow.util.Rectangle getBounds() {
712 return new com.jogamp.nativewindow.util.Rectangle(getX(), getY(), getWidth(), getHeight());
713 }
714
715 @Override
716 public final com.jogamp.nativewindow.util.Rectangle getSurfaceBounds() {
717 return new com.jogamp.nativewindow.util.Rectangle(getX(), getY(),
718 getSurfaceWidth(), getSurfaceHeight());
719 }
720
721 @Override
722 public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
723 pixelUnitsAndResult[0] /= pixelScale[0];
724 pixelUnitsAndResult[1] /= pixelScale[1];
725 return pixelUnitsAndResult;
726 }
727
728 @Override
729 public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
730 windowUnitsAndResult[0] *= pixelScale[0];
731 windowUnitsAndResult[1] *= pixelScale[1];
732 return windowUnitsAndResult;
733 }
734
735 @Override
736 public int getSurfaceWidth() {
737 return newtScaleUp(clientAreaWindow.width, clientAreaPixels.width);
738 }
739
740 @Override
741 public int getSurfaceHeight() {
742 return newtScaleUp(clientAreaWindow.height, clientAreaPixels.height);
743 }
744
745 @Override
746 public final NativeSurface getNativeSurface() { return this; }
747
748 @Override
749 public AbstractGraphicsConfiguration getGraphicsConfiguration() {
750 return config;
751 }
752
753 @Override
754 public long getDisplayHandle() {
755 return config.getScreen().getDevice().getHandle();
756 }
757
758 @Override
759 public int getScreenIndex() {
760 return config.getScreen().getIndex();
761 }
762
763 @Override
764 public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { }
765
766 @Override
767 public void destroy() { }
768
769 @Override
770 public NativeWindow getParent() {
771 return null;
772 }
773
774 @Override
775 public long getWindowHandle() {
776 return nativeWindowHandle;
777 }
778
779 @Override
780 public InsetsImmutable getInsets() {
781 return insets;
782 }
783
784 @Override
785 public Point getLocationOnScreen(final Point point) {
786 final Point los = NativeWindowFactory.getLocationOnScreen(this); // client window location on screen
787 if(null!=point) {
788 return point.translate(los);
789 } else {
790 return los;
791 }
792 }
793
794 @Override
795 public boolean hasFocus() {
796 return isFocusControl();
797 }
798 };
799
800 static String newtWinHandleToHexString(final Window w) {
801 return null != w ? toHexString(w.getWindowHandle()) : "nil";
802 }
803 static String toHexString(final long l) {
804 return "0x"+Long.toHexString(l);
805 }
806}
807
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.