summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-10-10 01:47:07 +0200
committerSven Gothel <[email protected]>2015-10-10 01:47:07 +0200
commitc61fa44d9a2e2049fec7833990f7bb699545bd15 (patch)
tree5152f4aeef8fd8900609fd39dfc038b0d987acec /src
parentc1594efa78951f187a75ec0b9a85cf64fba418d4 (diff)
Bug 1249: NEWT/X11 Visibility: Listening to more events for updated state; Adding QUIRK_BIT_VISIBILITY
1) More visibility detection on post ConfigureNotify events, since the latter may not yet contain the updated visibility state as it whould (WM bug!): - EnterNotify - LeaveNotify - Disabled - Expose - VisibilityNotify 2) Introducing quirks. Setting QUIRK_BIT_VISIBILITY to handle the issue where visibility -> false could not even be set.
Diffstat (limited to 'src')
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java154
-rw-r--r--src/newt/native/X11Display.c49
-rw-r--r--src/newt/native/X11Window.c1
3 files changed, 159 insertions, 45 deletions
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 107851d0b..ab2cf97c6 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -149,7 +149,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
//
- // Volatile: Multithread Mutable Access
+ // Volatile: Multithreaded Mutable Access
//
private volatile long windowHandle = 0; // lifecycle critical
private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user
@@ -182,6 +182,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private LifecycleHook lifecycleHook = null;
//
+ // Quirks
+ //
+
+ /**
+ * Bug 1249 and Bug 1250: Visibility issues on X11
+ * <ul>
+ * <li>setVisible(false) IconicState not listening to _NET_WM_STATE_HIDDEN</li>
+ * <li>setVisible(true) not restoring from _NET_WM_STATE_HIDDEN</li>
+ * </ul>
+ * <p>
+ * If {@code true} fall back to traditional visibility state,
+ * i.e. {@code fast=true}.
+ * </p>
+ */
+ static final int QUIRK_BIT_VISIBILITY = 0;
+ /** Regular state mask */
+ /* pp */ static final Bitfield quirks = Bitfield.Factory.synchronize(Bitfield.Factory.create(32));
+
+ //
// State Mask
//
@@ -1206,9 +1225,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
reconfigureWindowImpl(x, y, width, height, mask);
}
+
final void setVisibleActionImpl(final boolean visible) {
boolean nativeWindowCreated = false;
- boolean madeVisible = false;
+ int madeVisible = -1;
final RecursiveLock _lock = windowLock;
_lock.lock();
@@ -1226,16 +1246,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(!isNativeValid() && visible) {
if( 0<getWidth()*getHeight() ) {
nativeWindowCreated = createNative();
- madeVisible = nativeWindowCreated;
+ madeVisible = nativeWindowCreated ? 1 : -1;
}
// always flag visible, allowing a retry ..
stateMask.set(STATE_BIT_VISIBLE);
} else if(stateMask.get(STATE_BIT_VISIBLE) != visible) {
if(isNativeValid()) {
// Skip WM if child-window!
- setVisibleImpl(visible /* visible */, isChildWindow() /* fast */, getX(), getY(), getWidth(), getHeight());
- WindowImpl.this.waitForVisible(visible, false);
- madeVisible = visible;
+ final boolean hasVisibilityQuirk = quirks.get(QUIRK_BIT_VISIBILITY);
+ setVisibleImpl(visible /* visible */, hasVisibilityQuirk || isChildWindow() /* fast */,
+ getX(), getY(), getWidth(), getHeight());
+ if( 0 > WindowImpl.this.waitForVisible(visible, false) ) {
+ if( !hasVisibilityQuirk ) {
+ quirks.set(QUIRK_BIT_VISIBILITY);
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("Setting VISIBILITY QUIRK, due to setVisible("+visible+") failure");
+ }
+ setVisibleImpl(visible /* visible */, true /* fast */,
+ getX(), getY(), getWidth(), getHeight());
+ if( 0 <= WindowImpl.this.waitForVisible(visible, false) ) {
+ madeVisible = visible ? 1 : 0;
+ } // else: still not working .. bail out
+ } // else: no other remedy known .. bail out
+ } else {
+ madeVisible = visible ? 1 : 0;
+ }
} else {
stateMask.set(STATE_BIT_VISIBLE);
}
@@ -1267,7 +1302,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
_lock.unlock();
}
- if( nativeWindowCreated || madeVisible ) {
+ if( nativeWindowCreated || 1==madeVisible ) {
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
@@ -3354,7 +3389,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//
public final void sendMouseEvent(final short eventType, final int modifiers,
- final int x, final int y, final short button, final float rotation) {
+ final int x, final int y, final short button, final float rotation) {
doMouseEvent(false, false, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
}
@@ -4685,41 +4720,57 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Accumulated actions
//
+ /** Triggered by implementation. */
+ protected final void sendMouseEventRequestFocus(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ sendMouseEvent(eventType, modifiers, x, y, button, rotation);
+ requestFocus(false /* wait */);
+ }
/**
- * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags.
+ * Triggered by implementation's WM events to update the visibility state and send- or enqueue one mouse event
*
* @param defer
- * @param newX
- * @param newY
- * @param newWidth
- * @param newHeight
- * @param left insets, -1 ignored
- * @param right insets, -1 ignored
- * @param top insets, -1 ignored
- * @param bottom insets, -1 ignored
- * @param focusChange -1 ignored, 0 unfocused, > 0 focused
* @param visibleChange -1 ignored, 0 invisible, > 0 visible
- * @param force
+ * @param entranceChange -1 ignored, 0 exit, > 0 enter
+ * @param eventType 0 ignored, > 0 [send|enqueue]MouseEvent
+ * @param modifiers
+ * @param x
+ * @param y
+ * @param button
+ * @param rotation
*/
- protected final void sizePosInsetsFocusVisibleChanged(final boolean defer,
- final int newX, final int newY,
- final int newWidth, final int newHeight,
- final int left, final int right, final int top, final int bottom,
- final int focusChange,
- final int visibleChange,
- final boolean force) {
- sizeChanged(defer, newWidth, newHeight, force);
- positionChanged(defer, newX, newY);
- insetsChanged(defer, left, right, top, bottom);
- if( 0 <= focusChange ) { // ignore focus < 0
- focusChanged(defer, 0 < focusChange);
+ protected final void visibleChangedSendMouseEvent(final boolean defer, final int visibleChange,
+ final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ if( 0 <= visibleChange ) { // ignore visible < 0
+ visibleChanged(defer, 0 < visibleChange);
+ }
+ if( 0 < eventType ) {
+ if( defer ) {
+ enqueueMouseEvent(false /* wait */, eventType, modifiers, x, y, button, rotation);
+ } else {
+ sendMouseEvent(eventType, modifiers, x, y, button, rotation);
+ }
}
+ }
+ /**
+ * Triggered by implementation's WM events to update the content
+ * @param defer if true sent event later, otherwise wait until processed.
+ * @param visibleChange -1 ignored, 0 invisible, > 0 visible
+ * @param x dirty-region y-pos in pixel units
+ * @param y dirty-region x-pos in pixel units
+ * @param width dirty-region width in pixel units
+ * @param height dirty-region height in pixel units
+ */
+ protected final void visibleChangedWindowRepaint(final boolean defer, final int visibleChange,
+ final int x, final int y, final int width, final int height) {
if( 0 <= visibleChange ) { // ignore visible < 0
visibleChanged(defer, 0 < visibleChange);
}
+ windowRepaint(defer, x, y, width, height);
}
/**
- * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags.
+ * Triggered by implementation's WM events to update the focus and visibility state
*
* @param defer
* @param focusChange -1 ignored, 0 unfocused, > 0 focused
@@ -4761,6 +4812,39 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* @param newY
* @param newWidth
* @param newHeight
+ * @param left insets, -1 ignored
+ * @param right insets, -1 ignored
+ * @param top insets, -1 ignored
+ * @param bottom insets, -1 ignored
+ * @param focusChange -1 ignored, 0 unfocused, > 0 focused
+ * @param visibleChange -1 ignored, 0 invisible, > 0 visible
+ * @param force
+ */
+ protected final void sizePosInsetsFocusVisibleChanged(final boolean defer,
+ final int newX, final int newY,
+ final int newWidth, final int newHeight,
+ final int left, final int right, final int top, final int bottom,
+ final int focusChange,
+ final int visibleChange,
+ final boolean force) {
+ sizeChanged(defer, newWidth, newHeight, force);
+ positionChanged(defer, newX, newY);
+ insetsChanged(defer, left, right, top, bottom);
+ if( 0 <= focusChange ) { // ignore focus < 0
+ focusChanged(defer, 0 < focusChange);
+ }
+ if( 0 <= visibleChange ) { // ignore visible < 0
+ visibleChanged(defer, 0 < visibleChange);
+ }
+ }
+ /**
+ * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags.
+ *
+ * @param defer
+ * @param newX
+ * @param newY
+ * @param newWidth
+ * @param newHeight
* @param maxHorzChange -1 ignored, 0 !maximized, > 0 maximized
* @param maxVertChange -1 ignored, 0 !maximized, > 0 maximized
* @param left insets, -1 ignored
@@ -4787,12 +4871,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
visibleChanged(defer, 0 < visibleChange);
}
}
- /** Triggered by implementation. */
- protected final void sendMouseEventRequestFocus(final short eventType, final int modifiers,
- final int x, final int y, final short button, final float rotation) {
- sendMouseEvent(eventType, modifiers, x, y, button, rotation);
- requestFocus(false /* wait */);
- }
//
// Reflection helper ..
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index ab5afd1d6..32e0f8786 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -53,6 +53,8 @@ static jmethodID windowRepaintID = NULL;
static jmethodID sendMouseEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID sendMouseEventRequestFocusID = NULL;
+static jmethodID visibleChangedWindowRepaintID = NULL;
+static jmethodID visibleChangedSendMouseEventID = NULL;
static jmethodID sizePosMaxInsetsVisibleChangedID = NULL;
/**
@@ -260,8 +262,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
+ visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)V");
sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V");
+ visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V");
sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
if (displayCompletedID == NULL ||
@@ -278,8 +282,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
+ visibleChangedWindowRepaintID == NULL ||
sendMouseEventID == NULL ||
sendMouseEventRequestFocusID == NULL ||
+ visibleChangedSendMouseEventID == NULL ||
sendKeyEventID == NULL) {
return JNI_FALSE;
}
@@ -564,15 +570,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
break;
case EnterNotify:
DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "EnterNotify");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange,
+ (jshort) EVENT_MOUSE_ENTERED, modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ }
break;
case LeaveNotify:
DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ {
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "LeaveNotify");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange,
+ (jshort) EVENT_MOUSE_EXITED, modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ }
break;
case MappingNotify:
DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
@@ -621,6 +635,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
}
break;
case ClientMessage:
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, sendEvent %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, evt.xclient.send_event);
if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
jboolean closed;
DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
@@ -651,13 +667,32 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
}
break;
+ case VisibilityNotify:
+ DBG_PRINT( "X11: event . VisibilityNotify call %p\n", (void*)evt.xvisibility.window);
+ {
+ #if 0
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "VisibilityNotify");
+ if( 0 <= visibleChange ) {
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, 0 < visibleChange ? JNI_TRUE : JNI_FALSE);
+ }
+ #endif
+ }
+ break;
+
+
case Expose:
DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
-
if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
(*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE,
evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ #if 0
+ uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw);
+ int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "Expose");
+ (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ #endif
}
break;
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index f10db317a..de2bddc86 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -848,6 +848,7 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
xswa.event_mask = X11_MOUSE_EVENT_MASK;
xswa.event_mask |= KeyPressMask | KeyReleaseMask ;
xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask;
+ // xswa.event_mask |= VisibilityChangeMask;
{
int _x = x, _y = y; // pos for CreateWindow, might be tweaked