Ticket #4134: 0001-OSK-im-osk-position.2.patch
File 0001-OSK-im-osk-position.2.patch, 19.8 KB (added by garnacho, 11 years ago) |
---|
-
gtk/gtkimcontext.c
From 87ca87d690503eed71f7086de397c36756b4ec97 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 | 171 +++++++++++++++++++++++++++++++++++++++++++++++- gtk/gtkimmulticontext.c | 20 ++++++ gtk/gtkscrolledwindow.c | 82 ++++++++++++++++++++++- gtk/gtkwidget.c | 72 ++++++++++++++++++++ gtk/gtkwidget.h | 6 ++ 5 files changed, 346 insertions(+), 5 deletions(-) diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c index f0f351f..c9d02f1 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 GtkWidget *widget; 126 127 cairo_rectangle_int_t clear_area; 128 cairo_rectangle_int_t cursor_rect; 129 cairo_rectangle_int_t last_notified_clear_area; 130 guint clear_area_signal_id; 131 guint clear_area_idle_id; 132 guint focused : 1; 133 guint need_position_update : 1; 124 134 }; 125 135 126 136 static void gtk_im_context_real_get_preedit_string (GtkIMContext *context, … … static void gtk_im_context_set_property (GObject *obj, 145 155 guint property_id, 146 156 const GValue *value, 147 157 GParamSpec *pspec); 158 static void gtk_im_context_finalize (GObject *obj); 148 159 149 160 150 161 G_DEFINE_ABSTRACT_TYPE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT) … … gtk_im_context_class_init (GtkIMContextClass *klass) 213 224 214 225 object_class->get_property = gtk_im_context_get_property; 215 226 object_class->set_property = gtk_im_context_set_property; 227 object_class->finalize = gtk_im_context_finalize; 216 228 217 229 klass->get_preedit_string = gtk_im_context_real_get_preedit_string; 218 230 klass->filter_keypress = gtk_im_context_real_filter_keypress; … … gtk_im_context_class_init (GtkIMContextClass *klass) 327 339 G_TYPE_INT, 328 340 G_TYPE_INT); 329 341 342 im_context_signals[CLEAR_AREA] = 343 g_signal_new (I_("clear-area"), 344 G_TYPE_FROM_CLASS (klass), 345 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 346 0, NULL, NULL, 347 _gtk_marshal_VOID__BOXED_BOXED, 348 G_TYPE_NONE, 2, 349 GDK_TYPE_RECTANGLE, GDK_TYPE_RECTANGLE); 350 330 351 properties[PROP_INPUT_PURPOSE] = 331 352 g_param_spec_enum ("input-purpose", 332 353 P_("Purpose"), … … gtk_im_context_real_get_surrounding (GtkIMContext *context, 438 459 return result; 439 460 } 440 461 462 static gboolean 463 _gtk_im_context_clear_area_idle (gpointer user_data) 464 { 465 GtkIMContext *context = user_data; 466 GtkIMContextPrivate *priv; 467 468 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 469 GtkIMContextPrivate); 470 471 if (priv->need_position_update && 472 (priv->clear_area.x != priv->last_notified_clear_area.x || 473 priv->clear_area.y != priv->last_notified_clear_area.y || 474 priv->clear_area.width != priv->last_notified_clear_area.width || 475 priv->clear_area.height != priv->last_notified_clear_area.height)) 476 { 477 if (priv->clear_area.width != 0 && priv->clear_area.height != 0) 478 { 479 cairo_rectangle_int_t rect; 480 GtkAllocation allocation; 481 482 rect = priv->cursor_rect; 483 484 gtk_widget_get_allocation (priv->widget, &allocation); 485 rect.x += allocation.x; 486 rect.y += allocation.y; 487 gdk_window_get_root_coords (gtk_widget_get_window (priv->widget), 488 rect.x, rect.y, &rect.x, &rect.y); 489 490 gtk_widget_request_clear_area (priv->widget, &priv->clear_area, &rect); 491 } 492 else 493 gtk_widget_unset_clear_area (priv->widget, TRUE); 494 495 priv->last_notified_clear_area = priv->clear_area; 496 } 497 498 priv->need_position_update = FALSE; 499 priv->clear_area_idle_id = 0; 500 return FALSE; 501 } 502 503 static void 504 _gtk_im_context_check_clear_area (GtkIMContext *context) 505 { 506 GtkIMContextPrivate *priv; 507 508 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 509 GtkIMContextPrivate); 510 511 if (priv->clear_area_idle_id) 512 g_source_remove (priv->clear_area_idle_id); 513 514 priv->clear_area_idle_id = 515 g_idle_add (_gtk_im_context_clear_area_idle, context); 516 } 517 518 static void 519 _gtk_im_context_clear_area (GtkIMContext *context, 520 cairo_rectangle_int_t *clear_area, 521 cairo_rectangle_int_t *cursor_rect, 522 GtkWidget *widget) 523 { 524 GtkIMContextPrivate *priv; 525 526 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 527 528 if (priv->clear_area.x != clear_area->x || 529 priv->clear_area.y != clear_area->y || 530 priv->clear_area.width != clear_area->width || 531 priv->clear_area.height != clear_area->height) 532 priv->need_position_update = TRUE; 533 534 priv->clear_area = *clear_area; 535 } 536 441 537 /** 442 538 * gtk_im_context_set_client_window: 443 539 * @context: a #GtkIMContext … … gtk_im_context_set_client_window (GtkIMContext *context, 454 550 GdkWindow *window) 455 551 { 456 552 GtkIMContextClass *klass; 457 553 GtkIMContextPrivate *priv; 554 458 555 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 459 556 460 557 klass = GTK_IM_CONTEXT_GET_CLASS (context); 461 558 if (klass->set_client_window) 462 559 klass->set_client_window (context, window); 560 561 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 562 563 if (priv->clear_area_signal_id) 564 { 565 g_signal_handler_disconnect (context, priv->clear_area_signal_id); 566 priv->clear_area_signal_id = 0; 567 } 568 569 if (window) 570 { 571 gpointer window_data; 572 573 gdk_window_get_user_data (window, &window_data); 574 575 if (GTK_IS_WIDGET (window_data)) 576 { 577 priv->clear_area_signal_id = g_signal_connect (context, "clear-area", 578 G_CALLBACK (_gtk_im_context_clear_area), 579 window_data); 580 priv->widget = window_data; 581 } 582 } 463 583 } 464 584 465 585 /** … … void 531 651 gtk_im_context_focus_in (GtkIMContext *context) 532 652 { 533 653 GtkIMContextClass *klass; 534 654 GtkIMContextPrivate *priv; 655 535 656 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 536 657 537 658 klass = GTK_IM_CONTEXT_GET_CLASS (context); 538 659 if (klass->focus_in) 539 660 klass->focus_in (context); 661 662 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 663 priv->focused = TRUE; 664 _gtk_im_context_check_clear_area (context); 540 665 } 541 666 542 667 /** … … void 552 677 gtk_im_context_focus_out (GtkIMContext *context) 553 678 { 554 679 GtkIMContextClass *klass; 555 680 GtkIMContextPrivate *priv; 681 556 682 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 557 683 558 684 klass = GTK_IM_CONTEXT_GET_CLASS (context); 559 685 if (klass->focus_out) 560 686 klass->focus_out (context); 687 688 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 689 690 if (priv->focused) 691 gtk_widget_unset_clear_area (priv->widget, TRUE); 692 693 _gtk_im_context_check_clear_area (context); 694 priv->focused = FALSE; 561 695 } 562 696 563 697 /** … … gtk_im_context_reset (GtkIMContext *context) 575 709 576 710 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 577 711 712 _gtk_im_context_check_clear_area (context); 713 578 714 klass = GTK_IM_CONTEXT_GET_CLASS (context); 579 715 if (klass->reset) 580 716 klass->reset (context); … … gtk_im_context_set_cursor_location (GtkIMContext *context, 595 731 const GdkRectangle *area) 596 732 { 597 733 GtkIMContextClass *klass; 734 GtkIMContextPrivate *priv; 598 735 599 736 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 600 737 738 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 739 GtkIMContextPrivate); 740 741 if (priv->cursor_rect.x != area->x || 742 priv->cursor_rect.y != area->y || 743 priv->cursor_rect.width != area->width || 744 priv->cursor_rect.height != area->height) 745 { 746 priv->cursor_rect = *area; 747 priv->need_position_update = TRUE; 748 } 749 601 750 klass = GTK_IM_CONTEXT_GET_CLASS (context); 602 751 if (klass->set_cursor_location) 603 752 klass->set_cursor_location (context, (GdkRectangle *) area); 753 754 _gtk_im_context_check_clear_area (context); 604 755 } 605 756 606 757 /** … … gtk_im_context_set_property (GObject *obj, 798 949 break; 799 950 } 800 951 } 952 953 static void 954 gtk_im_context_finalize (GObject *obj) 955 { 956 GtkIMContextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 957 958 if (priv->clear_area_signal_id) 959 g_signal_handler_disconnect (obj, priv->clear_area_signal_id); 960 961 if (priv->clear_area_idle_id) 962 g_source_remove (priv->clear_area_idle_id); 963 964 G_OBJECT_CLASS (gtk_im_context_parent_class)->finalize (obj); 965 } -
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 * 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 { -
gtk/gtkscrolledwindow.c
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c index 08a286c..82d052f 100644
a b struct _GtkScrolledWindowPrivate 176 176 177 177 gdouble unclamped_hadj_value; 178 178 gdouble unclamped_vadj_value; 179 gdouble clear_area_dy; 179 180 }; 180 181 181 182 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) 597 606 gtk_scrolled_window_update_real_placement (scrolled_window); 598 607 priv->min_content_width = -1; 599 608 priv->min_content_height = -1; 609 priv->clear_area_dy = 0; 600 610 601 611 gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE); 602 612 gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE); 613 614 g_signal_connect (scrolled_window, "request-clear-area", 615 G_CALLBACK (gtk_scrolled_window_request_clear_area), 616 NULL); 617 g_signal_connect (scrolled_window, "unset-clear-area", 618 G_CALLBACK (gtk_scrolled_window_unset_clear_area), 619 NULL); 603 620 } 604 621 605 622 /** … … gtk_scrolled_window_size_allocate (GtkWidget *widget, 2249 2266 gtk_widget_hide (priv->vscrollbar); 2250 2267 2251 2268 _gtk_scrolled_window_allocate_overshoot_window (scrolled_window); 2269 _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), 2270 gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)), 2271 priv->unclamped_vadj_value, 2272 FALSE, FALSE); 2252 2273 } 2253 2274 2254 2275 static gboolean … … _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, 2361 2382 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar))) 2362 2383 prev_value = &priv->unclamped_hadj_value; 2363 2384 else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar))) 2364 prev_value = &priv->unclamped_vadj_value; 2385 { 2386 upper += priv->clear_area_dy; 2387 prev_value = &priv->unclamped_vadj_value; 2388 } 2365 2389 else 2366 2390 return FALSE; 2367 2391 … … _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window, 2379 2403 upper += MAX_OVERSHOOT_DISTANCE; 2380 2404 } 2381 2405 2382 *prev_value = CLAMP (value, lower, upper);2383 2406 gtk_adjustment_set_value (adjustment, value); 2407 *prev_value = CLAMP (value, lower, upper); 2384 2408 2385 2409 return (*prev_value != value); 2386 2410 } … … gtk_scrolled_window_grab_notify (GtkWidget *widget, 3500 3524 } 3501 3525 } 3502 3526 3527 static gboolean 3528 gtk_scrolled_window_request_clear_area (GtkWidget *widget, 3529 cairo_rectangle_int_t *clear_area, 3530 cairo_rectangle_int_t *cursor_area, 3531 gpointer user_data) 3532 { 3533 GtkScrolledWindowPrivate *priv; 3534 GtkAdjustment *adjustment; 3535 3536 priv = GTK_SCROLLED_WINDOW (widget)->priv; 3537 adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)); 3538 3539 priv->unclamped_vadj_value -= priv->clear_area_dy; 3540 priv->clear_area_dy = cursor_area->y + cursor_area->height - clear_area->y; 3541 priv->unclamped_vadj_value += priv->clear_area_dy; 3542 _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), 3543 adjustment, priv->unclamped_vadj_value, 3544 FALSE, FALSE); 3545 gtk_widget_queue_resize (widget); 3546 3547 return TRUE; 3548 } 3549 3550 static gboolean 3551 gtk_scrolled_window_unset_clear_area (GtkWidget *widget, 3552 gboolean snap_back, 3553 gpointer user_data) 3554 { 3555 GtkScrolledWindowPrivate *priv; 3556 3557 priv = GTK_SCROLLED_WINDOW (widget)->priv; 3558 3559 if (priv->clear_area_dy != 0) 3560 { 3561 priv->unclamped_vadj_value -= priv->clear_area_dy; 3562 priv->clear_area_dy = 0; 3563 3564 if (snap_back) 3565 { 3566 GtkAdjustment *adjustment; 3567 3568 adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)); 3569 _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), 3570 adjustment, priv->unclamped_vadj_value, 3571 FALSE, FALSE); 3572 gtk_widget_queue_resize (widget); 3573 } 3574 3575 return TRUE; 3576 } 3577 3578 return FALSE; 3579 } 3580 3503 3581 /** 3504 3582 * gtk_scrolled_window_get_min_content_width: 3505 3583 * @scrolled_window: a #GtkScrolledWindow -
gtk/gtkwidget.c
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index eb82eb8..f62cc66 100644
a b enum { 482 482 DRAG_FAILED, 483 483 STYLE_UPDATED, 484 484 TOUCH_EVENT, 485 REQUEST_CLEAR_AREA, 486 UNSET_CLEAR_AREA, 485 487 LAST_SIGNAL 486 488 }; 487 489 … … gtk_widget_class_init (GtkWidgetClass *klass) 3116 3118 _gtk_marshal_BOOLEAN__UINT, 3117 3119 G_TYPE_BOOLEAN, 1, G_TYPE_UINT); 3118 3120 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 3119 3138 binding_set = gtk_binding_set_by_class (klass); 3120 3139 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK, 3121 3140 "popup-menu", 0); … … gtk_widget_insert_action_group (GtkWidget *widget, 14144 14163 else 14145 14164 g_action_muxer_remove (muxer, name); 14146 14165 } 14166 14167 gboolean 14168 gtk_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 (cursor_position->x <= clear_area->x - cursor_position->width || 14180 cursor_position->x >= clear_area->x + clear_area->width || 14181 cursor_position->y <= clear_area->y - cursor_position->height || 14182 cursor_position->y >= clear_area->y + clear_area->height) 14183 return FALSE; 14184 14185 cur = widget; 14186 14187 while (!handled && cur) 14188 { 14189 g_signal_emit (cur, widget_signals[REQUEST_CLEAR_AREA], 0, 14190 clear_area, cursor_position, &handled); 14191 14192 if (!handled) 14193 cur = gtk_widget_get_parent (cur); 14194 } 14195 14196 return handled; 14197 } 14198 14199 gboolean 14200 gtk_widget_unset_clear_area (GtkWidget *widget, 14201 gboolean snap_back) 14202 { 14203 gboolean handled = FALSE; 14204 GtkWidget *cur; 14205 14206 cur = widget; 14207 14208 while (!handled && cur) 14209 { 14210 g_signal_emit (cur, widget_signals[UNSET_CLEAR_AREA], 0, 14211 snap_back, &handled); 14212 14213 if (!handled) 14214 cur = gtk_widget_get_parent (cur); 14215 } 14216 14217 return handled; 14218 } -
gtk/gtkwidget.h
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 2cdc7f3..4db2c99 100644
a b GDK_AVAILABLE_IN_3_4 887 887 GdkModifierType gtk_widget_get_modifier_mask (GtkWidget *widget, 888 888 GdkModifierIntent intent); 889 889 890 gboolean gtk_widget_request_clear_area (GtkWidget *widget, 891 cairo_rectangle_int_t *clear_area, 892 cairo_rectangle_int_t *cursor_position); 893 gboolean gtk_widget_unset_clear_area (GtkWidget *widget, 894 gboolean snap_back); 895 890 896 GDK_AVAILABLE_IN_3_6 891 897 void gtk_widget_insert_action_group (GtkWidget *widget, 892 898 const gchar *name,