From d97402167865f8bdd32fe8e306f7e17f58d0b20c Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 19 Jan 2016 15:05:14 +0300 Subject: [PATCH] WMenuBar: use the new mouse API. Signed-off-by: Andrew Borodin --- lib/widget/menu.c | 279 ++++++++++++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 123 deletions(-) diff --git a/lib/widget/menu.c b/lib/widget/menu.c index 504d6c8e0..c29fbe9a9 100644 --- a/lib/widget/menu.c +++ b/lib/widget/menu.c @@ -5,7 +5,7 @@ Free Software Foundation, Inc. Written by: - Andrew Borodin , 2012, 2013 + Andrew Borodin , 2012, 2013, 2016 This file is part of the Midnight Commander. @@ -38,7 +38,6 @@ #include "lib/tty/tty.h" #include "lib/skin.h" -#include "lib/tty/mouse.h" #include "lib/tty/key.h" /* key macros */ #include "lib/strutil.h" #include "lib/widget.h" @@ -631,142 +630,175 @@ menubar_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void /* --------------------------------------------------------------------------------------------- */ -static int -menubar_event (Gpm_Event * event, void *data) +static unsigned int +menubar_get_menu_by_x_coord (const WMenuBar * menubar, int x) { - WMenuBar *menubar = MENUBAR (data); - Widget *w = WIDGET (data); - gboolean was_active = TRUE; - int left_x, right_x, bottom_y; + unsigned int i; + GList *menu; + + for (i = 0, menu = menubar->menu; + menu != NULL && x > MENU (menu->data)->start_x; i++, menu = g_list_next (menu)) + ; + + /* Don't set the invalid value -1 */ + if (i != 0) + i--; + + return i; +} + +/* --------------------------------------------------------------------------------------------- */ + +static gboolean +menubar_mouse_on_menu (const WMenuBar * menubar, int y, int x) +{ + Widget *w = WIDGET (menubar); menu_t *menu; - Gpm_Event local; + int left_x, right_x, bottom_y; - if (!mouse_global_in_widget (event, w)) - return MOU_UNHANDLED; - - /* ignore unsupported events */ - if ((event->type & (GPM_UP | GPM_DOWN | GPM_DRAG)) == 0) - return MOU_NORMAL; - - /* ignore wheel events if menu is inactive */ - if (!menubar->is_active && ((event->buttons & (GPM_B_MIDDLE | GPM_B_UP | GPM_B_DOWN)) != 0)) - return MOU_NORMAL; - - local = mouse_get_local (event, w); - - if (local.y == 1 && (local.type & GPM_UP) != 0) - return MOU_NORMAL; - - if (!menubar->is_dropped) - { - if (local.y > 1) - { - /* mouse click below menubar -- close menu and send focus to widget under mouse */ - menubar_finish (menubar); - return MOU_UNHANDLED; - } - - menubar->previous_widget = dlg_get_current_widget_id (w->owner); - menubar->is_active = TRUE; - menubar->is_dropped = TRUE; - was_active = FALSE; - } - - /* Mouse operations on the menubar */ - if (local.y == 1 || !was_active) - { - /* wheel events on menubar */ - if ((local.buttons & GPM_B_UP) != 0) - menubar_left (menubar); - else if ((local.buttons & GPM_B_DOWN) != 0) - menubar_right (menubar); - else - { - const unsigned int len = g_list_length (menubar->menu); - unsigned int new_selection = 0; - - while ((new_selection < len) - && (local.x > MENU (g_list_nth_data (menubar->menu, new_selection))->start_x)) - new_selection++; - - if (new_selection != 0) /* Don't set the invalid value -1 */ - new_selection--; - - if (!was_active) - { - menubar->selected = new_selection; - dlg_select_widget (menubar); - } - else - { - menubar_remove (menubar); - menubar->selected = new_selection; - } - menubar_draw (menubar); - } - return MOU_NORMAL; - } - - if (!menubar->is_dropped || (local.y < 2)) - return MOU_NORMAL; - - /* middle click -- everywhere */ - if (((local.buttons & GPM_B_MIDDLE) != 0) && ((local.type & GPM_DOWN) != 0)) - { - menubar_execute (menubar); - return MOU_NORMAL; - } - - /* the mouse operation is on the menus or it is not */ menu = MENU (g_list_nth_data (menubar->menu, menubar->selected)); left_x = menu->start_x; right_x = left_x + menu->max_entry_len + 3; if (right_x > w->cols) { - left_x = w->cols - menu->max_entry_len - 3; + left_x = w->cols - (menu->max_entry_len + 3); right_x = w->cols; } - bottom_y = g_list_length (menu->entries) + 3; + bottom_y = g_list_length (menu->entries) + 2; /* skip bar and top frame */ - if ((local.x >= left_x) && (local.x <= right_x) && (local.y <= bottom_y)) + return (x >= left_x && x < right_x && y > 1 && y < bottom_y); +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +menubar_change_selected_item (WMenuBar * menubar, int y) +{ + menu_t *menu; + menu_entry_t *entry; + + y -= 2; /* skip bar and top frame */ + menu = MENU (g_list_nth_data (menubar->menu, menubar->selected)); + entry = MENUENTRY (g_list_nth_data (menu->entries, y)); + + if (entry != NULL && entry->command != CK_IgnoreKey) { - int pos = local.y - 3; - const menu_entry_t *entry = MENUENTRY (g_list_nth_data (menu->entries, pos)); - - /* mouse wheel */ - if ((local.buttons & GPM_B_UP) != 0 && (local.type & GPM_DOWN) != 0) - { - menubar_up (menubar); - return MOU_NORMAL; - } - if ((local.buttons & GPM_B_DOWN) != 0 && (local.type & GPM_DOWN) != 0) - { - menubar_down (menubar); - return MOU_NORMAL; - } - - /* ignore events above and below dropped down menu */ - if ((pos < 0) || (pos >= bottom_y - 3)) - return MOU_NORMAL; - - if ((entry != NULL) && (entry->command != CK_IgnoreKey)) - { - menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR); - menu->selected = pos; - menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR); - - if ((event->type & GPM_UP) != 0) - menubar_execute (menubar); - } + menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR); + menu->selected = y; + menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR); } - else if (((local.type & GPM_DOWN) != 0) && ((local.buttons & (GPM_B_UP | GPM_B_DOWN)) == 0)) +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +menubar_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event) +{ + WMenuBar *menubar = MENUBAR (w); + + switch (msg) { - /* use click not wheel to close menu */ - menubar_finish (menubar); - } + case MSG_MOUSE_DOWN: + if (event->y == 0) + { + unsigned int selected; - return MOU_NORMAL; + selected = menubar_get_menu_by_x_coord (menubar, event->x); + + if (!menubar->is_active) + { + /* menu bar is not active -- activate it */ + menubar->previous_widget = dlg_get_current_widget_id (w->owner); + menubar->is_active = TRUE; + menubar_drop (menubar, selected); + dlg_select_widget (w); + } + else if (selected != menubar->selected) + { + menubar_remove (menubar); + menubar_drop (menubar, selected); + } + } + else + menubar_change_selected_item (menubar, event->y); + break; + + case MSG_MOUSE_CLICK: + if (event->y == 0) + { + /* events on menubar */ + unsigned int selected; + + selected = menubar_get_menu_by_x_coord (menubar, event->x); + + if (selected != menubar->selected) + { + menubar_remove (menubar); + menubar_drop (menubar, selected); + } + } + else if (!menubar->is_dropped) + { + if (event->y > 0) + { + /* mouse click below menubar -- close menu */ + menubar_finish (menubar); + } + else + { + /* show drop-down menu */ + menubar_drop (menubar, menubar_get_menu_by_x_coord (menubar, event->x)); + } + } + else if ((event->buttons & GPM_B_MIDDLE) != 0) + { + /* middle click -- everywhere */ + menubar_execute (menubar); + } + else if (menubar_mouse_on_menu (menubar, event->y, event->x)) + menubar_execute (menubar); + else + menubar_finish (menubar); + break; + + case MSG_MOUSE_DRAG: + if (event->y == 0) + { + menubar_remove (menubar); + menubar_drop (menubar, menubar_get_menu_by_x_coord (menubar, event->x)); + } + else + menubar_change_selected_item (menubar, event->y); + break; + + case MSG_MOUSE_SCROLL_UP: + case MSG_MOUSE_SCROLL_DOWN: + if (menubar->is_active) + { + if (event->y == 0) + { + /* menubar: left/right */ + if (msg == MSG_MOUSE_SCROLL_UP) + menubar_left (menubar); + else + menubar_right (menubar); + } + else if (menubar_mouse_on_menu (menubar, event->y, event->x)) + { + /* drop-down menu: up/down */ + /* ignore events below drop-down menu */ + if (msg == MSG_MOUSE_SCROLL_UP) + menubar_up (menubar); + else + menubar_down (menubar); + } + } + break; + + default: + break; + } } /* --------------------------------------------------------------------------------------------- */ @@ -849,7 +881,8 @@ menubar_new (int y, int x, int cols, GList * menu, gboolean visible) menubar = g_new0 (WMenuBar, 1); w = WIDGET (menubar); - widget_init (w, y, x, 1, cols, menubar_callback, menubar_event); + widget_init (w, y, x, 1, cols, menubar_callback, NULL); + set_easy_mouse_callback (w, menubar_mouse_callback); menubar->is_visible = visible; widget_want_cursor (w, FALSE);