Ticket #4134: 0001-OSK-im-osk-position.patch
File 0001-OSK-im-osk-position.patch, 19.4 KB (added by garnacho, 11 years ago) |
---|
-
gtk/gtkimcontext.c
From 35180444a6b63e4e42a50fc0dbff99dd5262fafa Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlos@lanedo.com> Date: Wed, 19 Sep 2012 15:37:01 +0200 Subject: [PATCH 1/2] 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 | 81 ++++++++++++++++++++++- gtk/gtkwidget.c | 72 ++++++++++++++++++++ gtk/gtkwidget.h | 6 ++ 5 files changed, 345 insertions(+), 5 deletions(-) diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c index f0f351f..12023ba 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 guint clear_area_signal_id; 130 guint clear_area_idle_id; 131 guint focused : 1; 132 guint need_position_update : 1; 124 133 }; 125 134 126 135 static void gtk_im_context_real_get_preedit_string (GtkIMContext *context, … … static void gtk_im_context_set_property (GObject *obj, 145 154 guint property_id, 146 155 const GValue *value, 147 156 GParamSpec *pspec); 157 static void gtk_im_context_finalize (GObject *obj); 148 158 149 159 150 160 G_DEFINE_ABSTRACT_TYPE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT) … … gtk_im_context_class_init (GtkIMContextClass *klass) 213 223 214 224 object_class->get_property = gtk_im_context_get_property; 215 225 object_class->set_property = gtk_im_context_set_property; 226 object_class->finalize = gtk_im_context_finalize; 216 227 217 228 klass->get_preedit_string = gtk_im_context_real_get_preedit_string; 218 229 klass->filter_keypress = gtk_im_context_real_filter_keypress; … … gtk_im_context_class_init (GtkIMContextClass *klass) 327 338 G_TYPE_INT, 328 339 G_TYPE_INT); 329 340 341 im_context_signals[CLEAR_AREA] = 342 g_signal_new (I_("clear-area"), 343 G_TYPE_FROM_CLASS (klass), 344 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 345 0, NULL, NULL, 346 _gtk_marshal_VOID__BOXED_BOXED, 347 G_TYPE_NONE, 2, 348 GDK_TYPE_RECTANGLE, GDK_TYPE_RECTANGLE); 349 330 350 properties[PROP_INPUT_PURPOSE] = 331 351 g_param_spec_enum ("input-purpose", 332 352 P_("Purpose"), … … gtk_im_context_real_get_surrounding (GtkIMContext *context, 438 458 return result; 439 459 } 440 460 461 static gboolean 462 _gtk_im_context_clear_area_idle (gpointer user_data) 463 { 464 GtkIMContext *context = user_data; 465 GtkIMContextPrivate *priv; 466 467 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 468 GtkIMContextPrivate); 469 470 if (priv->need_position_update) 471 { 472 priv->need_position_update = FALSE; 473 gtk_widget_unset_clear_area (priv->widget, TRUE); 474 475 if (priv->clear_area.width != 0 && priv->clear_area.height != 0) 476 { 477 cairo_rectangle_int_t rect; 478 GtkAllocation allocation; 479 480 rect = priv->cursor_rect; 481 482 gtk_widget_get_allocation (priv->widget, &allocation); 483 rect.x += allocation.x; 484 rect.y += allocation.y; 485 gdk_window_get_root_coords (gtk_widget_get_window (priv->widget), 486 rect.x, rect.y, &rect.x, &rect.y); 487 488 gtk_widget_request_clear_area (priv->widget, &priv->clear_area, &rect); 489 } 490 } 491 492 priv->clear_area_idle_id = 0; 493 return FALSE; 494 } 495 496 static void 497 _gtk_im_context_check_clear_area (GtkIMContext *context) 498 { 499 GtkIMContextPrivate *priv; 500 501 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 502 GtkIMContextPrivate); 503 if (!priv->focused) 504 return; 505 506 if (priv->clear_area_idle_id) 507 g_source_remove (priv->clear_area_idle_id); 508 509 priv->clear_area_idle_id = 510 g_idle_add (_gtk_im_context_clear_area_idle, context); 511 } 512 513 static void 514 _gtk_im_context_clear_area (GtkIMContext *context, 515 cairo_rectangle_int_t *clear_area, 516 cairo_rectangle_int_t *cursor_rect, 517 GtkWidget *widget) 518 { 519 GtkIMContextPrivate *priv; 520 521 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 522 523 if (!priv->focused) 524 { 525 priv->need_position_update = TRUE; 526 return; 527 } 528 529 priv->clear_area = *clear_area; 530 531 if (priv->clear_area.x != clear_area->x || 532 priv->clear_area.y != clear_area->y || 533 priv->clear_area.width != clear_area->width || 534 priv->clear_area.height != clear_area->height) 535 { 536 priv->clear_area = *clear_area; 537 priv->need_position_update = TRUE; 538 } 539 } 540 441 541 /** 442 542 * gtk_im_context_set_client_window: 443 543 * @context: a #GtkIMContext … … gtk_im_context_set_client_window (GtkIMContext *context, 454 554 GdkWindow *window) 455 555 { 456 556 GtkIMContextClass *klass; 457 557 GtkIMContextPrivate *priv; 558 458 559 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 459 560 460 561 klass = GTK_IM_CONTEXT_GET_CLASS (context); 461 562 if (klass->set_client_window) 462 563 klass->set_client_window (context, window); 564 565 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 566 567 if (priv->clear_area_signal_id) 568 { 569 g_signal_handler_disconnect (context, priv->clear_area_signal_id); 570 priv->clear_area_signal_id = 0; 571 } 572 573 if (window) 574 { 575 gpointer window_data; 576 577 gdk_window_get_user_data (window, &window_data); 578 579 if (GTK_IS_WIDGET (window_data)) 580 { 581 priv->clear_area_signal_id = g_signal_connect (context, "clear-area", 582 G_CALLBACK (_gtk_im_context_clear_area), 583 window_data); 584 priv->widget = window_data; 585 } 586 } 463 587 } 464 588 465 589 /** … … void 531 655 gtk_im_context_focus_in (GtkIMContext *context) 532 656 { 533 657 GtkIMContextClass *klass; 534 658 GtkIMContextPrivate *priv; 659 535 660 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 536 661 537 662 klass = GTK_IM_CONTEXT_GET_CLASS (context); 538 663 if (klass->focus_in) 539 664 klass->focus_in (context); 665 666 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 667 priv->focused = TRUE; 540 668 } 541 669 542 670 /** … … void 552 680 gtk_im_context_focus_out (GtkIMContext *context) 553 681 { 554 682 GtkIMContextClass *klass; 555 683 GtkIMContextPrivate *priv; 684 556 685 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 557 686 558 687 klass = GTK_IM_CONTEXT_GET_CLASS (context); 559 688 if (klass->focus_out) 560 689 klass->focus_out (context); 690 691 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); 692 693 if (priv->focused) 694 gtk_widget_unset_clear_area (priv->widget, TRUE); 695 696 priv->focused = FALSE; 561 697 } 562 698 563 699 /** … … gtk_im_context_reset (GtkIMContext *context) 575 711 576 712 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 577 713 714 _gtk_im_context_check_clear_area (context); 715 578 716 klass = GTK_IM_CONTEXT_GET_CLASS (context); 579 717 if (klass->reset) 580 718 klass->reset (context); … … gtk_im_context_set_cursor_location (GtkIMContext *context, 595 733 const GdkRectangle *area) 596 734 { 597 735 GtkIMContextClass *klass; 736 GtkIMContextPrivate *priv; 598 737 599 738 g_return_if_fail (GTK_IS_IM_CONTEXT (context)); 600 739 740 priv = G_TYPE_INSTANCE_GET_PRIVATE (context, GTK_TYPE_IM_CONTEXT, 741 GtkIMContextPrivate); 742 743 if (priv->cursor_rect.x != area->x || 744 priv->cursor_rect.y != area->y || 745 priv->cursor_rect.width != area->width || 746 priv->cursor_rect.height != area->height) 747 { 748 priv->cursor_rect = *area; 749 priv->need_position_update = TRUE; 750 } 751 601 752 klass = GTK_IM_CONTEXT_GET_CLASS (context); 602 753 if (klass->set_cursor_location) 603 754 klass->set_cursor_location (context, (GdkRectangle *) area); … … 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..669fe04 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->clear_area_dy = cursor_area->y + cursor_area->height - clear_area->y; 3540 priv->unclamped_vadj_value += priv->clear_area_dy; 3541 _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), 3542 adjustment, priv->unclamped_vadj_value, 3543 FALSE, FALSE); 3544 gtk_widget_queue_resize (widget); 3545 3546 return TRUE; 3547 } 3548 3549 static gboolean 3550 gtk_scrolled_window_unset_clear_area (GtkWidget *widget, 3551 gboolean snap_back, 3552 gpointer user_data) 3553 { 3554 GtkScrolledWindowPrivate *priv; 3555 3556 priv = GTK_SCROLLED_WINDOW (widget)->priv; 3557 3558 if (priv->clear_area_dy != 0) 3559 { 3560 priv->unclamped_vadj_value -= priv->clear_area_dy; 3561 priv->clear_area_dy = 0; 3562 3563 if (snap_back) 3564 { 3565 GtkAdjustment *adjustment; 3566 3567 adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)); 3568 _gtk_scrolled_window_set_adjustment_value (GTK_SCROLLED_WINDOW (widget), 3569 adjustment, priv->unclamped_vadj_value, 3570 FALSE, FALSE); 3571 gtk_widget_queue_resize (widget); 3572 } 3573 3574 return TRUE; 3575 } 3576 3577 return FALSE; 3578 } 3579 3503 3580 /** 3504 3581 * gtk_scrolled_window_get_min_content_width: 3505 3582 * @scrolled_window: a #GtkScrolledWindow -
gtk/gtkwidget.c
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index eb82eb8..7fa093c 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,