From 1117a90cdee4352bdbf123ec5e0517002758b4f3 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 | 46 +++++++++++++++++++++++++++++-
gtk/gtkimmulticontext.c | 20 +++++++++++++
gtk/gtkscrolledwindow.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-
gtk/gtkwidget.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkwidget.h | 6 ++++
5 files changed, 218 insertions(+), 2 deletions(-)
diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c
index f0f351f..645795b 100644
a
|
b
|
enum { |
105 | 105 | COMMIT, |
106 | 106 | RETRIEVE_SURROUNDING, |
107 | 107 | DELETE_SURROUNDING, |
| 108 | CLEAR_AREA, |
108 | 109 | LAST_SIGNAL |
109 | 110 | }; |
110 | 111 | |
… |
… |
typedef struct _GtkIMContextPrivate GtkIMContextPrivate; |
121 | 122 | struct _GtkIMContextPrivate { |
122 | 123 | GtkInputPurpose purpose; |
123 | 124 | GtkInputHints hints; |
| 125 | guint clear_area_signal_id; |
124 | 126 | }; |
125 | 127 | |
126 | 128 | static void gtk_im_context_real_get_preedit_string (GtkIMContext *context, |
… |
… |
gtk_im_context_class_init (GtkIMContextClass *klass) |
327 | 329 | G_TYPE_INT, |
328 | 330 | G_TYPE_INT); |
329 | 331 | |
| 332 | im_context_signals[CLEAR_AREA] = |
| 333 | g_signal_new (I_("clear-area"), |
| 334 | G_TYPE_FROM_CLASS (klass), |
| 335 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
| 336 | 0, NULL, NULL, |
| 337 | _gtk_marshal_VOID__BOXED_BOXED, |
| 338 | G_TYPE_NONE, 2, |
| 339 | GDK_TYPE_RECTANGLE, GDK_TYPE_RECTANGLE); |
| 340 | |
330 | 341 | properties[PROP_INPUT_PURPOSE] = |
331 | 342 | g_param_spec_enum ("input-purpose", |
332 | 343 | P_("Purpose"), |
… |
… |
gtk_im_context_real_get_surrounding (GtkIMContext *context, |
438 | 449 | return result; |
439 | 450 | } |
440 | 451 | |
| 452 | static void |
| 453 | _gtk_im_context_clear_area (GtkIMContext *context, |
| 454 | cairo_rectangle_int_t *clear_area, |
| 455 | cairo_rectangle_int_t *cursor_rect, |
| 456 | GtkWidget *widget) |
| 457 | { |
| 458 | gtk_widget_unset_clear_area (widget, TRUE); |
| 459 | |
| 460 | if (clear_area->width != 0 && clear_area->height != 0) |
| 461 | gtk_widget_request_clear_area (widget, clear_area, cursor_rect); |
| 462 | } |
| 463 | |
441 | 464 | /** |
442 | 465 | * gtk_im_context_set_client_window: |
443 | 466 | * @context: a #GtkIMContext |
… |
… |
gtk_im_context_set_client_window (GtkIMContext *context, |
454 | 477 | GdkWindow *window) |
455 | 478 | { |
456 | 479 | GtkIMContextClass *klass; |
457 | | |
| 480 | GtkIMContextPrivate *priv; |
| 481 | |
458 | 482 | g_return_if_fail (GTK_IS_IM_CONTEXT (context)); |
459 | 483 | |
460 | 484 | klass = GTK_IM_CONTEXT_GET_CLASS (context); |
461 | 485 | if (klass->set_client_window) |
462 | 486 | klass->set_client_window (context, window); |
| 487 | |
| 488 | priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); |
| 489 | |
| 490 | if (priv->clear_area_signal_id) |
| 491 | { |
| 492 | g_signal_handler_disconnect (context, priv->clear_area_signal_id); |
| 493 | priv->clear_area_signal_id = 0; |
| 494 | } |
| 495 | |
| 496 | if (window) |
| 497 | { |
| 498 | gpointer window_data; |
| 499 | |
| 500 | gdk_window_get_user_data (window, &window_data); |
| 501 | |
| 502 | if (GTK_IS_WIDGET (window_data)) |
| 503 | priv->clear_area_signal_id = g_signal_connect (context, "clear-area", |
| 504 | G_CALLBACK (_gtk_im_context_clear_area), |
| 505 | window_data); |
| 506 | } |
463 | 507 | } |
464 | 508 | |
465 | 509 | /** |
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 * |
102 | 102 | gint n_chars, |
103 | 103 | GtkIMMulticontext *multicontext); |
104 | 104 | |
| 105 | static void gtk_im_multicontext_clear_area_cb (GtkIMContext *slave, |
| 106 | GdkRectangle *osk_rect, |
| 107 | GdkRectangle *cursor_rect, |
| 108 | GtkIMMulticontext *multicontext); |
| 109 | |
105 | 110 | static void propagate_purpose (GtkIMMulticontext *context); |
106 | 111 | |
107 | 112 | static const gchar *global_context_id = NULL; |
… |
… |
gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, |
197 | 202 | g_signal_handlers_disconnect_by_func (priv->slave, |
198 | 203 | gtk_im_multicontext_commit_cb, |
199 | 204 | multicontext); |
| 205 | g_signal_handlers_disconnect_by_func (priv->slave, |
| 206 | gtk_im_multicontext_clear_area_cb, |
| 207 | multicontext); |
200 | 208 | |
201 | 209 | g_object_unref (priv->slave); |
202 | 210 | priv->slave = NULL; |
… |
… |
gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, |
231 | 239 | g_signal_connect (priv->slave, "delete-surrounding", |
232 | 240 | G_CALLBACK (gtk_im_multicontext_delete_surrounding_cb), |
233 | 241 | multicontext); |
| 242 | g_signal_connect (priv->slave, "clear-area", |
| 243 | G_CALLBACK (gtk_im_multicontext_clear_area_cb), |
| 244 | multicontext); |
234 | 245 | |
235 | 246 | if (!priv->use_preedit) /* Default is TRUE */ |
236 | 247 | gtk_im_context_set_use_preedit (slave, FALSE); |
… |
… |
gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave, |
553 | 564 | } |
554 | 565 | |
555 | 566 | static void |
| 567 | gtk_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 | |
| 575 | static void |
556 | 576 | activate_cb (GtkWidget *menuitem, |
557 | 577 | GtkIMMulticontext *context) |
558 | 578 | { |
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index a18c4cf..3595456 100644
a
|
b
|
struct _GtkScrolledWindowPrivate |
175 | 175 | |
176 | 176 | gdouble unclamped_hadj_value; |
177 | 177 | gdouble unclamped_vadj_value; |
| 178 | gdouble clear_area_dy; |
178 | 179 | }; |
179 | 180 | |
180 | 181 | typedef struct |
… |
… |
static gboolean _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindo |
287 | 288 | gboolean allow_overshooting, |
288 | 289 | gboolean snap_to_border); |
289 | 290 | |
| 291 | static gboolean gtk_scrolled_window_request_clear_area (GtkWidget *widget, |
| 292 | cairo_rectangle_int_t *clear_area, |
| 293 | cairo_rectangle_int_t *cursor_area, |
| 294 | gpointer user_data); |
| 295 | static gboolean gtk_scrolled_window_unset_clear_area (GtkWidget *widget, |
| 296 | gboolean snap_back, |
| 297 | gpointer user_data); |
| 298 | |
290 | 299 | static guint signals[LAST_SIGNAL] = {0}; |
291 | 300 | |
292 | 301 | G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN) |
… |
… |
gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) |
599 | 608 | gtk_scrolled_window_update_real_placement (scrolled_window); |
600 | 609 | priv->min_content_width = -1; |
601 | 610 | priv->min_content_height = -1; |
| 611 | priv->clear_area_dy = 0; |
602 | 612 | |
603 | 613 | gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE); |
604 | 614 | 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); |
605 | 622 | } |
606 | 623 | |
607 | 624 | /** |
… |
… |
_gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, |
2363 | 2380 | if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar))) |
2364 | 2381 | prev_value = &priv->unclamped_hadj_value; |
2365 | 2382 | else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar))) |
2366 | | prev_value = &priv->unclamped_vadj_value; |
| 2383 | { |
| 2384 | if (!snap_to_border) |
| 2385 | upper += priv->clear_area_dy; |
| 2386 | prev_value = &priv->unclamped_vadj_value; |
| 2387 | } |
2367 | 2388 | else |
2368 | 2389 | return FALSE; |
2369 | 2390 | |
… |
… |
gtk_scrolled_window_grab_notify (GtkWidget *widget, |
3494 | 3515 | } |
3495 | 3516 | } |
3496 | 3517 | |
| 3518 | static gboolean |
| 3519 | gtk_scrolled_window_request_clear_area (GtkWidget *widget, |
| 3520 | cairo_rectangle_int_t *cursor_area, |
| 3521 | cairo_rectangle_int_t *clear_area, |
| 3522 | gpointer user_data) |
| 3523 | { |
| 3524 | GtkScrolledWindowPrivate *priv; |
| 3525 | GtkAdjustment *adjustment; |
| 3526 | gdouble value; |
| 3527 | |
| 3528 | priv = GTK_SCROLLED_WINDOW (widget)->priv; |
| 3529 | adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)); |
| 3530 | value = priv->unclamped_vadj_value; |
| 3531 | |
| 3532 | priv->clear_area_dy = cursor_area->y + cursor_area->height - clear_area->y; |
| 3533 | value = priv->unclamped_vadj_value + priv->clear_area_dy; |
| 3534 | _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), |
| 3535 | adjustment, value, |
| 3536 | FALSE, FALSE); |
| 3537 | |
| 3538 | return TRUE; |
| 3539 | } |
| 3540 | |
| 3541 | static gboolean |
| 3542 | gtk_scrolled_window_unset_clear_area (GtkWidget *widget, |
| 3543 | gboolean snap_back, |
| 3544 | gpointer user_data) |
| 3545 | { |
| 3546 | GtkScrolledWindowPrivate *priv; |
| 3547 | |
| 3548 | priv = GTK_SCROLLED_WINDOW (widget)->priv; |
| 3549 | |
| 3550 | if (priv->clear_area_dy != 0) |
| 3551 | { |
| 3552 | if (snap_back) |
| 3553 | { |
| 3554 | GtkAdjustment *adjustment; |
| 3555 | gdouble value; |
| 3556 | |
| 3557 | adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)); |
| 3558 | value = priv->unclamped_vadj_value - priv->clear_area_dy; |
| 3559 | _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), |
| 3560 | adjustment, value, |
| 3561 | FALSE, FALSE); |
| 3562 | } |
| 3563 | |
| 3564 | priv->clear_area_dy = 0; |
| 3565 | return TRUE; |
| 3566 | } |
| 3567 | |
| 3568 | return FALSE; |
| 3569 | } |
| 3570 | |
3497 | 3571 | /** |
3498 | 3572 | * gtk_scrolled_window_get_min_content_width: |
3499 | 3573 | * @scrolled_window: a #GtkScrolledWindow |
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 58ad57a..9c480a1 100644
a
|
b
|
enum { |
484 | 484 | DRAG_FAILED, |
485 | 485 | STYLE_UPDATED, |
486 | 486 | TOUCH_EVENT, |
| 487 | REQUEST_CLEAR_AREA, |
| 488 | UNSET_CLEAR_AREA, |
487 | 489 | LAST_SIGNAL |
488 | 490 | }; |
489 | 491 | |
… |
… |
gtk_widget_class_init (GtkWidgetClass *klass) |
3118 | 3120 | _gtk_marshal_BOOLEAN__UINT, |
3119 | 3121 | G_TYPE_BOOLEAN, 1, G_TYPE_UINT); |
3120 | 3122 | |
| 3123 | widget_signals[REQUEST_CLEAR_AREA] = |
| 3124 | g_signal_new (I_("request-clear-area"), |
| 3125 | G_TYPE_FROM_CLASS (klass), |
| 3126 | G_SIGNAL_RUN_LAST, 0, |
| 3127 | g_signal_accumulator_true_handled, NULL, |
| 3128 | _gtk_marshal_BOOLEAN__BOXED_BOXED, |
| 3129 | G_TYPE_BOOLEAN, 2, |
| 3130 | CAIRO_GOBJECT_TYPE_RECTANGLE_INT, |
| 3131 | CAIRO_GOBJECT_TYPE_RECTANGLE_INT); |
| 3132 | widget_signals[UNSET_CLEAR_AREA] = |
| 3133 | g_signal_new (I_("unset-clear-area"), |
| 3134 | G_TYPE_FROM_CLASS (klass), |
| 3135 | G_SIGNAL_RUN_LAST, 0, |
| 3136 | g_signal_accumulator_true_handled, NULL, |
| 3137 | _gtk_marshal_BOOLEAN__BOOLEAN, |
| 3138 | G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); |
| 3139 | |
3121 | 3140 | binding_set = gtk_binding_set_by_class (klass); |
3122 | 3141 | gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK, |
3123 | 3142 | "popup-menu", 0); |
… |
… |
gtk_widget_insert_action_group (GtkWidget *widget, |
14137 | 14156 | else |
14138 | 14157 | g_action_muxer_remove (muxer, name); |
14139 | 14158 | } |
| 14159 | |
| 14160 | gboolean |
| 14161 | gtk_widget_request_clear_area (GtkWidget *widget, |
| 14162 | cairo_rectangle_int_t *clear_area, |
| 14163 | cairo_rectangle_int_t *cursor_position) |
| 14164 | { |
| 14165 | gboolean handled = FALSE; |
| 14166 | GtkWidget *cur; |
| 14167 | |
| 14168 | g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); |
| 14169 | g_return_val_if_fail (cursor_position != NULL, FALSE); |
| 14170 | g_return_val_if_fail (clear_area != NULL, FALSE); |
| 14171 | |
| 14172 | if (cursor_position->x < clear_area->x - cursor_position->width || |
| 14173 | cursor_position->x >= clear_area->x + clear_area->width || |
| 14174 | cursor_position->y < clear_area->y - cursor_position->height || |
| 14175 | cursor_position->y >= clear_area->y + clear_area->height) |
| 14176 | return FALSE; |
| 14177 | |
| 14178 | cur = widget; |
| 14179 | |
| 14180 | while (!handled && cur) |
| 14181 | { |
| 14182 | g_signal_emit (cur, widget_signals[REQUEST_CLEAR_AREA], 0, |
| 14183 | clear_area, cursor_position, &handled); |
| 14184 | |
| 14185 | if (!handled) |
| 14186 | cur = gtk_widget_get_parent (cur); |
| 14187 | } |
| 14188 | |
| 14189 | return handled; |
| 14190 | } |
| 14191 | |
| 14192 | gboolean |
| 14193 | gtk_widget_unset_clear_area (GtkWidget *widget, |
| 14194 | gboolean snap_back) |
| 14195 | { |
| 14196 | gboolean handled = FALSE; |
| 14197 | GtkWidget *cur; |
| 14198 | |
| 14199 | cur = widget; |
| 14200 | |
| 14201 | while (!handled && cur) |
| 14202 | { |
| 14203 | g_signal_emit (cur, widget_signals[UNSET_CLEAR_AREA], 0, |
| 14204 | snap_back, &handled); |
| 14205 | |
| 14206 | if (!handled) |
| 14207 | cur = gtk_widget_get_parent (cur); |
| 14208 | } |
| 14209 | |
| 14210 | return handled; |
| 14211 | } |
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index c178478..ce4f4dc 100644
a
|
b
|
GDK_AVAILABLE_IN_3_4 |
886 | 886 | GdkModifierType gtk_widget_get_modifier_mask (GtkWidget *widget, |
887 | 887 | GdkModifierIntent intent); |
888 | 888 | |
| 889 | gboolean gtk_widget_request_clear_area (GtkWidget *widget, |
| 890 | cairo_rectangle_int_t *clear_area, |
| 891 | cairo_rectangle_int_t *cursor_position); |
| 892 | gboolean gtk_widget_unset_clear_area (GtkWidget *widget, |
| 893 | gboolean snap_back); |
| 894 | |
889 | 895 | GDK_AVAILABLE_IN_3_6 |
890 | 896 | void gtk_widget_insert_action_group (GtkWidget *widget, |
891 | 897 | const gchar *name, |