Bug 503431 - [wayland] CTabFolder slow when switching tabs

CTabFolder would signal a D&D timeout because gdk_event_get() was not
receiving anything in Wayland. Using gdk_window_get_device_position() we
can get the current mouse status to see if it was a release event to
leave the timeout loop correctly.

Change-Id: If6aa70d945f116dec6b5613835bdfd7c03b89c4d
Signed-off-by: Ian Pun <ipun@redhat.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index 3f7449c..4846d14 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
@@ -2471,7 +2471,7 @@
 }
 
 boolean dragDetect (int x, int y, boolean filter, boolean dragOnTimeout, boolean [] consume) {
-	boolean quit = false, dragging = false;
+	boolean quit = false, dragging = false, timeoutFlag = true;
 
 	//428852 DND workaround for GTk3.
 	//Gtk3 no longer sends motion events on the same control during thread sleep
@@ -2503,6 +2503,21 @@
 					dragging = OS.gtk_drag_check_threshold (handle,
 								startPos.x, startPos.y, currPos.x, currPos.y);
 					if (dragging) break;
+					/*
+					 *  Bug 503431: Wayland does not put GDK_BUTTON_RELEASE event into the gdk_event queue, instead it put into the system queue.
+					 *  Gdk_event_peek() does not read from the system queue, while gdk_event_get() does. GDK_BUTTON_RELEASE event is processed
+					 *  already in Wayland, so using gdk_window_get_device_position() we can get the correct mouse status to break out of
+					 *  timeout if necessary.
+					 */
+
+					OS.g_main_context_iteration (0, false);
+					int [] mask = new int [1];
+					gdk_window_get_device_position(0, null, null, mask);
+					if (mask[0] != OS.GDK_BUTTON1_MASK) {
+						timeoutFlag = false;
+						quit = true;
+						break;
+					}
 				} else {
 				try {Thread.sleep(50);}
 				catch (Exception ex) {}
@@ -2511,42 +2526,44 @@
 		}
 		display.sendPostExternalEventDispatchEvent();
 		if (dragging) return true;  //428852
-		if (eventPtr == 0) return dragOnTimeout;
-		switch (OS.GDK_EVENT_TYPE (eventPtr)) {
-			case OS.GDK_MOTION_NOTIFY: {
-				GdkEventMotion gdkMotionEvent = new GdkEventMotion ();
-				OS.memmove (gdkMotionEvent, eventPtr, GdkEventMotion.sizeof);
-				if ((gdkMotionEvent.state & OS.GDK_BUTTON1_MASK) != 0) {
-					if (OS.gtk_drag_check_threshold (handle, x, y, (int) gdkMotionEvent.x, (int) gdkMotionEvent.y)) {
-						dragging = true;
+		if (eventPtr == 0 && timeoutFlag) return dragOnTimeout;
+		if (eventPtr != 0) {
+			switch (OS.GDK_EVENT_TYPE (eventPtr)) {
+				case OS.GDK_MOTION_NOTIFY: {
+					GdkEventMotion gdkMotionEvent = new GdkEventMotion ();
+					OS.memmove (gdkMotionEvent, eventPtr, GdkEventMotion.sizeof);
+					if ((gdkMotionEvent.state & OS.GDK_BUTTON1_MASK) != 0) {
+						if (OS.gtk_drag_check_threshold (handle, x, y, (int) gdkMotionEvent.x, (int) gdkMotionEvent.y)) {
+							dragging = true;
+							quit = true;
+						}
+					} else {
 						quit = true;
 					}
-				} else {
-					quit = true;
+					int [] newX = new int [1], newY = new int [1];
+					gdk_window_get_device_position (gdkMotionEvent.window, newX, newY, null);
+					break;
 				}
-				int [] newX = new int [1], newY = new int [1];
-				gdk_window_get_device_position (gdkMotionEvent.window, newX, newY, null);
-				break;
+				case OS.GDK_KEY_PRESS:
+				case OS.GDK_KEY_RELEASE: {
+					GdkEventKey gdkEvent = new GdkEventKey ();
+					OS.memmove (gdkEvent, eventPtr, GdkEventKey.sizeof);
+					if (gdkEvent.keyval == OS.GDK_Escape) quit = true;
+					break;
+				}
+				case OS.GDK_BUTTON_RELEASE:
+				case OS.GDK_BUTTON_PRESS:
+				case OS.GDK_2BUTTON_PRESS:
+				case OS.GDK_3BUTTON_PRESS: {
+					OS.gdk_event_put (eventPtr);
+					quit = true;
+					break;
+				}
+				default:
+					OS.gtk_main_do_event (eventPtr);
 			}
-			case OS.GDK_KEY_PRESS:
-			case OS.GDK_KEY_RELEASE: {
-				GdkEventKey gdkEvent = new GdkEventKey ();
-				OS.memmove (gdkEvent, eventPtr, GdkEventKey.sizeof);
-				if (gdkEvent.keyval == OS.GDK_Escape) quit = true;
-				break;
-			}
-			case OS.GDK_BUTTON_RELEASE:
-			case OS.GDK_BUTTON_PRESS:
-			case OS.GDK_2BUTTON_PRESS:
-			case OS.GDK_3BUTTON_PRESS: {
-				OS.gdk_event_put (eventPtr);
-				quit = true;
-				break;
-			}
-			default:
-				OS.gtk_main_do_event (eventPtr);
+			OS.gdk_event_free (eventPtr);
 		}
-		OS.gdk_event_free (eventPtr);
 	}
 	return dragging;
 }