Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Unified Diff: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc

Issue 151006: Make Linux restore Omnibox contents on tab switch. (Closed)
Patch Set: free string returned by gtk Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index 06647df7e16595160f0dbfaa596e889341275149..1ee5a15327400d4307d27690136da4b433518f47 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -34,6 +34,34 @@ size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) {
return WideToUTF8(wide_text.substr(0, wide_text_offset)).size();
}
+// Stores GTK+-specific state so it can be restored after switching tabs.
+struct ViewState {
+ explicit ViewState(const AutocompleteEditViewGtk::CharRange& selection_range)
+ : selection_range(selection_range) {
+ }
+
+ // Range of selected text.
+ AutocompleteEditViewGtk::CharRange selection_range;
+};
+
+struct AutocompleteEditState {
+ AutocompleteEditState(const AutocompleteEditModel::State& model_state,
+ const ViewState& view_state)
+ : model_state(model_state),
+ view_state(view_state) {
+ }
+
+ const AutocompleteEditModel::State model_state;
+ const ViewState view_state;
+};
+
+// Returns a lazily initialized property bag accessor for saving our state in a
+// TabContents.
+PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
+ static PropertyAccessor<AutocompleteEditState> state;
+ return &state;
+}
+
} // namespace
AutocompleteEditViewGtk::AutocompleteEditViewGtk(
@@ -48,7 +76,6 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk(
base_tag_(NULL),
secure_scheme_tag_(NULL),
insecure_scheme_tag_(NULL),
- primary_clipboard_(NULL),
model_(new AutocompleteEditModel(this, controller, profile)),
popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile,
popup_positioner)),
@@ -56,7 +83,8 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk(
toolbar_model_(toolbar_model),
command_updater_(command_updater),
popup_window_mode_(false), // TODO(deanm)
- scheme_security_level_(ToolbarModel::NORMAL) {
+ scheme_security_level_(ToolbarModel::NORMAL),
+ selection_saved_(false) {
model_->set_popup_model(popup_view_->GetModel());
}
@@ -145,6 +173,8 @@ void AutocompleteEditViewGtk::Init() {
G_CALLBACK(&HandleViewSizeRequestThunk), this);
g_signal_connect(text_view_, "populate-popup",
G_CALLBACK(&HandlePopulatePopupThunk), this);
+ g_signal_connect(text_buffer_, "mark-set",
+ G_CALLBACK(&HandleMarkSetThunk), this);
}
void AutocompleteEditViewGtk::SetFocus() {
@@ -152,7 +182,18 @@ void AutocompleteEditViewGtk::SetFocus() {
}
void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) {
- NOTIMPLEMENTED();
+ DCHECK(tab);
+ GetStateAccessor()->SetProperty(
+ tab->property_bag(),
+ AutocompleteEditState(model_->GetStateForTabSwitch(),
+ ViewState(GetSelection())));
+
+ // If any text has been selected, register it as the PRIMARY selection so it
+ // can still be pasted via middle-click after the text view is cleared.
+ if (!selected_text_.empty() && !selection_saved_) {
+ SavePrimarySelection(selected_text_);
+ selection_saved_ = true;
+ }
}
void AutocompleteEditViewGtk::Update(const TabContents* contents) {
@@ -173,9 +214,27 @@ void AutocompleteEditViewGtk::Update(const TabContents* contents) {
}
if (contents) {
+ selected_text_.clear();
+ selection_saved_ = false;
RevertAll();
- // TODO(deanm): Tab switching. The Windows code puts some state in a
- // PropertyBag on the tab contents, and restores state from there.
+ const AutocompleteEditState* state =
+ GetStateAccessor()->GetProperty(contents->property_bag());
+ if (state) {
+ model_->RestoreState(state->model_state);
+
+ // Move the marks for the cursor and the other end of the selection to
+ // the previously-saved offsets.
+ GtkTextIter selection_iter, insert_iter;
+ ItersFromCharRange(
+ state->view_state.selection_range, &selection_iter, &insert_iter);
+ // TODO(derat): Restore the selection range instead of just the cursor
+ // ("insert") position. This in itself is trivial to do using
+ // gtk_text_buffer_select_range(), but then it also becomes necessary to
+ // invalidate hidden tabs' saved ranges when another tab or another app
+ // takes the selection, lest we incorrectly regrab a stale selection when
+ // a hidden tab is later shown.
+ gtk_text_buffer_place_cursor(text_buffer_, &insert_iter);
+ }
} else if (visibly_changed_permanent_text) {
RevertAll();
// TODO(deanm): There should be code to restore select all here.
@@ -295,17 +354,18 @@ bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged(
size_t user_text_length) {
if (display_text == GetText())
return false;
-
+
// We need to get the clipboard while it's attached to the toplevel. The
// easiest thing to do is just to lazily pull the clipboard here.
- if (primary_clipboard_ == NULL) {
- primary_clipboard_ = gtk_widget_get_clipboard(text_view_,
- GDK_SELECTION_PRIMARY);
- }
+ GtkClipboard* clipboard =
+ gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
+ DCHECK(clipboard);
+ if (!clipboard)
+ return true;
// Remove the PRIMARY clipboard to avoid having "clipboard helpers" like
// klipper and glipper race with / remove our inline autocomplete selection.
- gtk_text_buffer_remove_selection_clipboard(text_buffer_, primary_clipboard_);
+ gtk_text_buffer_remove_selection_clipboard(text_buffer_, clipboard);
SetWindowTextAndCaretPos(display_text, 0);
// Select the part of the text that was inline autocompleted.
@@ -316,7 +376,7 @@ bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged(
TextChanged();
// Put the PRIMARY clipboard back, so that selection still somewhat works.
- gtk_text_buffer_add_selection_clipboard(text_buffer_, primary_clipboard_);
+ gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard);
return true;
}
@@ -449,6 +509,12 @@ gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) {
if (GTK_WIDGET_HAS_FOCUS(text_view_))
return FALSE; // Continue to propagate into the GtkTextView handler.
+ // We only want to select everything on left-click; otherwise we'll end up
+ // stealing the PRIMARY selection when the user middle-clicks to paste it
+ // here.
+ if (event->button != 1)
+ return FALSE;
+
// Call the GtkTextView default handler, ignoring the fact that it will
// likely have told us to stop propagating. We want to handle selection.
GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(text_view_);
@@ -545,6 +611,44 @@ void AutocompleteEditViewGtk::HandlePasteAndGoReceivedText(
model_->PasteAndGo();
}
+void AutocompleteEditViewGtk::HandleMarkSet(GtkTextBuffer* buffer,
+ GtkTextIter* location,
+ GtkTextMark* mark) {
+ if (!text_buffer_ || buffer != text_buffer_)
+ return;
+
+ if (mark != gtk_text_buffer_get_insert(text_buffer_) &&
+ mark != gtk_text_buffer_get_selection_bound(text_buffer_)) {
+ return;
+ }
+
+ // Is no text selected in the GtkTextView?
+ bool no_text_selected = false;
+
+ // Get the currently-selected text, if there is any.
+ GtkTextIter start, end;
+ if (!gtk_text_buffer_get_selection_bounds(text_buffer_, &start, &end)) {
+ no_text_selected = true;
+ } else {
+ gchar* text = gtk_text_iter_get_text(&start, &end);
+ size_t text_len = strlen(text);
+ if (!text_len) {
+ no_text_selected = true;
+ } else {
+ selected_text_ = std::string(text, text_len);
+ selection_saved_ = false;
+ }
+ g_free(text);
+ }
+
+ // If we have some previously-selected text but it's no longer highlighted
+ // and we haven't saved it as the selection yet, we save it now.
+ if (!selected_text_.empty() && no_text_selected && !selection_saved_) {
+ SavePrimarySelection(selected_text_);
+ selection_saved_ = true;
+ }
+}
+
AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() {
// You can not just use get_selection_bounds here, since the order will be
// ascending, and you don't know where the user's start and end of the
@@ -635,3 +739,15 @@ void AutocompleteEditViewGtk::TextChanged() {
EmphasizeURLComponents();
controller_->OnChanged();
}
+
+void AutocompleteEditViewGtk::SavePrimarySelection(
+ const std::string& selected_text) {
+ GtkClipboard* clipboard =
+ gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
+ DCHECK(clipboard);
+ if (!clipboard)
+ return;
+
+ gtk_clipboard_set_text(
+ clipboard, selected_text.data(), selected_text.size());
+}
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | chrome/browser/gtk/location_bar_view_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698