OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" | 5 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 } | 153 } |
154 | 154 |
155 } // namespace | 155 } // namespace |
156 | 156 |
157 OmniboxViewGtk::OmniboxViewGtk(OmniboxEditController* controller, | 157 OmniboxViewGtk::OmniboxViewGtk(OmniboxEditController* controller, |
158 ToolbarModel* toolbar_model, | 158 ToolbarModel* toolbar_model, |
159 Browser* browser, | 159 Browser* browser, |
160 CommandUpdater* command_updater, | 160 CommandUpdater* command_updater, |
161 bool popup_window_mode, | 161 bool popup_window_mode, |
162 GtkWidget* location_bar) | 162 GtkWidget* location_bar) |
163 : browser_(browser), | 163 : OmniboxView(browser->profile(), controller, toolbar_model, |
| 164 command_updater), |
| 165 browser_(browser), |
164 text_view_(NULL), | 166 text_view_(NULL), |
165 tag_table_(NULL), | 167 tag_table_(NULL), |
166 text_buffer_(NULL), | 168 text_buffer_(NULL), |
167 faded_text_tag_(NULL), | 169 faded_text_tag_(NULL), |
168 secure_scheme_tag_(NULL), | 170 secure_scheme_tag_(NULL), |
169 security_error_scheme_tag_(NULL), | 171 security_error_scheme_tag_(NULL), |
170 normal_text_tag_(NULL), | 172 normal_text_tag_(NULL), |
171 instant_anchor_tag_(NULL), | 173 instant_anchor_tag_(NULL), |
172 instant_view_(NULL), | 174 instant_view_(NULL), |
173 instant_mark_(NULL), | 175 instant_mark_(NULL), |
174 model_(new OmniboxEditModel(this, controller, browser->profile())), | |
175 controller_(controller), | |
176 toolbar_model_(toolbar_model), | |
177 command_updater_(command_updater), | |
178 popup_window_mode_(popup_window_mode), | 176 popup_window_mode_(popup_window_mode), |
179 security_level_(ToolbarModel::NONE), | 177 security_level_(ToolbarModel::NONE), |
180 mark_set_handler_id_(0), | 178 mark_set_handler_id_(0), |
181 button_1_pressed_(false), | 179 button_1_pressed_(false), |
182 theme_service_(GtkThemeService::GetFrom(browser->profile())), | 180 theme_service_(GtkThemeService::GetFrom(browser->profile())), |
183 enter_was_pressed_(false), | 181 enter_was_pressed_(false), |
184 tab_was_pressed_(false), | 182 tab_was_pressed_(false), |
185 paste_clipboard_requested_(false), | 183 paste_clipboard_requested_(false), |
186 enter_was_inserted_(false), | 184 enter_was_inserted_(false), |
187 selection_suggested_(false), | 185 selection_suggested_(false), |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 void OmniboxViewGtk::SetFocus() { | 413 void OmniboxViewGtk::SetFocus() { |
416 DCHECK(text_view_); | 414 DCHECK(text_view_); |
417 gtk_widget_grab_focus(text_view_); | 415 gtk_widget_grab_focus(text_view_); |
418 } | 416 } |
419 | 417 |
420 int OmniboxViewGtk::WidthOfTextAfterCursor() { | 418 int OmniboxViewGtk::WidthOfTextAfterCursor() { |
421 // Not used. | 419 // Not used. |
422 return -1; | 420 return -1; |
423 } | 421 } |
424 | 422 |
425 OmniboxEditModel* OmniboxViewGtk::model() { | |
426 return model_.get(); | |
427 } | |
428 | |
429 const OmniboxEditModel* OmniboxViewGtk::model() const { | |
430 return model_.get(); | |
431 } | |
432 | |
433 void OmniboxViewGtk::SaveStateToTab(WebContents* tab) { | 423 void OmniboxViewGtk::SaveStateToTab(WebContents* tab) { |
434 DCHECK(tab); | 424 DCHECK(tab); |
435 // If any text has been selected, register it as the PRIMARY selection so it | 425 // If any text has been selected, register it as the PRIMARY selection so it |
436 // can still be pasted via middle-click after the text view is cleared. | 426 // can still be pasted via middle-click after the text view is cleared. |
437 if (!selected_text_.empty()) | 427 if (!selected_text_.empty()) |
438 SavePrimarySelection(selected_text_); | 428 SavePrimarySelection(selected_text_); |
439 // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. | 429 // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. |
440 OmniboxEditModel::State model_state = model_->GetStateForTabSwitch(); | 430 OmniboxEditModel::State model_state = model_->GetStateForTabSwitch(); |
441 GetStateAccessor()->SetProperty( | 431 GetStateAccessor()->SetProperty( |
442 tab->GetPropertyBag(), | 432 tab->GetPropertyBag(), |
(...skipping 25 matching lines...) Expand all Loading... |
468 FinishUpdatingHighlightedText(); | 458 FinishUpdatingHighlightedText(); |
469 } | 459 } |
470 } else if (visibly_changed_permanent_text) { | 460 } else if (visibly_changed_permanent_text) { |
471 RevertAll(); | 461 RevertAll(); |
472 // TODO(deanm): There should be code to restore select all here. | 462 // TODO(deanm): There should be code to restore select all here. |
473 } else if (changed_security_level) { | 463 } else if (changed_security_level) { |
474 EmphasizeURLComponents(); | 464 EmphasizeURLComponents(); |
475 } | 465 } |
476 } | 466 } |
477 | 467 |
478 void OmniboxViewGtk::OpenMatch(const AutocompleteMatch& match, | |
479 WindowOpenDisposition disposition, | |
480 const GURL& alternate_nav_url, | |
481 size_t selected_line) { | |
482 if (!match.destination_url.is_valid()) | |
483 return; | |
484 | |
485 model_->OpenMatch(match, disposition, alternate_nav_url, selected_line); | |
486 } | |
487 | |
488 string16 OmniboxViewGtk::GetText() const { | 468 string16 OmniboxViewGtk::GetText() const { |
489 GtkTextIter start, end; | 469 GtkTextIter start, end; |
490 GetTextBufferBounds(&start, &end); | 470 GetTextBufferBounds(&start, &end); |
491 gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false); | 471 gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false); |
492 string16 out(UTF8ToUTF16(utf8)); | 472 string16 out(UTF8ToUTF16(utf8)); |
493 g_free(utf8); | 473 g_free(utf8); |
494 | 474 |
495 if (supports_pre_edit_) { | 475 if (supports_pre_edit_) { |
496 // We need to treat the text currently being composed by the input method | 476 // We need to treat the text currently being composed by the input method |
497 // as part of the text content, so that omnibox can work correctly in the | 477 // as part of the text content, so that omnibox can work correctly in the |
498 // middle of composition. | 478 // middle of composition. |
499 if (pre_edit_.size()) { | 479 if (pre_edit_.size()) { |
500 GtkTextMark* mark = gtk_text_buffer_get_insert(text_buffer_); | 480 GtkTextMark* mark = gtk_text_buffer_get_insert(text_buffer_); |
501 gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark); | 481 gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark); |
502 out.insert(gtk_text_iter_get_offset(&start), pre_edit_); | 482 out.insert(gtk_text_iter_get_offset(&start), pre_edit_); |
503 } | 483 } |
504 } | 484 } |
505 return out; | 485 return out; |
506 } | 486 } |
507 | 487 |
508 bool OmniboxViewGtk::IsEditingOrEmpty() const { | |
509 return model_->user_input_in_progress() || (GetTextLength() == 0); | |
510 } | |
511 | |
512 int OmniboxViewGtk::GetIcon() const { | |
513 return IsEditingOrEmpty() ? | |
514 AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : | |
515 toolbar_model_->GetIcon(); | |
516 } | |
517 | |
518 void OmniboxViewGtk::SetUserText(const string16& text) { | |
519 SetUserText(text, text, true); | |
520 } | |
521 | |
522 void OmniboxViewGtk::SetUserText(const string16& text, | |
523 const string16& display_text, | |
524 bool update_popup) { | |
525 model_->SetUserText(text); | |
526 // TODO(deanm): something about selection / focus change here. | |
527 SetWindowTextAndCaretPos(display_text, display_text.length(), update_popup, | |
528 true); | |
529 } | |
530 | |
531 void OmniboxViewGtk::SetWindowTextAndCaretPos(const string16& text, | 488 void OmniboxViewGtk::SetWindowTextAndCaretPos(const string16& text, |
532 size_t caret_pos, | 489 size_t caret_pos, |
533 bool update_popup, | 490 bool update_popup, |
534 bool notify_text_changed) { | 491 bool notify_text_changed) { |
535 CharRange range(static_cast<int>(caret_pos), static_cast<int>(caret_pos)); | 492 CharRange range(static_cast<int>(caret_pos), static_cast<int>(caret_pos)); |
536 SetTextAndSelectedRange(text, range); | 493 SetTextAndSelectedRange(text, range); |
537 | 494 |
538 if (update_popup) | 495 if (update_popup) |
539 UpdatePopup(); | 496 UpdatePopup(); |
540 | 497 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 *end = static_cast<size_t>(selection.cp_max); | 534 *end = static_cast<size_t>(selection.cp_max); |
578 } | 535 } |
579 | 536 |
580 void OmniboxViewGtk::SelectAll(bool reversed) { | 537 void OmniboxViewGtk::SelectAll(bool reversed) { |
581 // SelectAll() is invoked as a side effect of other actions (e.g. switching | 538 // SelectAll() is invoked as a side effect of other actions (e.g. switching |
582 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the | 539 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the |
583 // PRIMARY selection here. | 540 // PRIMARY selection here. |
584 SelectAllInternal(reversed, false); | 541 SelectAllInternal(reversed, false); |
585 } | 542 } |
586 | 543 |
587 void OmniboxViewGtk::RevertAll() { | |
588 ClosePopup(); | |
589 model_->Revert(); | |
590 TextChanged(); | |
591 } | |
592 | |
593 void OmniboxViewGtk::UpdatePopup() { | 544 void OmniboxViewGtk::UpdatePopup() { |
594 model_->SetInputInProgress(true); | 545 model_->SetInputInProgress(true); |
595 if (!update_popup_without_focus_ && !model_->has_focus()) | 546 if (!update_popup_without_focus_ && !model_->has_focus()) |
596 return; | 547 return; |
597 | 548 |
598 // Don't inline autocomplete when the caret/selection isn't at the end of | 549 // Don't inline autocomplete when the caret/selection isn't at the end of |
599 // the text, or in the middle of composition. | 550 // the text, or in the middle of composition. |
600 CharRange sel = GetSelection(); | 551 CharRange sel = GetSelection(); |
601 bool no_inline_autocomplete = | 552 bool no_inline_autocomplete = |
602 std::max(sel.cp_max, sel.cp_min) < GetTextLength() || IsImeComposing(); | 553 std::max(sel.cp_max, sel.cp_min) < GetOmniboxTextLength() || |
| 554 IsImeComposing(); |
603 model_->StartAutocomplete(sel.cp_min != sel.cp_max, no_inline_autocomplete); | 555 model_->StartAutocomplete(sel.cp_min != sel.cp_max, no_inline_autocomplete); |
604 } | 556 } |
605 | 557 |
606 void OmniboxViewGtk::ClosePopup() { | |
607 model_->StopAutocomplete(); | |
608 } | |
609 | |
610 void OmniboxViewGtk::OnTemporaryTextMaybeChanged( | 558 void OmniboxViewGtk::OnTemporaryTextMaybeChanged( |
611 const string16& display_text, | 559 const string16& display_text, |
612 bool save_original_selection) { | 560 bool save_original_selection) { |
613 if (save_original_selection) | 561 if (save_original_selection) |
614 saved_temporary_selection_ = GetSelection(); | 562 saved_temporary_selection_ = GetSelection(); |
615 | 563 |
616 StartUpdatingHighlightedText(); | 564 StartUpdatingHighlightedText(); |
617 SetWindowTextAndCaretPos(display_text, display_text.length(), false, false); | 565 SetWindowTextAndCaretPos(display_text, display_text.length(), false, false); |
618 FinishUpdatingHighlightedText(); | 566 FinishUpdatingHighlightedText(); |
619 TextChanged(); | 567 TextChanged(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 // {Start|Finish}UpdatingHighlightedText() are called here to prevent the | 623 // {Start|Finish}UpdatingHighlightedText() are called here to prevent the |
676 // PRIMARY selection from being changed. | 624 // PRIMARY selection from being changed. |
677 if (enter_was_pressed_ && enter_was_inserted_) { | 625 if (enter_was_pressed_ && enter_was_inserted_) { |
678 StartUpdatingHighlightedText(); | 626 StartUpdatingHighlightedText(); |
679 SetTextAndSelectedRange(text_before_change_, sel_before_change_); | 627 SetTextAndSelectedRange(text_before_change_, sel_before_change_); |
680 FinishUpdatingHighlightedText(); | 628 FinishUpdatingHighlightedText(); |
681 return false; | 629 return false; |
682 } | 630 } |
683 | 631 |
684 const CharRange new_sel = GetSelection(); | 632 const CharRange new_sel = GetSelection(); |
685 const int length = GetTextLength(); | 633 const int length = GetOmniboxTextLength(); |
686 const bool selection_differs = | 634 const bool selection_differs = |
687 ((new_sel.cp_min != new_sel.cp_max) || | 635 ((new_sel.cp_min != new_sel.cp_max) || |
688 (sel_before_change_.cp_min != sel_before_change_.cp_max)) && | 636 (sel_before_change_.cp_min != sel_before_change_.cp_max)) && |
689 ((new_sel.cp_min != sel_before_change_.cp_min) || | 637 ((new_sel.cp_min != sel_before_change_.cp_min) || |
690 (new_sel.cp_max != sel_before_change_.cp_max)); | 638 (new_sel.cp_max != sel_before_change_.cp_max)); |
691 const bool at_end_of_edit = | 639 const bool at_end_of_edit = |
692 (new_sel.cp_min == length && new_sel.cp_max == length); | 640 (new_sel.cp_min == length && new_sel.cp_max == length); |
693 | 641 |
694 // See if the text or selection have changed since OnBeforePossibleChange(). | 642 // See if the text or selection have changed since OnBeforePossibleChange(). |
695 const string16 new_text(GetText()); | 643 const string16 new_text(GetText()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 gfx::NativeView OmniboxViewGtk::GetNativeView() const { | 684 gfx::NativeView OmniboxViewGtk::GetNativeView() const { |
737 return alignment_.get(); | 685 return alignment_.get(); |
738 } | 686 } |
739 | 687 |
740 gfx::NativeView OmniboxViewGtk::GetRelativeWindowForPopup() const { | 688 gfx::NativeView OmniboxViewGtk::GetRelativeWindowForPopup() const { |
741 GtkWidget* toplevel = gtk_widget_get_toplevel(GetNativeView()); | 689 GtkWidget* toplevel = gtk_widget_get_toplevel(GetNativeView()); |
742 DCHECK(gtk_widget_is_toplevel(toplevel)); | 690 DCHECK(gtk_widget_is_toplevel(toplevel)); |
743 return toplevel; | 691 return toplevel; |
744 } | 692 } |
745 | 693 |
746 CommandUpdater* OmniboxViewGtk::GetCommandUpdater() { | |
747 return command_updater_; | |
748 } | |
749 | |
750 void OmniboxViewGtk::SetInstantSuggestion(const string16& suggestion, | 694 void OmniboxViewGtk::SetInstantSuggestion(const string16& suggestion, |
751 bool animate_to_complete) { | 695 bool animate_to_complete) { |
752 std::string suggestion_utf8 = UTF16ToUTF8(suggestion); | 696 std::string suggestion_utf8 = UTF16ToUTF8(suggestion); |
753 | 697 |
754 gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str()); | 698 gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str()); |
755 | 699 |
756 StopAnimation(); | 700 StopAnimation(); |
757 | 701 |
758 if (suggestion.empty()) { | 702 if (suggestion.empty()) { |
759 gtk_widget_hide(instant_view_); | 703 gtk_widget_hide(instant_view_); |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1876 } | 1820 } |
1877 | 1821 |
1878 void OmniboxViewGtk::ItersFromCharRange(const CharRange& range, | 1822 void OmniboxViewGtk::ItersFromCharRange(const CharRange& range, |
1879 GtkTextIter* iter_min, | 1823 GtkTextIter* iter_min, |
1880 GtkTextIter* iter_max) { | 1824 GtkTextIter* iter_max) { |
1881 DCHECK(!IsImeComposing()); | 1825 DCHECK(!IsImeComposing()); |
1882 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min); | 1826 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min); |
1883 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max); | 1827 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max); |
1884 } | 1828 } |
1885 | 1829 |
1886 int OmniboxViewGtk::GetTextLength() const { | 1830 int OmniboxViewGtk::GetOmniboxTextLength() const { |
1887 GtkTextIter end; | 1831 GtkTextIter end; |
1888 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); | 1832 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); |
1889 if (supports_pre_edit_) { | 1833 if (supports_pre_edit_) { |
1890 // We need to count the length of the text being composed, because we treat | 1834 // We need to count the length of the text being composed, because we treat |
1891 // it as part of the content in GetText(). | 1835 // it as part of the content in GetText(). |
1892 return gtk_text_iter_get_offset(&end) + pre_edit_.size(); | 1836 return gtk_text_iter_get_offset(&end) + pre_edit_.size(); |
1893 } | 1837 } |
1894 return gtk_text_iter_get_offset(&end); | 1838 return gtk_text_iter_get_offset(&end); |
1895 } | 1839 } |
1896 | 1840 |
1897 void OmniboxViewGtk::PlaceCaretAt(int pos) { | |
1898 GtkTextIter cursor; | |
1899 gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, pos); | |
1900 gtk_text_buffer_place_cursor(text_buffer_, &cursor); | |
1901 } | |
1902 | |
1903 bool OmniboxViewGtk::IsCaretAtEnd() const { | 1841 bool OmniboxViewGtk::IsCaretAtEnd() const { |
1904 const CharRange selection = GetSelection(); | 1842 const CharRange selection = GetSelection(); |
1905 return selection.cp_min == selection.cp_max && | 1843 return selection.cp_min == selection.cp_max && |
1906 selection.cp_min == GetTextLength(); | 1844 selection.cp_min == GetOmniboxTextLength(); |
1907 } | 1845 } |
1908 | 1846 |
1909 void OmniboxViewGtk::EmphasizeURLComponents() { | 1847 void OmniboxViewGtk::EmphasizeURLComponents() { |
1910 if (supports_pre_edit_) { | 1848 if (supports_pre_edit_) { |
1911 // We can't change the text style easily, if the pre-edit string (the text | 1849 // We can't change the text style easily, if the pre-edit string (the text |
1912 // being composed by the input method) is not empty, which is not treated as | 1850 // being composed by the input method) is not empty, which is not treated as |
1913 // a part of the text content inside GtkTextView. And it's ok to simply | 1851 // a part of the text content inside GtkTextView. And it's ok to simply |
1914 // return in this case, as this method will be called again when the | 1852 // return in this case, as this method will be called again when the |
1915 // pre-edit string gets committed. | 1853 // pre-edit string gets committed. |
1916 if (pre_edit_.size()) { | 1854 if (pre_edit_.size()) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1974 } | 1912 } |
1975 } | 1913 } |
1976 | 1914 |
1977 void OmniboxViewGtk::StopAnimation() { | 1915 void OmniboxViewGtk::StopAnimation() { |
1978 // Clear the animation delegate so we don't get an AnimationEnded() callback. | 1916 // Clear the animation delegate so we don't get an AnimationEnded() callback. |
1979 instant_animation_->set_delegate(NULL); | 1917 instant_animation_->set_delegate(NULL); |
1980 instant_animation_->Stop(); | 1918 instant_animation_->Stop(); |
1981 UpdateInstantViewColors(); | 1919 UpdateInstantViewColors(); |
1982 } | 1920 } |
1983 | 1921 |
1984 void OmniboxViewGtk::TextChanged() { | |
1985 EmphasizeURLComponents(); | |
1986 model_->OnChanged(); | |
1987 } | |
1988 | |
1989 void OmniboxViewGtk::SavePrimarySelection(const std::string& selected_text) { | 1922 void OmniboxViewGtk::SavePrimarySelection(const std::string& selected_text) { |
1990 DCHECK(text_view_); | 1923 DCHECK(text_view_); |
1991 | 1924 |
1992 GtkClipboard* clipboard = | 1925 GtkClipboard* clipboard = |
1993 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 1926 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
1994 DCHECK(clipboard); | 1927 DCHECK(clipboard); |
1995 if (!clipboard) | 1928 if (!clipboard) |
1996 return; | 1929 return; |
1997 | 1930 |
1998 gtk_clipboard_set_text( | 1931 gtk_clipboard_set_text( |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2242 void OmniboxViewGtk::AdjustVerticalAlignmentOfInstantView() { | 2175 void OmniboxViewGtk::AdjustVerticalAlignmentOfInstantView() { |
2243 // By default, GtkTextView layouts an anchored child widget just above the | 2176 // By default, GtkTextView layouts an anchored child widget just above the |
2244 // baseline, so we need to move the |instant_view_| down to make sure it | 2177 // baseline, so we need to move the |instant_view_| down to make sure it |
2245 // has the same baseline as the |text_view_|. | 2178 // has the same baseline as the |text_view_|. |
2246 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2179 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
2247 int height; | 2180 int height; |
2248 pango_layout_get_size(layout, NULL, &height); | 2181 pango_layout_get_size(layout, NULL, &height); |
2249 int baseline = pango_layout_get_baseline(layout); | 2182 int baseline = pango_layout_get_baseline(layout); |
2250 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2183 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
2251 } | 2184 } |
OLD | NEW |