[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51661] trunk/blender/source/blender/ windowmanager/intern: Bugfix #28734

Ton Roosendaal ton at blender.org
Fri Oct 26 17:21:31 CEST 2012


Revision: 51661
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51661
Author:   ton
Date:     2012-10-26 15:21:31 +0000 (Fri, 26 Oct 2012)
Log Message:
-----------
Bugfix #28734

Double clicks were never working reliably in Blender - this mostly because
it wasn't a real event, but something generated in the handler code.

Now it is an actual event - meaning it always gets handled (if you have
a keymap item for it of course), but if there's no doubleclick handling
it treats the doubleclick as a normal click.

Also cleaned code. No recursion anymore.

Modified Paths:
--------------
    trunk/blender/source/blender/windowmanager/intern/wm_event_system.c
    trunk/blender/source/blender/windowmanager/intern/wm_keymap.c

Modified: trunk/blender/source/blender/windowmanager/intern/wm_event_system.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_event_system.c	2012-10-26 14:45:56 UTC (rev 51660)
+++ trunk/blender/source/blender/windowmanager/intern/wm_event_system.c	2012-10-26 15:21:31 UTC (rev 51661)
@@ -1672,7 +1672,7 @@
 	return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL);
 }
 
-static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
+static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers)
 {
 #ifndef NDEBUG
 	const int do_debug_handler = (G.debug & G_DEBUG_EVENTS)
@@ -1849,49 +1849,44 @@
 		}
 	}
 
-	/* test for CLICK event */
-	if (wm_action_not_handled(action) && event->val == KM_RELEASE) {
-		wmWindow *win = CTX_wm_window(C);
+	if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL))
+		wm_cursor_arrow_move(CTX_wm_window(C), event);
 
-		if (win && win->eventstate->prevtype == event->type && win->eventstate->prevval == KM_PRESS) {
-			/* test for double click first,
-			 * note1: this can be problematic because single click operators can get the
-			 *   double click event but then with old mouse coords which is highly confusing,
-			 *   so check for mouse moves too.
-			 * note2: the first click event will be handled but still used to create a
-			 *   double click event if clicking again quickly.
-			 *   If no double click events are found it will fallback to a single click.
-			 *   So a double click event can result in 2 successive single click calls
-			 *   if its not handled by the keymap - campbell */
-			if ((ABS(event->x - win->eventstate->prevclickx)) <= 2 &&
-			    (ABS(event->y - win->eventstate->prevclicky)) <= 2 &&
-			    ((PIL_check_seconds_timer() - win->eventstate->prevclicktime) * 1000 < U.dbl_click_time))
-			{
-				event->val = KM_DBL_CLICK;
-				/* removed this because in cases where we're this is used as a single click
-				 * event, this will give old coords,
-				 * since the distance is checked above, using new coords should be ok. */
-				//   event->x = win->eventstate->prevclickx;
-				//   event->y = win->eventstate->prevclicky;
-				action |= wm_handlers_do(C, event, handlers);
-			}
+	return action;
+}
 
-			if (wm_action_not_handled(action)) {
+/* this calls handlers twice - to solve (double-)click events */
+static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
+{
+	int action = wm_handlers_do_intern(C, event, handlers);
+	
+	/* test for CLICK events */
+	if (wm_action_not_handled(action)) {
+		wmWindow *win = CTX_wm_window(C);
+		
+		if (win && win->eventstate->prevtype == event->type) {
+			
+			if(event->val == KM_RELEASE && win->eventstate->prevval == KM_PRESS) {
 				event->val = KM_CLICK;
-				action |= wm_handlers_do(C, event, handlers);
+				action |= wm_handlers_do_intern(C, event, handlers);
+				
+				/* revert value if not handled */
+				if (wm_action_not_handled(action)) {
+					event->val = KM_RELEASE;
+				}
 			}
-
-
-			/* revert value if not handled */
-			if (wm_action_not_handled(action)) {
-				event->val = KM_RELEASE;
+			else if(event->val == KM_DBL_CLICK) {
+				event->val = KM_PRESS;
+				action |= wm_handlers_do_intern(C, event, handlers);
+				
+				/* revert value if not handled */
+				if (wm_action_not_handled(action)) {
+					event->val = KM_DBL_CLICK;
+				}
 			}
 		}
 	}
 	
-	if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL))
-		wm_cursor_arrow_move(CTX_wm_window(C), event);
-
 	return action;
 }
 
@@ -2185,40 +2180,6 @@
 				}
 			}
 			
-			/* store last event for this window */
-			/* mousemove and timer events don't overwrite last type */
-			if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) && !ISTIMER(event->type)) {
-				if (wm_action_not_handled(action)) {
-					if (win->eventstate->prevtype == event->type) {
-						/* set click time on first click (press -> release) */
-						if (win->eventstate->prevval == KM_PRESS && event->val == KM_RELEASE) {
-							win->eventstate->prevclicktime = PIL_check_seconds_timer();
-							win->eventstate->prevclickx = event->x;
-							win->eventstate->prevclicky = event->y;
-						}
-					}
-					else {
-						/* reset click time if event type not the same */
-						win->eventstate->prevclicktime = 0;
-					}
-
-					win->eventstate->prevval = event->val;
-					win->eventstate->prevtype = event->type;
-				}
-				else if (event->val == KM_CLICK) { /* keep click for double click later */
-					win->eventstate->prevtype = event->type;
-					win->eventstate->prevval = event->val;
-					win->eventstate->prevclicktime = PIL_check_seconds_timer();
-					win->eventstate->prevclickx = event->x;
-					win->eventstate->prevclicky = event->y;
-				}
-				else { /* reset if not */
-					win->eventstate->prevtype = -1;
-					win->eventstate->prevval = 0;
-					win->eventstate->prevclicktime = 0;
-				}
-			}
-
 			/* unlink and free here, blender-quit then frees all */
 			BLI_remlink(&win->queue, event);
 			wm_event_free(event);
@@ -2724,6 +2685,10 @@
 	/* initialize and copy state (only mouse x y and modifiers) */
 	event = *evt;
 	
+	/* copy prev state to event state */
+	evt->prevval = evt->val;
+	evt->prevtype = evt->type;
+	
 	switch (type) {
 		/* mouse move */
 		case GHOST_kEventCursorMove:
@@ -2806,7 +2771,8 @@
 		case GHOST_kEventButtonUp:
 		{
 			GHOST_TEventButtonData *bd = customdata;
-
+			
+			/* get value and type from ghost */
 			event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE;
 			
 			if (bd->button == GHOST_kButtonMaskLeft)
@@ -2820,6 +2786,10 @@
 			else
 				event.type = MIDDLEMOUSE;
 			
+			/* copy to event state */
+			evt->val= event.val;
+			evt->type= event.type;
+			
 			if (win->active == 0) {
 				int cx, cy;
 				
@@ -2830,6 +2800,21 @@
 				event.y = evt->y = cy;
 			}
 			
+			/* double click test */
+			if (event.type == evt->prevtype && event.val == KM_PRESS) {
+				if ((ABS(event.x - evt->prevclickx)) <= 2 &&
+					(ABS(event.y - evt->prevclicky)) <= 2 &&
+					((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time))
+				{
+					event.val = KM_DBL_CLICK;
+				}
+			}
+			if (event.val == KM_RELEASE) {
+				evt->prevclicktime = PIL_check_seconds_timer();
+				evt->prevclickx = event.x;
+				evt->prevclicky = event.y;
+			}
+			
 			/* add to other window if event is there (not to both!) */
 			owin = wm_event_cursor_other_windows(wm, win, &event);
 			if (owin) {
@@ -2860,6 +2845,10 @@
 			memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
 			event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE;
 			
+			/* copy to event state */
+			evt->val= event.val;
+			evt->type= event.type;
+			
 			/* exclude arrow keys, esc, etc from text input */
 			if (type == GHOST_kEventKeyUp) {
 				event.ascii = '\0';
@@ -2932,6 +2921,22 @@
 			if (event.type == ESCKEY && event.val == KM_PRESS)
 				G.is_break = TRUE;
 			
+			/* double click test */
+			if (event.type == evt->prevtype && event.val == KM_PRESS) {
+				if ((ABS(event.x - evt->prevclickx)) <= 2 &&
+					(ABS(event.y - evt->prevclicky)) <= 2 &&
+					((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time))
+				{
+					printf("double key click\n");
+					event.val = KM_DBL_CLICK;
+				}
+			}
+			if (event.val == KM_RELEASE) {
+				evt->prevclicktime = PIL_check_seconds_timer();
+				evt->prevclickx = event.x;
+				evt->prevclicky = event.y;
+			}
+			
 			wm_event_add(win, &event);
 			
 			break;

Modified: trunk/blender/source/blender/windowmanager/intern/wm_keymap.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_keymap.c	2012-10-26 14:45:56 UTC (rev 51660)
+++ trunk/blender/source/blender/windowmanager/intern/wm_keymap.c	2012-10-26 15:21:31 UTC (rev 51661)
@@ -957,11 +957,6 @@
 		return 0;
 
 	if (k1->val != KM_ANY && k2->val != KM_ANY) {
-		/* take click, press, release conflict into account */
-		if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
-			return 0;
-		if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
-			return 0;
 		if (k1->val != k2->val)
 			return 0;
 	}




More information about the Bf-blender-cvs mailing list