diff options
author | Sven Gothel <[email protected]> | 2012-12-04 07:10:59 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-12-04 07:10:59 +0100 |
commit | 7cb6cf2a9708d3f4e06f2215eb0d06b00fa6cd15 (patch) | |
tree | 246a97d17f229bf694e9cc82cac00eea9278d6d6 /src/nativewindow | |
parent | ceadea1c11cfeecfcafe3dfa76aafd8e915c0076 (diff) |
SWT GLCanvas: Fix sporadic drop of redraw on X11 _and_ allow using custom GLCapabilities on X11 (feature complete)
To allow custom GLCapabilities, we had to use native parenting on X11 w/ a new child window.
The desired visualID chosen by the users GLCapabilities is passed to the new child window.
The redraw drops must be caused by the original GDK or the new child GDK window.
Now we use a plain X11 child window similar to NEWT's X11 window and NewtCanvasSWT,
which doesn't expose this bug.
(Note: SWTAccessor/GLCanvas still contains the uncommented GDK code path for further inspection, if desired)
Also added SWTNewtEventFactory to test event handling on the SWT GLCanvas w/ GearsES2.
TestSWTJOGLGLCanvas01GLn tests custom GLCapabilities now.
SWTEDTUtil has been moved to private: com.jogamp.newt.swt -> jogamp.newt.swt.
Diffstat (limited to 'src/nativewindow')
3 files changed, 352 insertions, 120 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index e208cfb28..eba26c7d3 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,6 +34,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import org.eclipse.swt.graphics.GCData; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import javax.media.nativewindow.AbstractGraphicsScreen; @@ -59,12 +60,22 @@ public class SWTAccessor { private static final Field swt_control_handle; private static final boolean swt_uses_long_handles; + private static Object swt_osx_init = new Object(); + private static Field swt_osx_control_view = null; + private static Field swt_osx_view_id = null; + + private static final String nwt; + private static final boolean isOSX; + private static final boolean isWindows; + private static final boolean isX11; + private static final boolean isX11GTK; + // X11/GTK, Windows/GDI, .. private static final String str_handle = "handle"; // OSX/Cocoa - private static final String str_view = "view"; // OSX - private static final String str_id = "id"; // OSX + private static final String str_osx_view = "view"; // OSX + private static final String str_osx_id = "id"; // OSX // static final String str_NSView = "org.eclipse.swt.internal.cocoa.NSView"; private static final Method swt_control_internal_new_GC; @@ -73,9 +84,10 @@ public class SWTAccessor { private static final String str_internal_dispose_GC = "internal_dispose_GC"; private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS"; - private static final Class<?> OS_gtk_class; + public static final Class<?> OS_gtk_class; private static final String str_OS_gtk_version = "GTK_VERSION"; - private static final VersionNumber OS_gtk_version; + public static final VersionNumber OS_gtk_version; + private static final Method OS_gtk_widget_realize; private static final Method OS_gtk_widget_unrealize; // optional (removed in SWT 4.3) private static final Method OS_GTK_WIDGET_WINDOW; @@ -85,6 +97,8 @@ public class SWTAccessor { private static final Method OS_gdk_window_get_display; private static final Method OS_gdk_x11_drawable_get_xid; private static final Method OS_gdk_x11_window_get_xid; + private static final Method OS_gdk_window_set_back_pixmap; + private static final String str_gtk_widget_realize = "gtk_widget_realize"; private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize"; private static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW"; @@ -94,6 +108,7 @@ public class SWTAccessor { private static final String str_gdk_window_get_display = "gdk_window_get_display"; private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid"; private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid"; + private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap"; private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0); private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0); @@ -108,23 +123,25 @@ public class SWTAccessor { } static { - Field f = null; - AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { NativeWindowFactory.initSingleton(); // last resort .. return null; } } ); - final String nwt = NativeWindowFactory.getNativeWindowType(false); - - if(NativeWindowFactory.TYPE_MACOSX != nwt ) { + nwt = NativeWindowFactory.getNativeWindowType(false); + isOSX = NativeWindowFactory.TYPE_MACOSX == nwt; + isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt; + isX11 = NativeWindowFactory.TYPE_X11 == nwt; + + Field f = null; + if( !isOSX ) { try { f = Control.class.getField(str_handle); } catch (Exception ex) { throw new NativeWindowException(ex); } - } + } swt_control_handle = f; // maybe null ! boolean ulh; @@ -158,31 +175,32 @@ public class SWTAccessor { Class<?> c=null; VersionNumber _gtk_version = new VersionNumber(0, 0, 0); - Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null; - Class<?> handleType = swt_uses_long_handles ? long.class : int.class ; - if( NativeWindowFactory.TYPE_X11 == nwt ) { + Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null; + final Class<?> handleType = swt_uses_long_handles ? long.class : int.class ; + if( isX11 ) { // mandatory try { c = ReflectionUtil.getClass(str_OS_gtk_class, false, SWTAccessor.class.getClassLoader()); Field field_OS_gtk_version = c.getField(str_OS_gtk_version); _gtk_version = GTK_VERSION(field_OS_gtk_version.getInt(null)); m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType); - if( _gtk_version.compareTo(GTK_VERSION_2_14_0) < 0 ) { - m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType); - } else { + if (_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) { m4 = c.getDeclaredMethod(str_gtk_widget_get_window, handleType); - } - if( _gtk_version.compareTo(GTK_VERSION_2_24_0) < 0 ) { - m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType); } else { + m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType); + } + if (_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) { m6 = c.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType); - m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType); - } - if( _gtk_version.compareTo(GTK_VERSION_3_0_0) < 0 ) { - m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType); + m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType); } else { + m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType); + } + if (_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) { m9 = c.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType); + } else { + m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType); } + ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class); } catch (Exception ex) { throw new NativeWindowException(ex); } // optional try { @@ -200,25 +218,31 @@ public class SWTAccessor { OS_gdk_window_get_display = m7; OS_gdk_x11_drawable_get_xid = m8; OS_gdk_x11_window_get_xid = m9; + OS_gdk_window_set_back_pixmap = ma; + + isX11GTK = isX11 && null != OS_gtk_class; if(DEBUG) { System.err.println("SWTAccessor.<init>: GTK Version: "+OS_gtk_version); } } - - - static Object getIntOrLong(long arg) { + + private static Number getIntOrLong(long arg) { if(swt_uses_long_handles) { return new Long(arg); } return new Integer((int) arg); } - static void callStaticMethodL2V(Method m, long arg) { + private static void callStaticMethodL2V(Method m, long arg) { ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) }); } - static long callStaticMethodL2L(Method m, long arg) { + private static void callStaticMethodLLZ2V(Method m, long arg0, long arg1, boolean arg3) { + ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1), Boolean.valueOf(arg3) }); + } + + private static long callStaticMethodL2L(Method m, long arg) { Object o = ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) }); if(o instanceof Number) { return ((Number)o).longValue(); @@ -226,13 +250,73 @@ public class SWTAccessor { throw new InternalError("SWT method "+m.getName()+" didn't return int or long but "+o.getClass()); } } - + + // + // Public properties + // + public static boolean isUsingLongHandles() { return swt_uses_long_handles; } + public static boolean useX11GTK() { return isX11GTK; } public static VersionNumber GTK_VERSION() { return OS_gtk_version; } + // + // Common GTK + // + + public static long gdk_widget_get_window(long handle) { + final long window; + if (OS_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) { + window = callStaticMethodL2L(OS_gtk_widget_get_window, handle); + } else { + window = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle); + } + if(0 == window) { + throw new NativeWindowException("Null gtk-window-handle of SWT handle 0x"+Long.toHexString(handle)); + } + return window; + } + + public static long gdk_window_get_xdisplay(long window) { + final long xdisplay; + if (OS_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) { + final long display = callStaticMethodL2L(OS_gdk_window_get_display, window); + if(0 == display) { + throw new NativeWindowException("Null display-handle of gtk-window-handle 0x"+Long.toHexString(window)); + } + xdisplay = callStaticMethodL2L(OS_gdk_x11_display_get_xdisplay, display); + } else { + xdisplay = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, window); + } + if(0 == xdisplay) { + throw new NativeWindowException("Null x11-display-handle of gtk-window-handle 0x"+Long.toHexString(window)); + } + return xdisplay; + } + + public static long gdk_window_get_xwindow(long window) { + final long xWindow; + if (OS_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) { + xWindow = callStaticMethodL2L(OS_gdk_x11_window_get_xid, window); + } else { + xWindow = callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, window); + } + if(0 == xWindow) { + throw new NativeWindowException("Null x11-window-handle of gtk-window-handle 0x"+Long.toHexString(window)); + } + return xWindow; + } + + public static void gdk_window_set_back_pixmap(long window, long pixmap, boolean parent_relative) { + callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative); + } + + // + // Common any toolkit + // + /** * @param swtControl the SWT Control to retrieve the native widget-handle from * @return the native widget-handle @@ -240,15 +324,21 @@ public class SWTAccessor { */ public static long getHandle(Control swtControl) throws NativeWindowException { long h = 0; - if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { - try { - Field fView = Control.class.getField(str_view); - Object view = fView.get(swtControl); - Field fId = view.getClass().getField(str_id); - h = fId.getLong(view); - } catch (Exception ex) { - throw new NativeWindowException(ex); - } + if( isOSX ) { + synchronized(swt_osx_init) { + try { + if(null == swt_osx_view_id) { + swt_osx_control_view = Control.class.getField(str_osx_view); + Object view = swt_osx_control_view.get(swtControl); + swt_osx_view_id = view.getClass().getField(str_osx_id); + h = swt_osx_view_id.getLong(view); + } else { + h = swt_osx_view_id.getLong( swt_osx_control_view.get(swtControl) ); + } + } catch (Exception ex) { + throw new NativeWindowException(ex); + } + } } else { try { h = swt_control_handle.getLong(swtControl); @@ -283,49 +373,6 @@ public class SWTAccessor { } } - private static long gdk_x11_display_get_xdisplay(long window) { - final long xdisplay; - if ( OS_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0 ) { - final long display = callStaticMethodL2L(OS_gdk_window_get_display, window); - if(0 == display) { - throw new NativeWindowException("Null display-handle of gtk-window-handle 0x"+Long.toHexString(window)); - } - xdisplay = callStaticMethodL2L(OS_gdk_x11_display_get_xdisplay, display); - } else { - xdisplay = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, window); - } - if(0 == xdisplay) { - throw new NativeWindowException("Null x11-display-handle of gtk-window-handle 0x"+Long.toHexString(window)); - } - return xdisplay; - } - - private static long gdk_widget_get_window(long handle) { - final long window; - if ( OS_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0 ) { - window = callStaticMethodL2L(OS_gtk_widget_get_window, handle); - } else { - window = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle); - } - if(0 == window) { - throw new NativeWindowException("Null gtk-window-handle of SWT handle 0x"+Long.toHexString(handle)); - } - return window; - } - - private static long gdk_window_get_xwindow(long window) { - final long xwindow; - if ( OS_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0 ) { - xwindow = callStaticMethodL2L(OS_gdk_x11_window_get_xid, window); - } else { - xwindow = callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, window); - } - if(0 == xwindow) { - throw new NativeWindowException("Null x11-window-handle of gtk-window-handle 0x"+Long.toHexString(window)); - } - return xwindow; - } - /** * @param swtControl the SWT Control to retrieve the native device handle from * @return the AbstractGraphicsDevice w/ the native device handle @@ -333,43 +380,49 @@ public class SWTAccessor { * @throws UnsupportedOperationException if the windowing system is not supported */ public static AbstractGraphicsDevice getDevice(Control swtControl) throws NativeWindowException, UnsupportedOperationException { - long handle = getHandle(swtControl); - if( null != OS_gtk_class ) { - final long xdisplay0 = gdk_x11_display_get_xdisplay( gdk_widget_get_window( handle ) ); - // final String displayName = X11Lib.XDisplayString(xdisplay0); - // final long xdisplay1 = X11Util.openDisplay(displayName); - // return new X11GraphicsDevice(xdisplay1, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */); + final long handle = getHandle(swtControl); + if( isX11GTK ) { + final long xdisplay0 = gdk_window_get_xdisplay( gdk_widget_get_window( handle ) ); return new X11GraphicsDevice(xdisplay0, AbstractGraphicsDevice.DEFAULT_UNIT, false /* owner */); } - final String nwt = NativeWindowFactory.getNativeWindowType(false); - if( NativeWindowFactory.TYPE_WINDOWS == nwt ) { + if( isWindows ) { return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); } - if( NativeWindowFactory.TYPE_MACOSX == nwt ) { + if( isOSX ) { return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); } + /** + * + * @param device + * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen + * @return + * @throws UnsupportedOperationException + */ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) throws UnsupportedOperationException { - if( null != OS_gtk_class ) { - return new X11GraphicsScreen((X11GraphicsDevice)device, screen); + if( isX11 ) { + X11GraphicsDevice x11Device = (X11GraphicsDevice)device; + if(0 > screen) { + screen = x11Device.getDefaultScreen(); + } + return new X11GraphicsScreen(x11Device, screen); + } + if(0 > screen) { + screen = 0; // FIXME: Needs native API utilization } - final String nwt = NativeWindowFactory.getNativeWindowType(false); - if( NativeWindowFactory.TYPE_WINDOWS == nwt || - NativeWindowFactory.TYPE_MACOSX == nwt ) { + if( isWindows || isOSX ) { return new DefaultGraphicsScreen(device, screen); } throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); } public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) { - if( null != OS_gtk_class ) { + if( isX11 ) { return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); } - final String nwt = NativeWindowFactory.getNativeWindowType(false); - if( NativeWindowFactory.TYPE_WINDOWS == nwt || - NativeWindowFactory.TYPE_MACOSX == nwt ) { + if( isWindows || isOSX ) { return VisualIDHolder.VID_UNDEFINED; } throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); @@ -383,12 +436,13 @@ public class SWTAccessor { */ public static long getWindowHandle(Control swtControl) throws NativeWindowException, UnsupportedOperationException { final long handle = getHandle(swtControl); - if( null != OS_gtk_class ) { + if(0 == handle) { + throw new NativeWindowException("Null SWT handle of SWT control "+swtControl); + } + if( isX11GTK ) { return gdk_window_get_xwindow( gdk_widget_get_window( handle ) ); } - final String nwt = NativeWindowFactory.getNativeWindowType(false); - if( NativeWindowFactory.TYPE_WINDOWS == nwt || - NativeWindowFactory.TYPE_MACOSX == nwt ) { + if( isWindows || isOSX ) { return handle; } throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); @@ -407,7 +461,7 @@ public class SWTAccessor { throw new InternalError("SWT internal_new_GC did not return int or long but "+o[0].getClass()); } } - + public static void disposeGC(final Control swtControl, final long gc, final GCData gcData) { invoke(true, new Runnable() { public void run() { @@ -437,7 +491,7 @@ public class SWTAccessor { * @see Platform#getOSType() */ public static void invoke(boolean wait, Runnable runnable) { - if( Platform.OS_TYPE == Platform.OSType.MACOS ) { + if( isOSX ) { // Use SWT main thread! Only reliable config w/ -XStartOnMainThread !? OSXUtil.RunOnMainThread(wait, runnable); } else { @@ -445,4 +499,85 @@ public class SWTAccessor { } } + // + // Specific X11 GTK ChildWindow - Using plain X11 native parenting (works well) + // + + public static long createCompatibleX11ChildWindow(AbstractGraphicsScreen screen, Control swtControl, int visualID, int width, int height) { + final long handle = getHandle(swtControl); + final long parentWindow = gdk_widget_get_window( handle ); + gdk_window_set_back_pixmap (parentWindow, 0, false); + + final long x11ParentHandle = gdk_window_get_xwindow(parentWindow); + final long x11WindowHandle = X11Lib.CreateWindow(x11ParentHandle, screen.getDevice().getHandle(), screen.getIndex(), visualID, width, height, true, true); + + return x11WindowHandle; + } + + public static void resizeX11Window(AbstractGraphicsDevice device, Rectangle clientArea, long x11Window) { + X11Lib.SetWindowPosSize(device.getHandle(), x11Window, clientArea.x, clientArea.y, clientArea.width, clientArea.height); + } + public static void destroyX11Window(AbstractGraphicsDevice device, long x11Window) { + X11Lib.DestroyWindow(device.getHandle(), x11Window); + } + + // + // Specific X11 SWT/GTK ChildWindow - Using SWT/GTK native parenting (buggy - sporadic resize flickering, sporadic drop of rendering) + // + // FIXME: Need to use reflection for 32bit access as well ! + // + + // public static final int GDK_WA_TYPE_HINT = 1 << 9; + // public static final int GDK_WA_VISUAL = 1 << 6; + + public static long createCompatibleGDKChildWindow(Control swtControl, int visualID, int width, int height) { + return 0; + /** + final long handle = SWTAccessor.getHandle(swtControl); + final long parentWindow = gdk_widget_get_window( handle ); + + final long screen = OS.gdk_screen_get_default (); + final long gdkvisual = OS.gdk_x11_screen_lookup_visual (screen, visualID); + + final GdkWindowAttr attrs = new GdkWindowAttr(); + attrs.width = width > 0 ? width : 1; + attrs.height = height > 0 ? height : 1; + attrs.event_mask = OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK | + OS.GDK_FOCUS_CHANGE_MASK | OS.GDK_POINTER_MOTION_MASK | + OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK | + OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK | + OS.GDK_EXPOSURE_MASK | OS.GDK_VISIBILITY_NOTIFY_MASK | + OS.GDK_POINTER_MOTION_HINT_MASK; + attrs.window_type = OS.GDK_WINDOW_CHILD; + attrs.visual = gdkvisual; + + final long childWindow = OS.gdk_window_new (parentWindow, attrs, OS.GDK_WA_VISUAL|GDK_WA_TYPE_HINT); + OS.gdk_window_set_user_data (childWindow, handle); + OS.gdk_window_set_back_pixmap (parentWindow, 0, false); + + OS.gdk_window_show (childWindow); + OS.gdk_flush(); + return childWindow; */ + } + + public static void showGDKWindow(long gdkWindow) { + /* OS.gdk_window_show (gdkWindow); + OS.gdk_flush(); */ + } + public static void focusGDKWindow(long gdkWindow) { + /* + OS.gdk_window_show (gdkWindow); + OS.gdk_window_focus(gdkWindow, 0); + OS.gdk_flush(); */ + } + public static void resizeGDKWindow(Rectangle clientArea, long gdkWindow) { + /** + OS.gdk_window_move (gdkWindow, clientArea.x, clientArea.y); + OS.gdk_window_resize (gdkWindow, clientArea.width, clientArea.height); + OS.gdk_flush(); */ + } + + public static void destroyGDKWindow(long gdkWindow) { + // OS.gdk_window_destroy (gdkWindow); + } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java index 67a33e55c..827862002 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java @@ -37,7 +37,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); } if( 0 == s.getSurfaceHandle() ) { - final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64); + final long windowHandle = X11Lib.CreateWindow(0, device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64, false, false); if(0 == windowHandle) { throw new NativeWindowException("Creating dummy window failed w/ "+cfg); } @@ -59,7 +59,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize } device.lock(); try { - X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle()); + X11Lib.DestroyWindow(device.getHandle(), s.getSurfaceHandle()); s.setSurfaceHandle(0); s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); } finally { diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index c73952693..a8d45f288 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -31,6 +31,8 @@ #include "jogamp_nativewindow_x11_X11Lib.h" #include "jogamp_nativewindow_x11_X11Util.h" +#include <X11/Xatom.h> + // #define VERBOSE_ON 1 #ifdef VERBOSE_ON @@ -85,6 +87,8 @@ Bool XF86VidModeSetGammaRamp( #define RTLD_DEFAULT NULL #endif +#define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask) + static const char * const ClazzNameBuffers = "com/jogamp/common/nio/Buffers"; static const char * const ClazzNameBuffersStaticCstrName = "copyByteBuffer"; static const char * const ClazzNameBuffersStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;"; @@ -436,17 +440,62 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused return _res; } +static void NativewindowX11_setNormalWindowEWMH (Display *dpy, Window w) { + Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False ); + Atom types[1]={0}; + types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False ); + XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1); + XSync(dpy, False); +} + +#define DECOR_USE_MWM 1 // works for known WMs +// #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated) + +/* see <http://tonyobryan.com/index.php?article=9> */ +#define MWM_HINTS_DECORATIONS (1L << 1) +#define PROP_MWM_HINTS_ELEMENTS 5 + +static void NativewindowX11_setDecorations (Display *dpy, Window w, Bool decorated) { + +#ifdef DECOR_USE_MWM + unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status + Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); +#endif + +#ifdef DECOR_USE_EWMH + Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False ); + Atom types[3]={0}; + int ntypes=0; + if(True==decorated) { + types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False ); + } else { + types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False ); + } +#endif + +#ifdef DECOR_USE_MWM + XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS); +#endif + +#ifdef DECOR_USE_EWMH + XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); +#endif + + XSync(dpy, False); +} + /* * Class: jogamp_nativewindow_x11_X11Lib - * Method: CreateDummyWindow - * Signature: (JIIII)J + * Method: CreateWindow + * Signature: (JJIIIIZZ)J */ -JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow - (JNIEnv *env, jclass unused, jlong display, jint screen_index, jint visualID, jint width, jint height) +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow + (JNIEnv *env, jclass unused, jlong parent, jlong display, jint screen_index, jint visualID, jint width, jint height, jboolean input, jboolean visible) { Display * dpy = (Display *)(intptr_t)display; int scrn_idx = (int)screen_index; - Window windowParent = 0; + Window root = RootWindow(dpy, scrn_idx); + Window windowParent = (Window) parent; Window window = 0; XVisualInfo visualTemplate; @@ -473,6 +522,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 0); scrn = ScreenOfDisplay(dpy, scrn_idx); + if(0==windowParent) { + windowParent = root; + } // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -500,9 +552,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow pVisualQuery=NULL; } - if(0==windowParent) { - windowParent = XRootWindowOfScreen(scrn); - } attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap | CWBorderPixel | CWColormap | CWOverrideRedirect ) ; @@ -514,15 +563,22 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */ xswa.backing_planes=0; /* planes to be preserved if possible */ xswa.backing_pixel=0; /* value to use in restoring planes */ + if( input ) { + xswa.event_mask = X11_MOUSE_EVENT_MASK; + xswa.event_mask |= KeyPressMask | KeyReleaseMask ; + } + if( visible ) { + xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ; + } xswa.colormap = XCreateColormap(dpy, - XRootWindow(dpy, scrn_idx), + windowParent, visual, AllocNone); window = XCreateWindow(dpy, windowParent, - 0, 0, + 0, 0, // only a hint, WM most likely will override width, height, 0, // border width depth, @@ -530,9 +586,25 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow visual, attrMask, &xswa); + if(0==window) { + NativewindowCommon_throwNewRuntimeException(env, "could not create Window, bail out!"); + return 0; + } + + NativewindowX11_setNormalWindowEWMH(dpy, window); + NativewindowX11_setDecorations(dpy, window, False); + + if( visible ) { + XEvent event; + + XMapWindow(dpy, window); + } + XSync(dpy, False); - XSelectInput(dpy, window, 0); // no events + if( !input ) { + XSelectInput(dpy, window, 0); // no events + } // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1); @@ -544,10 +616,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow /* * Class: jogamp_nativewindow_x11_X11Lib - * Method: DestroyDummyWindow + * Method: DestroyWindow * Signature: (JJ)V */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow +JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow (JNIEnv *env, jclass unused, jlong display, jlong window) { Display * dpy = (Display *)(intptr_t)display; @@ -559,12 +631,37 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow } NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 0); + XSelectInput(dpy, w, 0); XUnmapWindow(dpy, w); XSync(dpy, False); XDestroyWindow(dpy, w); // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1); } +JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_SetWindowPosSize + (JNIEnv *env, jclass unused, jlong display, jlong window, jint x, jint y, jint width, jint height) { + Display * dpy = (Display *)(intptr_t)display; + Window w = (Window) window; + XWindowChanges xwc; + int flags = 0; + + memset(&xwc, 0, sizeof(XWindowChanges)); + + if(0<=x && 0<=y) { + flags |= CWX | CWY; + xwc.x=x; + xwc.y=y; + } + + if(0<width && 0<height) { + flags |= CWWidth | CWHeight; + xwc.width=width; + xwc.height=height; + } + XConfigureWindow(dpy, w, flags, &xwc); + XSync(dpy, False); +} + /* * Class: jogamp_nativewindow_x11_X11Lib * Method: GetRelativeLocation |