Просмотр исходного кода

WGroup: support mouse events.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Andrew Borodin 8 лет назад
Родитель
Сommit
c2aadb2ad5

+ 50 - 75
lib/widget/dialog.c

@@ -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);

+ 2 - 4
lib/widget/dialog.h

@@ -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);
 

+ 47 - 0
lib/widget/group.c

@@ -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.

+ 2 - 0
lib/widget/group.h

@@ -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);

+ 25 - 4
lib/widget/mouse.c

@@ -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);
+}
+
 /* --------------------------------------------------------------------------------------------- */

+ 2 - 4
lib/widget/mouse.h

@@ -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 ****************************************************************************/
 

+ 1 - 0
lib/widget/widget-common.c

@@ -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;

+ 4 - 0
lib/widget/widget-common.h

@@ -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: */

+ 1 - 1
src/filemanager/find.c

@@ -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);