Re: Tap and Hold API



El mar, 17-04-2007 a las 12:02 +0200, Kristian Rietveld escribi�> Recently I have been working on a tap-n-hold implementation based on the
> implementation found in Maemo.  Tap-n-hold allows for a callback to be
> called after a mouse button has been pressed for a given amount of time
> This action is particularly useful on touch screen devices, since it can be
> used to, for example, popup a context menu instead of using the right
> mouse button which is not available on these devices.

Nice!  This is always cumbersome to implement by hand.

>   typedef enum
>   {
>     GTK_TAP_AND_HOLD_QUERY,
>     GTK_TAP_AND_HOLD_TRIGGER,
>     GTK_TAP_AND_HOLD_CANCEL
>   } GtkTapAndHoldAction;
> 
>   gboolean     (* tap_and_hold) (GtkWidget           *widget,
>                                  GtkTapAndHoldAction  action,
>                                  gint                 x,
>                                  gint                 y);
[snip]
>   * Query: once the user presses the mouse button, this signal will be
>     emitted to check whether the given location (x, y) allows for executing
>     the tap-n-hold action.  The x and y parameters are set to the location
>     of the mouse cursor (relative to the widget's allocation)  A return
>     value of FALSE means no tap-n-hold action should occur.

As a widget, checking (x, y) based on your allocation is not convenient
if you have subwindows.  Why not pass a complete GdkEventButton
structure to the signal?  That way you can see the event->window and
deduce things more easily.

[If you have a simple stylus I guess you don't need to know about a
particular mouse button.  Are there styluses for which you would need a
button number?  Tap-and-hold-while-pressing-a-certain-button-
in-the-fancy-wacom-stylus?]

[Let's not repeat the mistake of having event-generated signals which
don't give you the actual event structure, like in DnD for GtkTreeView.]

>   * Trigger: if the application returned TRUE in response to the query
>     signal and the user hold the button and did not move the mouse past the
>     threshold (currently the drag threshold is used for this) during the
>     timeout period, this signal will be emitted.  X and y again reflect the
>     position of the mouse cursor.  The return value of the signal is not of
>     any significance and ignored.

What happens when you already have a button-press-event handler?  Or is
the intention that you replace that handler with the tap-and-hold one?

[I.e. is it easy to retrofit apps to support tap-and-hold with ths new
API, or do all the event handlers need to be changed?]

> A GtkSetting called "gtk-tap-and-hold-timeout" has been added, which is
> used to set the tap-n-hold timeout.

Does this interact the Right Way with respect to widgets that already
have automatic drag handlers set up for them?  I.e. you tap and hold for
a bit, then actually drag.  The widget should emit tap-and-hold(cancel)
and then drag-begin.

> During the timeout period between pressing the button and triggering the
> tap-n-hold action the mouse cursor will be replaced by an animation,
> indicating that "something" is happening.

I guess this has to be experienced to get a good feel, but my
spider-sense tells me that widgets will prefer to show the "I'm armed"
state by themselves, rather than relying on an automatic cursor.  How
would the widget change the cursor itself when it gets the "trigger"
version of the signal?  Do we need an API analogous to
gtk_drag_set_icon_*()?

> Another questionable point is whether we should allow for tap-n-hold
> actions to be triggered via the keyboard.  This is probably a good thing
> to do and would involve adding a gboolean "triggered_by_keyboard" to the
> signal signature, just like the new tooltips API has.  Does anyone have
> better suggestions here?

But then you would need to bind a key to the tap-and-hold action, and
that gets messy.

I'd prefer a way to solve the "Photoshop spacebar" problem:  say a
drawing program wants to let you scroll the view by holding down the
spacebar while you press-and-drag with the mouse.  (This is to avoid
having to switch to the "scroll the view" tool temporarily, and it is
*very* convenient!)

If you hold down the spacebar, currently you get a fast stream of
key_press/key_release events, and you have to implement the "Photoshop
spacebar" by hand using timers.  It would be more comfortable to just
say

  static gboolean
  my_key_press_event_handler (GtkWidget *widget, GdkEventKey *event)
  {
     MyWidget *my = MY_WIDGET (widget);

     if (event->keyval == GDK_SPACE) {
         gdk_dont_emit_key_release_until_user_actually_releases_the_key (GDK_SPACE);
         my->is_scrolling = TRUE;
         return TRUE;
     }

     return FALSE;
  }

  static gboolean
  my_key_release_event_handler (GtkWidget *widget, GdkEventKey *event)
  {
     MyWidget *my = MY_WIDGET (widget);

     if (event->keyval == GDK_SPACE) {
         my->is_scrolling = FALSE;
         return TRUE;
     }

     return FALSE;
  }

  Federico




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]