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