WGroup: support mouse events.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2016-11-15 09:33:34 +03:00
parent 4b3b49faad
commit c2aadb2ad5
9 changed files with 134 additions and 88 deletions

View File

@ -205,75 +205,6 @@ dlg_handle_key (WDialog * h, int d_key)
return MSG_NOT_HANDLED;
}
/* --------------------------------------------------------------------------------------------- */
/**
* This is the low-level mouse handler.
* It receives a Gpm_Event event and translates it into a higher level protocol.
*/
static int
dlg_mouse_translator (Gpm_Event * event, Widget * w)
{
mouse_event_t me;
me = mouse_translate_event (w, event);
return mouse_process_event (w, &me);
}
/* --------------------------------------------------------------------------------------------- */
static int
dlg_mouse_event (WDialog * h, Gpm_Event * event)
{
Widget *wh = WIDGET (h);
GList *p;
/* close the dialog by mouse left click out of dialog area */
if (mouse_close_dialog && (wh->pos_flags & WPOS_FULLSCREEN) == 0
&& ((event->buttons & GPM_B_LEFT) != 0) && ((event->type & GPM_DOWN) != 0)
&& !mouse_global_in_widget (event, wh))
{
h->ret_value = B_CANCEL;
dlg_stop (h);
return MOU_NORMAL;
}
if (wh->mouse_callback != NULL)
{
int mou;
mou = dlg_mouse_translator (event, wh);
if (mou != MOU_UNHANDLED)
return mou;
}
if (GROUP (h)->widgets == NULL)
return MOU_UNHANDLED;
/* send the event to widgets in reverse Z-order */
p = g_list_last (GROUP (h)->widgets);
do
{
Widget *w = WIDGET (p->data);
if (!widget_get_state (w, WST_DISABLED) && w->mouse_callback != NULL)
{
/* put global cursor position to the widget */
int ret;
ret = dlg_mouse_translator (event, w);
if (ret != MOU_UNHANDLED)
return ret;
}
p = g_list_previous (p);
}
while (p != NULL);
return MOU_UNHANDLED;
}
/* --------------------------------------------------------------------------------------------- */
static cb_ret_t
@ -398,6 +329,23 @@ dlg_key_event (WDialog * h, int d_key)
/* --------------------------------------------------------------------------------------------- */
static int
dlg_handle_mouse_event (Widget * w, Gpm_Event * event)
{
if (w->mouse_callback != NULL)
{
int mou;
mou = mouse_handle_event (w, event);
if (mou != MOU_UNHANDLED)
return mou;
}
return group_handle_mouse_event (w, event);
}
/* --------------------------------------------------------------------------------------------- */
static void
frontend_dlg_run (WDialog * h)
{
@ -437,7 +385,7 @@ frontend_dlg_run (WDialog * h)
/* Clear interrupt flag */
tty_got_interrupt ();
d_key = tty_get_event (&event, h->mouse_status == MOU_REPEAT, TRUE);
d_key = tty_get_event (&event, GROUP (h)->mouse_status == MOU_REPEAT, TRUE);
dlg_process_event (h, d_key, &event);
@ -468,6 +416,28 @@ dlg_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, v
/* --------------------------------------------------------------------------------------------- */
void
dlg_default_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
{
switch (msg)
{
case MSG_MOUSE_CLICK:
if (event->y < 0 || event->y >= w->lines || event->x < 0 || event->x >= w->cols)
{
DIALOG (w)->ret_value = B_CANCEL;
dlg_stop (DIALOG (w));
}
break;
default:
/* return MOU_UNHANDLED */
event->result.abort = TRUE;
break;
}
}
/* --------------------------------------------------------------------------------------------- */
WDialog *
dlg_create (gboolean modal, int y1, int x1, int lines, int cols, widget_pos_flags_t pos_flags,
gboolean compact, const int *colors, widget_cb_fn callback,
@ -482,7 +452,7 @@ dlg_create (gboolean modal, int y1, int x1, int lines, int cols, widget_pos_flag
g = GROUP (new_d);
widget_adjust_position (pos_flags, &y1, &x1, &lines, &cols);
group_init (g, y1, x1, lines, cols, callback != NULL ? callback : dlg_default_callback,
mouse_callback);
mouse_callback != NULL ? mouse_callback : dlg_default_mouse_callback);
w->pos_flags = pos_flags;
w->options |= WOP_SELECTABLE | WOP_TOP_SELECT;
@ -490,13 +460,14 @@ dlg_create (gboolean modal, int y1, int x1, int lines, int cols, widget_pos_flag
/* Temporary hack: dialog doesn't have an owner, own itself. */
w->owner = g;
w->mouse_handler = dlg_handle_mouse_event;
w->mouse.forced_capture = mouse_close_dialog && (w->pos_flags & WPOS_FULLSCREEN) == 0;
new_d->color = colors;
new_d->help_ctx = help_ctx;
new_d->compact = compact;
new_d->data = NULL;
new_d->mouse_status = MOU_UNHANDLED;
if (modal)
{
frame_colors_t frame_colors;
@ -632,8 +603,12 @@ dlg_process_event (WDialog * h, int key, Gpm_Event * event)
break;
case EV_MOUSE:
h->mouse_status = dlg_mouse_event (h, event);
break;
{
Widget *w = WIDGET (h);
GROUP (h)->mouse_status = w->mouse_handler (w, event);
break;
}
default:
dlg_key_event (h, key);

View File

@ -70,9 +70,6 @@ struct WDialog
/* Set and received by the user */
int ret_value; /* Result of dlg_run() */
/* Internal flags */
int mouse_status; /* For the autorepeat status of the mouse */
/* Internal variables */
void *data; /* Data can be passed to dialog */
char *event_group; /* Name of event group for this dialog */
@ -119,8 +116,9 @@ void dlg_process_event (WDialog * h, int key, Gpm_Event * event);
char *dlg_get_title (const WDialog * h, size_t len);
/* Default callback for dialogs */
/* Default callbacks for dialogs */
cb_ret_t dlg_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data);
void dlg_default_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event);
void dlg_stop (WDialog * h);

View File

@ -430,9 +430,13 @@ group_init (WGroup * g, int y1, int x1, int lines, int cols, widget_cb_fn callba
widget_init (w, y1, x1, lines, cols, callback != NULL ? callback : group_default_callback,
mouse_callback);
w->mouse_handler = group_handle_mouse_event;
w->find = group_default_find;
w->find_by_type = group_default_find_by_type;
w->find_by_id = group_default_find_by_id;
g->mouse_status = MOU_UNHANDLED;
}
/* --------------------------------------------------------------------------------------------- */
@ -471,6 +475,49 @@ group_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
/* --------------------------------------------------------------------------------------------- */
/**
* Handling mouse events.
*
* @param g WGroup object
* @param event GPM mouse event
*
* @return result of mouse event handling
*/
int
group_handle_mouse_event (Widget * w, Gpm_Event * event)
{
WGroup *g = GROUP (w);
if (g->widgets != NULL)
{
GList *p;
/* send the event to widgets in reverse Z-order */
p = g_list_last (g->widgets);
do
{
Widget *wp = WIDGET (p->data);
if (!widget_get_state (wp, WST_DISABLED))
{
/* put global cursor position to the widget */
int ret;
ret = wp->mouse_handler (wp, event);
if (ret != MOU_UNHANDLED)
return ret;
}
p = g_list_previous (p);
}
while (p != NULL);
}
return MOU_UNHANDLED;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Insert widget to group before specified widget with specified positioning.
* Make the inserted widget current.

View File

@ -31,6 +31,7 @@ struct WGroup
GList *current; /* Currently active widget */
gboolean winch_pending; /* SIGWINCH signal has been got. Resize group after rise */
int mouse_status; /* For the autorepeat status of the mouse */
};
/*** global variables defined in .c file *********************************************************/
@ -42,6 +43,7 @@ void group_init (WGroup * g, int y1, int x1, int lines, int cols, widget_cb_fn c
/* Default callback for groups */
cb_ret_t group_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
void *data);
int group_handle_mouse_event (Widget * w, Gpm_Event * event);
unsigned long group_add_widget_autopos (WGroup * g, void *w, widget_pos_flags_t pos_flags,
const void *before);

View File

@ -69,8 +69,6 @@ init_mouse_event (mouse_event_t * event, mouse_msg_t msg, const Gpm_Event * glob
event->result.repeat = FALSE;
}
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/**
@ -81,7 +79,7 @@ init_mouse_event (mouse_event_t * event, mouse_msg_t msg, const Gpm_Event * glob
*
* @return high level mouse event
*/
mouse_event_t
static mouse_event_t
mouse_translate_event (Widget * w, Gpm_Event * event)
{
gboolean in_widget;
@ -172,7 +170,7 @@ mouse_translate_event (Widget * w, Gpm_Event * event)
*
* @return result of mouse event handling
*/
int
static int
mouse_process_event (Widget * w, mouse_event_t * event)
{
int ret = MOU_UNHANDLED;
@ -201,4 +199,27 @@ mouse_process_event (Widget * w, mouse_event_t * event)
return ret;
}
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/**
* Translate GPM event to high-level event and process it
*
* @param w Widget object
* @param event GPM event
*
* @return result of mouse event handling
*/
int
mouse_handle_event (Widget * w, Gpm_Event * event)
{
mouse_event_t me;
me = mouse_translate_event (w, event);
return mouse_process_event (w, &me);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -57,10 +57,8 @@ typedef struct
/*** declarations of public functions ************************************************************/
/* Translate GPM event to high-level event */
mouse_event_t mouse_translate_event (Widget * w, Gpm_Event * event);
/* Process high-level mouse event */
int mouse_process_event (Widget * w, mouse_event_t * event);
/* Translate GPM event to high-level event and process it */
int mouse_handle_event (Widget * w, Gpm_Event * event);
/*** inline functions ****************************************************************************/

View File

@ -299,6 +299,7 @@ widget_init (Widget * w, int y, int x, int lines, int cols,
w->callback = callback;
w->mouse_callback = mouse_callback;
w->owner = NULL;
w->mouse_handler = mouse_handle_event;
w->mouse.forced_capture = FALSE;
w->mouse.capture = FALSE;
w->mouse.last_msg = MSG_MOUSE_NONE;

View File

@ -122,6 +122,8 @@ typedef cb_ret_t (*widget_cb_fn) (Widget * widget, Widget * sender, widget_msg_t
void *data);
/* Widget mouse callback */
typedef void (*widget_mouse_cb_fn) (Widget * w, mouse_msg_t msg, mouse_event_t * event);
/* translate mouse event and process it */
typedef int (*widget_mouse_handle_fn) (Widget * w, Gpm_Event * event);
/* Every Widget must have this as its first element */
struct Widget
@ -135,7 +137,9 @@ struct Widget
widget_cb_fn callback;
widget_mouse_cb_fn mouse_callback;
WGroup *owner;
/* Mouse-related fields. */
widget_mouse_handle_fn mouse_handler;
struct
{
/* Public members: */

View File

@ -958,7 +958,7 @@ check_find_events (WDialog * h)
int c;
event.x = -1;
c = tty_get_event (&event, h->mouse_status == MOU_REPEAT, FALSE);
c = tty_get_event (&event, GROUP (h)->mouse_status == MOU_REPEAT, FALSE);
if (c != EV_NONE)
{
dlg_process_event (h, c, &event);