[Bf-blender-cvs] [47e7ce6] master: Fix for glitch with menus not reliably setting an active item (D674)

Campbell Barton noreply at git.blender.org
Sun Aug 3 12:38:55 CEST 2014


Commit: 47e7ce696c997313ae30bca0c09d17d6886a155b
Author: Campbell Barton
Date:   Sun Aug 3 20:30:12 2014 +1000
Branches: master
https://developer.blender.org/rB47e7ce696c997313ae30bca0c09d17d6886a155b

Fix for glitch with menus not reliably setting an active item (D674)

When menus are clamped to the window bounds,
its was possible not to have an active menu-item under the mouse,
Making Ctrl+S,Enter not completely reliable.

Changes needed to support this are:

- menu item is activated on popup menus
  (to avoid relying on mouse-over)
- moving mouse away from menu items only de-activates when over a new menu-item.
- Mouse clicks are ignored if they are not directly over the menu item.

===================================================================

M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_regions.c

===================================================================

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index b3f13cc..b5f11c2 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -385,7 +385,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
 	}
 }
 
-static bool ui_but_is_editable(const uiBut *but)
+bool ui_but_is_editable(const uiBut *but)
 {
 	return !ELEM(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
 }
@@ -7199,6 +7199,17 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
 	ui_do_button(C, but->block, but, &event);
 }
 
+/**
+ * Simulate moving the mouse over a button (or navigating to it with arrow keys).
+ *
+ * exported so menus can start with a highlighted button,
+ * even if the mouse isnt over it
+ */
+void ui_button_activate_over(bContext *C, ARegion *ar, uiBut *but)
+{
+	button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+}
+
 void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
 {
 	/* note: ideally we would not have to change 'but->active' however
@@ -7261,12 +7272,20 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
 				retval = WM_UI_HANDLER_CONTINUE;
 				break;
 			case MOUSEMOVE:
-				/* verify if we are still over the button, if not exit */
-				if (!ui_mouse_inside_button(ar, but, event->x, event->y)) {
-					data->cancel = true;
-					button_activate_state(C, but, BUTTON_STATE_EXIT);
+			{
+				uiBut *but_other = ui_but_find_mouse_over(ar, event);
+				bool exit = false;
+
+				if (!ui_block_is_menu(block) &&
+				    !ui_mouse_inside_button(ar, but, event->x, event->y))
+				{
+					exit = true;
+				}
+				else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
+					exit = true;
 				}
-				else if (ui_but_find_mouse_over(ar, event) != but) {
+
+				if (exit) {
 					data->cancel = true;
 					button_activate_state(C, but, BUTTON_STATE_EXIT);
 				}
@@ -7277,6 +7296,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
 				}
 
 				break;
+			}
 			case TIMER:
 			{
 				/* handle tooltip timer */
@@ -7860,6 +7880,16 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
 	int retval;
 
 	if (but) {
+		/* Its possible there is an active menu item NOT under the mouse,
+		 * in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
+		if ((event->type != MOUSEMOVE) && ISMOUSE(event->type)) {
+			if (!ui_mouse_inside_button(but->active->region, but, event->x, event->y)) {
+				but = NULL;
+			}
+		}
+	}
+
+	if (but) {
 		ScrArea *ctx_area = CTX_wm_area(C);
 		ARegion *ctx_region = CTX_wm_region(C);
 
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index fa8b6b1..7d03aae 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -552,6 +552,7 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol
 PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
 extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
 extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_button_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
 extern void ui_button_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
 extern void ui_button_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
 extern void ui_button_active_free(const struct bContext *C, uiBut *but);
@@ -559,6 +560,7 @@ extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
 extern int ui_button_open_menu_direction(uiBut *but);
 extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
 extern uiBut *ui_but_find_activated(struct ARegion *ar);
+bool ui_but_is_editable(const uiBut *but);
 
 void ui_button_clipboard_free(void);
 void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 85bf15e..32fb684 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2408,6 +2408,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
 	uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
 	
 	if (pup->popup) {
+		uiBut *but_activate = NULL;
 		uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
 		uiBlockSetDirection(block, direction);
 
@@ -2421,6 +2422,10 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
 			 * block to be under the mouse */
 			offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
 			offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
+
+			if (ui_but_is_editable(bt)) {
+				but_activate = bt;
+			}
 		}
 		else {
 			/* position mouse at 0.8*width of the button and below the tile
@@ -2430,6 +2435,20 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
 				offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
 
 			offset[1] = 2.1 * UI_UNIT_Y;
+
+			for (bt = block->buttons.first; bt; bt = bt->next) {
+				if (ui_but_is_editable(bt)) {
+					but_activate = bt;
+					break;
+				}
+			}
+		}
+
+		/* in rare cases this is needed since moving the popup
+		 * to be within the window bounds may move it away from the mouse,
+		 * This ensures we set an item to be active. */
+		if (but_activate) {
+			ui_button_activate_over(C, handle->region, but_activate);
 		}
 
 		block->minbounds = minwidth;




More information about the Bf-blender-cvs mailing list