mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-03 18:14:25 +03:00
Fix menu handling.
We now send mouse events to widgets in reverse Z-order, as done in common GUIs. This makes it easy to implement "invisible" menubars correctly. Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
parent
c9a437a9c2
commit
781b810c13
@ -362,7 +362,7 @@ dlg_mouse_event (WDialog * h, Gpm_Event * event)
|
||||
{
|
||||
Widget *wh = WIDGET (h);
|
||||
|
||||
GList *p, *first;
|
||||
GList *p;
|
||||
|
||||
/* close the dialog by mouse left click out of dialog area */
|
||||
if (mouse_close_dialog && !h->fullscreen && ((event->buttons & GPM_B_LEFT) != 0)
|
||||
@ -382,15 +382,12 @@ dlg_mouse_event (WDialog * h, Gpm_Event * event)
|
||||
return mou;
|
||||
}
|
||||
|
||||
first = h->current;
|
||||
p = first;
|
||||
|
||||
/* send the event to widgets in reverse Z-order */
|
||||
p = g_list_last (h->widgets);
|
||||
do
|
||||
{
|
||||
Widget *w = WIDGET (p->data);
|
||||
|
||||
p = dlg_widget_prev (h, p);
|
||||
|
||||
if ((w->options & W_DISABLED) == 0 && w->mouse != NULL)
|
||||
{
|
||||
/* put global cursor position to the widget */
|
||||
@ -400,8 +397,10 @@ dlg_mouse_event (WDialog * h, Gpm_Event * event)
|
||||
if (ret != MOU_UNHANDLED)
|
||||
return ret;
|
||||
}
|
||||
|
||||
p = g_list_previous (p);
|
||||
}
|
||||
while (p != first);
|
||||
while (p != NULL);
|
||||
|
||||
return MOU_UNHANDLED;
|
||||
}
|
||||
@ -1072,12 +1071,8 @@ dlg_select_widget (void *w)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set widget at top of widget list and make it current.
|
||||
*/
|
||||
|
||||
void
|
||||
dlg_set_top_widget (void *w)
|
||||
static void
|
||||
dlg_set_top_or_bottom_widget (void *w, gboolean set_top)
|
||||
{
|
||||
Widget *widget = WIDGET (w);
|
||||
WDialog *h = widget->owner;
|
||||
@ -1088,13 +1083,37 @@ dlg_set_top_widget (void *w)
|
||||
abort (); /* widget is not in dialog, this should not happen */
|
||||
|
||||
/* unfocus prevoius widget and focus current one before widget reordering */
|
||||
if (h->state == DLG_ACTIVE)
|
||||
if (set_top && h->state == DLG_ACTIVE)
|
||||
do_select_widget (h, l, SELECT_EXACT);
|
||||
|
||||
/* widget reordering */
|
||||
h->widgets = g_list_remove_link (h->widgets, l);
|
||||
if (set_top)
|
||||
h->widgets = g_list_concat (h->widgets, l);
|
||||
h->current = l;
|
||||
else
|
||||
h->widgets = g_list_concat (l, h->widgets);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Set widget at top of widget list and make it current.
|
||||
*/
|
||||
|
||||
void
|
||||
dlg_set_top_widget (void *w)
|
||||
{
|
||||
dlg_set_top_or_bottom_widget (w, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Set widget at bottom of widget list.
|
||||
*/
|
||||
|
||||
void
|
||||
dlg_set_bottom_widget (void *w)
|
||||
{
|
||||
dlg_set_top_or_bottom_widget (w, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -171,6 +171,7 @@ void dlg_stop (WDialog * h);
|
||||
/* Widget selection */
|
||||
void dlg_select_widget (void *w);
|
||||
void dlg_set_top_widget (void *w);
|
||||
void dlg_set_bottom_widget (void *w);
|
||||
void dlg_one_up (WDialog * h);
|
||||
void dlg_one_down (WDialog * h);
|
||||
gboolean dlg_focus (WDialog * h);
|
||||
|
@ -309,6 +309,10 @@ menubar_finish (WMenuBar * menubar)
|
||||
w->lines = 1;
|
||||
widget_want_hotkey (w, 0);
|
||||
|
||||
/* Move the menubar to the bottom so that widgets displayed on top of
|
||||
* an "invisible" menubar get the first chance to respond to mouse events. */
|
||||
dlg_set_bottom_widget (w);
|
||||
|
||||
dlg_select_by_id (w->owner, menubar->previous_widget);
|
||||
do_refresh ();
|
||||
}
|
||||
@ -716,15 +720,7 @@ menubar_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
|
||||
unsigned int selected;
|
||||
|
||||
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;
|
||||
dlg_select_widget (w);
|
||||
}
|
||||
|
||||
menubar_activate (menubar, TRUE, selected);
|
||||
menubar_remove (menubar); /* if already shown */
|
||||
menubar_drop (menubar, selected);
|
||||
}
|
||||
@ -1019,7 +1015,10 @@ menubar_activate (WMenuBar * menubar, gboolean dropped, int which)
|
||||
menubar->selected = (guint) which;
|
||||
|
||||
menubar->previous_widget = dlg_get_current_widget_id (w->owner);
|
||||
dlg_select_widget (w);
|
||||
|
||||
/* Bring it to the top so it receives all mouse events before any other widget.
|
||||
* See also comment in menubar_finish(). */
|
||||
dlg_set_top_widget (w);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1575,42 +1575,6 @@ midnight_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
midnight_event (Gpm_Event * event, void *data)
|
||||
{
|
||||
Widget *wh = WIDGET (data);
|
||||
int ret = MOU_UNHANDLED;
|
||||
|
||||
if (event->y == wh->y + 1)
|
||||
{
|
||||
/* menubar */
|
||||
if (menubar_visible || the_menubar->is_active)
|
||||
ret = WIDGET (the_menubar)->mouse (event, the_menubar);
|
||||
else
|
||||
{
|
||||
Widget *w;
|
||||
|
||||
w = get_panel_widget (0);
|
||||
if (w->mouse != NULL)
|
||||
ret = w->mouse (event, w);
|
||||
|
||||
if (ret == MOU_UNHANDLED)
|
||||
{
|
||||
w = get_panel_widget (1);
|
||||
if (w->mouse != NULL)
|
||||
ret = w->mouse (event, w);
|
||||
}
|
||||
|
||||
if (ret == MOU_UNHANDLED)
|
||||
ret = WIDGET (the_menubar)->mouse (event, the_menubar);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1793,8 +1757,8 @@ do_nc (void)
|
||||
edit_stack_init ();
|
||||
#endif
|
||||
|
||||
midnight_dlg = dlg_create (FALSE, 0, 0, LINES, COLS, dialog_colors, midnight_callback,
|
||||
midnight_event, "[main]", NULL, DLG_NONE);
|
||||
midnight_dlg = dlg_create (FALSE, 0, 0, LINES, COLS, dialog_colors, midnight_callback, NULL,
|
||||
"[main]", NULL, DLG_NONE);
|
||||
|
||||
/* Check if we were invoked as an editor or file viewer */
|
||||
if (mc_global.mc_run_mode != MC_RUN_FULL)
|
||||
|
Loading…
Reference in New Issue
Block a user