Ticket #4134: 0001-OSK-im-osk-position.3.patch

File 0001-OSK-im-osk-position.3.patch, 24.1 KB (added by garnacho, 11 years ago)

Updated patch

  • gtk/gtkimcontext.c

    From 28dceb6b2d9e6e37c15a09f47da5a4f23f78b9a6 Mon Sep 17 00:00:00 2001
    From: Carlos Garnacho <carlos@lanedo.com>
    Date: Wed, 19 Sep 2012 15:37:01 +0200
    Subject: [PATCH] OSK: im-osk-position
    
    Patch based on: http://git.gnome.org/browse/gtk+/log/?h=wip/im-osk-position
    ---
     gtk/gtkimcontext.c      | 185 +++++++++++++++++++++++++++++++++++++++++++++++-
     gtk/gtkimmulticontext.c |  20 ++++++
     gtk/gtkscrolledwindow.c | 117 +++++++++++++++++++++++++++---
     gtk/gtkwidget.c         |  75 ++++++++++++++++++++
     gtk/gtkwidget.h         |   6 ++
     5 files changed, 389 insertions(+), 14 deletions(-)
    
    diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c
    index f0f351f..7a03d3e 100644
    a b enum { 
    105105  COMMIT,
    106106  RETRIEVE_SURROUNDING,
    107107  DELETE_SURROUNDING,
     108  CLEAR_AREA,
    108109  LAST_SIGNAL
    109110};
    110111
    typedef struct _GtkIMContextPrivate GtkIMContextPrivate; 
    121122struct _GtkIMContextPrivate {
    122123  GtkInputPurpose purpose;
    123124  GtkInputHints hints;
     125  GdkWindow *window;
     126  GtkWidget *widget;
     127
     128  cairo_rectangle_int_t clear_area;
     129  cairo_rectangle_int_t cursor_rect;
     130  cairo_rectangle_int_t last_notified_clear_area;
     131  guint clear_area_signal_id;
     132  guint clear_area_idle_id;
     133  guint focused : 1;
     134  guint need_unset : 1;
     135  guint need_position_update : 1;
    124136};
    125137
    126138static void     gtk_im_context_real_get_preedit_string (GtkIMContext   *context,
    static void gtk_im_context_set_property (GObject *obj, 
    145157                                                        guint           property_id,
    146158                                                        const GValue   *value,
    147159                                                        GParamSpec     *pspec);
     160static void     gtk_im_context_finalize                (GObject        *obj);
    148161
    149162
    150163G_DEFINE_ABSTRACT_TYPE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT)
    gtk_im_context_class_init (GtkIMContextClass *klass) 
    213226
    214227  object_class->get_property = gtk_im_context_get_property;
    215228  object_class->set_property = gtk_im_context_set_property;
     229  object_class->finalize = gtk_im_context_finalize;
    216230
    217231  klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
    218232  klass->filter_keypress = gtk_im_context_real_filter_keypress;
    gtk_im_context_class_init (GtkIMContextClass *klass) 
    327341                  G_TYPE_INT,
    328342                  G_TYPE_INT);
    329343
     344  im_context_signals[CLEAR_AREA] =
     345      g_signal_new (I_("clear-area"),
     346                    G_TYPE_FROM_CLASS (klass),
     347                    G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
     348                    0, NULL, NULL,
     349                    _gtk_marshal_VOID__BOXED_BOXED,
     350                    G_TYPE_NONE, 2,
     351                    GDK_TYPE_RECTANGLE, GDK_TYPE_RECTANGLE);
     352
    330353  properties[PROP_INPUT_PURPOSE] =
    331354    g_param_spec_enum ("input-purpose",
    332355                         P_("Purpose"),
    gtk_im_context_real_get_surrounding (GtkIMContext *context, 
    438461  return result;
    439462}
    440463
     464static gboolean
     465_gtk_im_context_clear_area_idle (gpointer user_data)
     466{
     467  GtkIMContext *context = user_data;
     468  GtkIMContextPrivate *priv;
     469
     470  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT,
     471                                      GtkIMContextPrivate);
     472
     473  if (priv->need_position_update &&
     474      (priv->clear_area.x != priv->last_notified_clear_area.x ||
     475       priv->clear_area.y != priv->last_notified_clear_area.y ||
     476       priv->clear_area.width != priv->last_notified_clear_area.width ||
     477       priv->clear_area.height != priv->last_notified_clear_area.height))
     478    {
     479      if (priv->focused &&
     480          priv->clear_area.width != 0 && priv->clear_area.height != 0)
     481        {
     482          cairo_rectangle_int_t rect;
     483          GtkAllocation allocation;
     484
     485          rect = priv->cursor_rect;
     486
     487          gtk_widget_get_allocation (priv->widget, &allocation);
     488          rect.x += allocation.x;
     489          rect.y += allocation.y;
     490          gdk_window_get_root_coords (priv->window,
     491                                      rect.x, rect.y, &rect.x, &rect.y);
     492
     493          if (gtk_widget_request_clear_area (priv->widget, &priv->clear_area, &rect))
     494            priv->need_unset = TRUE;
     495        }
     496      else if (!priv->focused && priv->need_unset)
     497        {
     498          gtk_widget_unset_clear_area (priv->widget, TRUE);
     499          priv->need_unset = FALSE;
     500        }
     501
     502      priv->last_notified_clear_area = priv->clear_area;
     503    }
     504
     505  priv->need_position_update = FALSE;
     506  priv->clear_area_idle_id = 0;
     507  return FALSE;
     508}
     509
     510static void
     511_gtk_im_context_check_clear_area (GtkIMContext *context)
     512{
     513  GtkIMContextPrivate *priv;
     514
     515  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT,
     516                                      GtkIMContextPrivate);
     517
     518  if (priv->clear_area_idle_id)
     519    g_source_remove (priv->clear_area_idle_id);
     520
     521  priv->clear_area_idle_id =
     522    g_idle_add (_gtk_im_context_clear_area_idle, context);
     523}
     524
     525static void
     526_gtk_im_context_clear_area (GtkIMContext          *context,
     527                            cairo_rectangle_int_t *clear_area,
     528                            cairo_rectangle_int_t *cursor_rect,
     529                            GtkWidget             *widget)
     530{
     531  GtkIMContextPrivate *priv;
     532
     533  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate);
     534
     535  if (priv->clear_area.x != clear_area->x ||
     536      priv->clear_area.y != clear_area->y ||
     537      priv->clear_area.width != clear_area->width ||
     538      priv->clear_area.height != clear_area->height)
     539    priv->need_position_update = TRUE;
     540
     541  priv->clear_area = *clear_area;
     542}
     543
    441544/**
    442545 * gtk_im_context_set_client_window:
    443546 * @context: a #GtkIMContext
    gtk_im_context_set_client_window (GtkIMContext *context, 
    454557                                  GdkWindow    *window)
    455558{
    456559  GtkIMContextClass *klass;
    457  
     560  GtkIMContextPrivate *priv;
     561
    458562  g_return_if_fail (GTK_IS_IM_CONTEXT (context));
    459563
    460564  klass = GTK_IM_CONTEXT_GET_CLASS (context);
    461565  if (klass->set_client_window)
    462566    klass->set_client_window (context, window);
     567
     568  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate);
     569
     570  if (priv->clear_area_signal_id)
     571    {
     572      g_signal_handler_disconnect (context, priv->clear_area_signal_id);
     573      priv->clear_area_signal_id = 0;
     574    }
     575
     576  if (window)
     577    {
     578      gpointer window_data;
     579
     580      gdk_window_get_user_data (window, &window_data);
     581
     582      if (GTK_IS_WIDGET (window_data))
     583        {
     584          priv->clear_area_signal_id = g_signal_connect (context, "clear-area",
     585                                                         G_CALLBACK (_gtk_im_context_clear_area),
     586                                                         window_data);
     587          priv->window = window;
     588          priv->widget = window_data;
     589        }
     590    }
    463591}
    464592
    465593/**
    void 
    531659gtk_im_context_focus_in (GtkIMContext   *context)
    532660{
    533661  GtkIMContextClass *klass;
    534  
     662  GtkIMContextPrivate *priv;
     663
    535664  g_return_if_fail (GTK_IS_IM_CONTEXT (context));
    536665 
    537666  klass = GTK_IM_CONTEXT_GET_CLASS (context);
    538667  if (klass->focus_in)
    539668    klass->focus_in (context);
     669
     670  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate);
     671
     672  if (!priv->focused)
     673    {
     674      priv->focused = TRUE;
     675      priv->need_position_update = TRUE;
     676    }
     677
     678  _gtk_im_context_check_clear_area (context);
    540679}
    541680
    542681/**
    void 
    552691gtk_im_context_focus_out (GtkIMContext   *context)
    553692{
    554693  GtkIMContextClass *klass;
    555  
     694  GtkIMContextPrivate *priv;
     695
    556696  g_return_if_fail (GTK_IS_IM_CONTEXT (context));
    557697
    558698  klass = GTK_IM_CONTEXT_GET_CLASS (context);
    559699  if (klass->focus_out)
    560700    klass->focus_out (context);
     701
     702  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate);
     703
     704  if (priv->focused)
     705    gtk_widget_unset_clear_area (priv->widget, TRUE);
     706
     707  _gtk_im_context_check_clear_area (context);
     708  priv->focused = FALSE;
    561709}
    562710
    563711/**
    gtk_im_context_reset (GtkIMContext *context) 
    575723 
    576724  g_return_if_fail (GTK_IS_IM_CONTEXT (context));
    577725
     726  _gtk_im_context_check_clear_area (context);
     727
    578728  klass = GTK_IM_CONTEXT_GET_CLASS (context);
    579729  if (klass->reset)
    580730    klass->reset (context);
    gtk_im_context_set_cursor_location (GtkIMContext *context, 
    595745                                    const GdkRectangle *area)
    596746{
    597747  GtkIMContextClass *klass;
     748  GtkIMContextPrivate *priv;
    598749 
    599750  g_return_if_fail (GTK_IS_IM_CONTEXT (context));
    600751
     752  priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT,
     753                                      GtkIMContextPrivate);
     754
     755  if (priv->cursor_rect.x != area->x ||
     756      priv->cursor_rect.y != area->y ||
     757      priv->cursor_rect.width != area->width ||
     758      priv->cursor_rect.height != area->height)
     759    {
     760      priv->cursor_rect = *area;
     761      priv->need_position_update = TRUE;
     762    }
     763
    601764  klass = GTK_IM_CONTEXT_GET_CLASS (context);
    602765  if (klass->set_cursor_location)
    603766    klass->set_cursor_location (context, (GdkRectangle *) area);
     767
     768  _gtk_im_context_check_clear_area (context);
    604769}
    605770
    606771/**
    gtk_im_context_set_property (GObject *obj, 
    798963      break;
    799964    }
    800965}
     966
     967static void
     968gtk_im_context_finalize (GObject *obj)
     969{
     970  GtkIMContextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate);
     971
     972  if (priv->clear_area_signal_id)
     973    g_signal_handler_disconnect (obj, priv->clear_area_signal_id);
     974
     975  if (priv->clear_area_idle_id)
     976    g_source_remove (priv->clear_area_idle_id);
     977
     978  G_OBJECT_CLASS (gtk_im_context_parent_class)->finalize (obj);
     979}
  • gtk/gtkimmulticontext.c

    diff --git a/gtk/gtkimmulticontext.c b/gtk/gtkimmulticontext.c
    index 712d5ca..69fba46 100644
    a b static gboolean gtk_im_multicontext_delete_surrounding_cb (GtkIMContext * 
    102102                                                             gint               n_chars,
    103103                                                             GtkIMMulticontext *multicontext);
    104104
     105static void     gtk_im_multicontext_clear_area_cb           (GtkIMContext      *slave,
     106                                                             GdkRectangle      *osk_rect,
     107                                                             GdkRectangle      *cursor_rect,
     108                                                             GtkIMMulticontext *multicontext);
     109
    105110static void propagate_purpose (GtkIMMulticontext *context);
    106111
    107112static const gchar *global_context_id = NULL;
    gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, 
    197202      g_signal_handlers_disconnect_by_func (priv->slave,
    198203                                            gtk_im_multicontext_commit_cb,
    199204                                            multicontext);
     205      g_signal_handlers_disconnect_by_func (priv->slave,
     206                                            gtk_im_multicontext_clear_area_cb,
     207                                            multicontext);
    200208
    201209      g_object_unref (priv->slave);
    202210      priv->slave = NULL;
    gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, 
    231239      g_signal_connect (priv->slave, "delete-surrounding",
    232240                        G_CALLBACK (gtk_im_multicontext_delete_surrounding_cb),
    233241                        multicontext);
     242      g_signal_connect (priv->slave, "clear-area",
     243                        G_CALLBACK (gtk_im_multicontext_clear_area_cb),
     244                        multicontext);
    234245
    235246      if (!priv->use_preedit)   /* Default is TRUE */
    236247        gtk_im_context_set_use_preedit (slave, FALSE);
    gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave, 
    553564}
    554565
    555566static void
     567gtk_im_multicontext_clear_area_cb (GtkIMContext      *slave,
     568                                   GdkRectangle      *osk_rect,
     569                                   GdkRectangle      *cursor_rect,
     570                                   GtkIMMulticontext *multicontext)
     571{
     572  g_signal_emit_by_name (multicontext, "clear-area", osk_rect, cursor_rect);
     573}
     574
     575static void
    556576activate_cb (GtkWidget         *menuitem,
    557577             GtkIMMulticontext *context)
    558578{
  • gtk/gtkscrolledwindow.c

    diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
    index 08a286c..31d83ec 100644
    a b struct _GtkScrolledWindowPrivate 
    176176
    177177  gdouble                unclamped_hadj_value;
    178178  gdouble                unclamped_vadj_value;
     179  gdouble                clear_area_dy;
     180  gdouble                focus_area_dy;
    179181};
    180182
    181183typedef struct
    static gboolean _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindo 
    287289                                                                gboolean           allow_overshooting,
    288290                                                                gboolean           snap_to_border);
    289291
     292static gboolean gtk_scrolled_window_request_clear_area (GtkWidget             *widget,
     293                                                        cairo_rectangle_int_t *clear_area,
     294                                                        cairo_rectangle_int_t *cursor_area,
     295                                                        gpointer               user_data);
     296static gboolean gtk_scrolled_window_unset_clear_area   (GtkWidget             *widget,
     297                                                         gboolean               snap_back,
     298                                                        gpointer               user_data);
     299
    290300static guint signals[LAST_SIGNAL] = {0};
    291301
    292302G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
    gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) 
    597607  gtk_scrolled_window_update_real_placement (scrolled_window);
    598608  priv->min_content_width = -1;
    599609  priv->min_content_height = -1;
     610  priv->focus_area_dy = 0;
     611  priv->clear_area_dy = 0;
    600612
    601613  gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
    602614  gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
     615
     616  g_signal_connect (scrolled_window, "request-clear-area",
     617                    G_CALLBACK (gtk_scrolled_window_request_clear_area),
     618                    NULL);
     619  g_signal_connect (scrolled_window, "unset-clear-area",
     620                    G_CALLBACK (gtk_scrolled_window_unset_clear_area),
     621                    NULL);
    603622}
    604623
    605624/**
    _gtk_scrolled_window_get_overshoot (GtkScrolledWindow *scrolled_window, 
    18231842
    18241843  if (priv->unclamped_vadj_value < lower)
    18251844    y = priv->unclamped_vadj_value - lower;
    1826   else if (priv->unclamped_vadj_value > upper)
    1827     y = priv->unclamped_vadj_value - upper;
     1845  else if (priv->unclamped_vadj_value + priv->focus_area_dy > upper)
     1846    y = priv->unclamped_vadj_value - upper + priv->focus_area_dy;
    18281847  else
    18291848    y = 0;
    18301849
    _gtk_scrolled_window_allocate_overshoot_window (GtkScrolledWindow *scrolled_wind 
    18781897    window_allocation.x += -overshoot_x;
    18791898
    18801899  if (overshoot_y < 0)
     1900  {
     1901    window_allocation.y -= priv->focus_area_dy;
    18811902    window_allocation.y += -overshoot_y;
     1903  }
    18821904
    18831905  window_allocation.width -= ABS (overshoot_x);
    18841906  window_allocation.height -= ABS (overshoot_y);
    gtk_scrolled_window_size_allocate (GtkWidget *widget, 
    22492271    gtk_widget_hide (priv->vscrollbar);
    22502272
    22512273  _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
     2274  _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget),
     2275                                             gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)),
     2276                                             priv->unclamped_vadj_value,
     2277                                             TRUE, FALSE);
    22522278}
    22532279
    22542280static gboolean
    _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, 
    23522378                                           gboolean           snap_to_border)
    23532379{
    23542380  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
    2355   gdouble lower, upper, *prev_value;
     2381  gdouble lower, upper, *prev_value, diff = 0;
    23562382
    23572383  lower = gtk_adjustment_get_lower (adjustment);
    23582384  upper = gtk_adjustment_get_upper (adjustment) -
    _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, 
    23612387  if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar)))
    23622388    prev_value = &priv->unclamped_hadj_value;
    23632389  else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)))
    2364     prev_value = &priv->unclamped_vadj_value;
     2390    {
     2391      diff = priv->focus_area_dy;
     2392      upper += priv->clear_area_dy;
     2393      prev_value = &priv->unclamped_vadj_value;
     2394    }
    23652395  else
    23662396    return FALSE;
    23672397
     2398  value += diff;
     2399
    23682400  if (snap_to_border)
    23692401    {
    23702402      if (*prev_value < 0 && value > 0)
    _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, 
    23792411      upper += MAX_OVERSHOOT_DISTANCE;
    23802412    }
    23812413
    2382   *prev_value = CLAMP (value, lower, upper);
    23832414  gtk_adjustment_set_value (adjustment, value);
     2415  *prev_value = CLAMP (value - diff, lower, upper);
    23842416
    2385   return (*prev_value != value);
     2417  return (*prev_value != value - diff);
    23862418}
    23872419
    23882420static gboolean
    scrolled_window_deceleration_cb (gpointer user_data) 
    24572489  else if (overshoot_x > 0)
    24582490    data->x_velocity -= OVERSHOOT_INVERSE_ACCELERATION * elapsed;
    24592491
    2460   if (overshoot_y == 0)
     2492  if (overshoot_y >= 0 && overshoot_y <= priv->clear_area_dy)
    24612493    {
    2462       if (old_overshoot_y != 0)
     2494      if (old_overshoot_y < 0 || old_overshoot_y > priv->clear_area_dy)
    24632495        {
    24642496          /* Overshooting finished snapping back */
    24652497          data->y_velocity = 0;
    gtk_scrolled_window_captured_button_release (GtkWidget *widget, 
    26232655{
    26242656  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
    26252657  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
     2658  gint overshoot_x, overshoot_y;
    26262659  GtkWidget *child;
    26272660  gboolean overshoot;
    26282661  guint button;
    gtk_scrolled_window_captured_button_release (GtkWidget *widget, 
    26442677      priv->release_timeout_id = 0;
    26452678    }
    26462679
    2647   overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
     2680  overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, &overshoot_x, &overshoot_y);
    26482681
    26492682  if (priv->in_drag)
    26502683    gdk_device_ungrab (gdk_event_get_device (event), gdk_event_get_time (event));
    gtk_scrolled_window_captured_button_release (GtkWidget *widget, 
    26552688       */
    26562689      gtk_scrolled_window_release_captured_event (scrolled_window);
    26572690
    2658       if (!overshoot)
     2691      if (!overshoot ||
     2692          (overshoot_x == 0 && overshoot_y >= 0 &&
     2693           overshoot_y <= priv->clear_area_dy))
    26592694        return FALSE;
    26602695    }
    26612696  priv->in_drag = FALSE;
    gtk_scrolled_window_captured_motion_notify (GtkWidget *widget, 
    27632798  vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
    27642799  if (vadjustment && priv->vscrollbar_visible)
    27652800    {
    2766       dy = (priv->last_motion_event_y_root - y_root) + priv->unclamped_vadj_value;
     2801      dy = (priv->last_motion_event_y_root - y_root) + priv->unclamped_vadj_value + priv->focus_area_dy;
    27672802      _gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
    27682803                                                 dy, TRUE, FALSE);
    27692804    }
    27702805
     2806  priv->focus_area_dy = 0;
    27712807  _gtk_scrolled_window_get_overshoot (scrolled_window,
    27722808                                      &new_overshoot_x, &new_overshoot_y);
    27732809
    gtk_scrolled_window_grab_notify (GtkWidget *widget, 
    35003536    }
    35013537}
    35023538
     3539static gboolean
     3540gtk_scrolled_window_request_clear_area (GtkWidget             *widget,
     3541                                        cairo_rectangle_int_t *clear_area,
     3542                                        cairo_rectangle_int_t *cursor_area,
     3543                                        gpointer               user_data)
     3544{
     3545  GtkScrolledWindowPrivate *priv;
     3546  GtkAdjustment *adjustment;
     3547  GtkAllocation allocation;
     3548
     3549  priv = GTK_SCROLLED_WINDOW (widget)->priv;
     3550  adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
     3551
     3552  gtk_widget_get_allocation (widget, &allocation);
     3553  gdk_window_get_root_coords (gtk_widget_get_window (widget),
     3554                              allocation.x, allocation.y,
     3555                              &allocation.x, &allocation.y);
     3556
     3557  priv->clear_area_dy = allocation.y + allocation.height - clear_area->y;
     3558  priv->focus_area_dy = cursor_area->y + cursor_area->height - clear_area->y;
     3559  _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget),
     3560                                             adjustment, priv->unclamped_vadj_value,
     3561                                             TRUE, FALSE);
     3562  gtk_widget_queue_resize (widget);
     3563
     3564  return TRUE;
     3565}
     3566
     3567static gboolean
     3568gtk_scrolled_window_unset_clear_area (GtkWidget *widget,
     3569                                      gboolean   snap_back,
     3570                                      gpointer   user_data)
     3571{
     3572  GtkScrolledWindowPrivate *priv;
     3573
     3574  priv = GTK_SCROLLED_WINDOW (widget)->priv;
     3575
     3576  if (priv->clear_area_dy != 0 || priv->focus_area_dy != 0)
     3577    {
     3578      priv->clear_area_dy = 0;
     3579      priv->focus_area_dy = 0;
     3580
     3581      if (snap_back)
     3582        {
     3583          GtkAdjustment *adjustment;
     3584
     3585          adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
     3586          _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget),
     3587                                                     adjustment, priv->unclamped_vadj_value,
     3588                                                     FALSE, FALSE);
     3589          gtk_widget_queue_resize (widget);
     3590        }
     3591
     3592      return TRUE;
     3593    }
     3594
     3595  return FALSE;
     3596}
     3597
    35033598/**
    35043599 * gtk_scrolled_window_get_min_content_width:
    35053600 * @scrolled_window: a #GtkScrolledWindow
  • gtk/gtkwidget.c

    diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
    index eb82eb8..289c5e5 100644
    a b enum { 
    482482  DRAG_FAILED,
    483483  STYLE_UPDATED,
    484484  TOUCH_EVENT,
     485  REQUEST_CLEAR_AREA,
     486  UNSET_CLEAR_AREA,
    485487  LAST_SIGNAL
    486488};
    487489
    gtk_widget_class_init (GtkWidgetClass *klass) 
    31163118                  _gtk_marshal_BOOLEAN__UINT,
    31173119                  G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
    31183120
     3121  widget_signals[REQUEST_CLEAR_AREA] =
     3122    g_signal_new (I_("request-clear-area"),
     3123                  G_TYPE_FROM_CLASS (klass),
     3124                  G_SIGNAL_RUN_LAST, 0,
     3125                  g_signal_accumulator_true_handled, NULL,
     3126                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
     3127                  G_TYPE_BOOLEAN, 2,
     3128                  CAIRO_GOBJECT_TYPE_RECTANGLE_INT,
     3129                  CAIRO_GOBJECT_TYPE_RECTANGLE_INT);
     3130  widget_signals[UNSET_CLEAR_AREA] =
     3131    g_signal_new (I_("unset-clear-area"),
     3132                  G_TYPE_FROM_CLASS (klass),
     3133                  G_SIGNAL_RUN_LAST, 0,
     3134                  g_signal_accumulator_true_handled, NULL,
     3135                  _gtk_marshal_BOOLEAN__BOOLEAN,
     3136                  G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
     3137
    31193138  binding_set = gtk_binding_set_by_class (klass);
    31203139  gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK,
    31213140                                "popup-menu", 0);
    gtk_widget_insert_action_group (GtkWidget *widget, 
    1414414163  else
    1414514164    g_action_muxer_remove (muxer, name);
    1414614165}
     14166
     14167gboolean
     14168gtk_widget_request_clear_area (GtkWidget             *widget,
     14169                               cairo_rectangle_int_t *clear_area,
     14170                               cairo_rectangle_int_t *cursor_position)
     14171{
     14172  gboolean handled = FALSE;
     14173  GtkWidget *cur;
     14174
     14175  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
     14176  g_return_val_if_fail (cursor_position != NULL, FALSE);
     14177  g_return_val_if_fail (clear_area != NULL, FALSE);
     14178
     14179  if (!gtk_widget_has_focus (widget))
     14180    return FALSE;
     14181
     14182  if (cursor_position->x <= clear_area->x - cursor_position->width ||
     14183      cursor_position->x >= clear_area->x + clear_area->width ||
     14184      cursor_position->y <= clear_area->y - cursor_position->height ||
     14185      cursor_position->y >= clear_area->y + clear_area->height)
     14186    return FALSE;
     14187
     14188  cur = widget;
     14189
     14190  while (!handled && cur)
     14191    {
     14192      g_signal_emit (cur, widget_signals[REQUEST_CLEAR_AREA], 0,
     14193                     clear_area, cursor_position, &handled);
     14194
     14195      if (!handled)
     14196        cur = gtk_widget_get_parent (cur);
     14197    }
     14198
     14199  return handled;
     14200}
     14201
     14202gboolean
     14203gtk_widget_unset_clear_area (GtkWidget *widget,
     14204                             gboolean   snap_back)
     14205{
     14206  gboolean handled = FALSE;
     14207  GtkWidget *cur;
     14208
     14209  cur = widget;
     14210
     14211  while (!handled && cur)
     14212    {
     14213      g_signal_emit (cur, widget_signals[UNSET_CLEAR_AREA], 0,
     14214                     snap_back, &handled);
     14215
     14216      if (!handled)
     14217        cur = gtk_widget_get_parent (cur);
     14218    }
     14219
     14220  return handled;
     14221}
  • gtk/gtkwidget.h

    diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
    index 2cdc7f3..4db2c99 100644
    a b GDK_AVAILABLE_IN_3_4 
    887887GdkModifierType   gtk_widget_get_modifier_mask (GtkWidget         *widget,
    888888                                                GdkModifierIntent  intent);
    889889
     890gboolean gtk_widget_request_clear_area (GtkWidget             *widget,
     891                                        cairo_rectangle_int_t *clear_area,
     892                                        cairo_rectangle_int_t *cursor_position);
     893gboolean gtk_widget_unset_clear_area   (GtkWidget             *widget,
     894                                        gboolean               snap_back);
     895
    890896GDK_AVAILABLE_IN_3_6
    891897void                    gtk_widget_insert_action_group                  (GtkWidget    *widget,
    892898                                                                         const gchar  *name,