diff options
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc | 483 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_gtk.h | 201 | ||||
-rwxr-xr-x | chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc | 115 | ||||
-rwxr-xr-x | chrome/browser/autocomplete/autocomplete_popup_view_gtk.h | 55 | ||||
-rw-r--r-- | chrome/browser/browser.scons | 3 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.cc | 91 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.h | 24 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.cc | 143 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.h | 88 |
9 files changed, 1114 insertions, 89 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc new file mode 100644 index 0000000..cae7c6e --- /dev/null +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -0,0 +1,483 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" + +#include <gtk/gtk.h> + +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/toolbar_model.h" +#include "chrome/common/notification_service.h" +#include "googleurl/src/gurl.h" + +namespace { + +const char kTextBaseColor[] = "#808080"; +const char kSecureSchemeColor[] = "#009614"; +const char kInsecureSchemeColor[] = "#009614"; +const GdkColor kSecureBackgroundColor = {0, 65535, 62965, 50115}; // #fff5c3 +const GdkColor kInsecureBackgroundColor = {0, 65535, 65535, 65535}; // #ffffff + +} // namespace + +AutocompleteEditViewGtk::AutocompleteEditViewGtk( + AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater) + : text_view_(NULL), + tag_table_(NULL), + text_buffer_(NULL), + base_tag_(NULL), + secure_scheme_tag_(NULL), + insecure_scheme_tag_(NULL), + model_(new AutocompleteEditModel(this, controller, profile)), + popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile)), + controller_(controller), + toolbar_model_(toolbar_model), + command_updater_(command_updater), + popup_window_mode_(false), // TODO(deanm) + scheme_security_level_(ToolbarModel::NORMAL) { + model_->set_popup_model(popup_view_->model()); +} + +AutocompleteEditViewGtk::~AutocompleteEditViewGtk() { + NotificationService::current()->Notify( + NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, + Source<AutocompleteEditViewGtk>(this), + NotificationService::NoDetails()); +} + +void AutocompleteEditViewGtk::Init() { + tag_table_ = gtk_text_tag_table_new(); + text_buffer_ = gtk_text_buffer_new(tag_table_); + text_view_ = gtk_text_view_new_with_buffer(text_buffer_); + + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_view_), 4); + gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text_view_), 4); + + // TODO(deanm): This is a super lame attempt to vertically center our single + // line of text in a multiline edit control. Mannnn. + gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(text_view_), 4); + + // TODO(deanm): This will probably have to be handled differently with the + // tab to search business. Maybe we should just eat the tab characters. + // We want the tab key to move focus, not insert a tab. + gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(text_view_), false); + + base_tag_ = gtk_text_buffer_create_tag(text_buffer_, + NULL, "foreground", kTextBaseColor, NULL); + secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, + NULL, "foreground", kSecureSchemeColor, NULL); + insecure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, + NULL, "foreground", kInsecureSchemeColor, NULL); + + // NOTE: This code used to connect to "changed", however this was fired too + // often and during bad times (our own buffer changes?). It works out much + // better to listen to end-user-action, which should be fired whenever the + // user makes some sort of change to the buffer. + g_signal_connect(text_buffer_, "begin-user-action", + G_CALLBACK(&HandleBeginUserActionThunk), this); + g_signal_connect(text_buffer_, "end-user-action", + G_CALLBACK(&HandleEndUserActionThunk), this); + g_signal_connect(text_view_, "size-request", + G_CALLBACK(&HandleViewSizeRequest), this); + g_signal_connect(text_view_, "button-press-event", + G_CALLBACK(&HandleViewButtonPressThunk), this); + g_signal_connect(text_view_, "focus-in-event", + G_CALLBACK(&HandleViewFocusInThunk), this); + g_signal_connect(text_view_, "focus-out-event", + G_CALLBACK(&HandleViewFocusOutThunk), this); + // NOTE: The GtkTextView documentation asks you not to connect to this + // signal, but it is very convenient and clean for catching up/down. + g_signal_connect(text_view_, "move-cursor", + G_CALLBACK(&HandleViewMoveCursorThunk), this); +} + +void AutocompleteEditViewGtk::FocusLocation() { + gtk_widget_grab_focus(text_view_); + SelectAll(false); +} + +void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) { + NOTIMPLEMENTED(); +} + +void AutocompleteEditViewGtk::Update(const TabContents* contents) { + // NOTE: We're getting the URL text here from the ToolbarModel. + bool visibly_changed_permanent_text = + model_->UpdatePermanentText(toolbar_model_->GetText()); + + ToolbarModel::SecurityLevel security_level = + toolbar_model_->GetSchemeSecurityLevel(); + bool changed_security_level = (security_level != scheme_security_level_); + scheme_security_level_ = security_level; + + if (contents) { + RevertAll(); + // TODO(deanm): Tab switching. The Windows code puts some state in a + // PropertyBag on the tab contents, and restores state from there. + } else if (visibly_changed_permanent_text) { + RevertAll(); + // TODO(deanm): There should be code to restore select all here. + } else if(changed_security_level) { + EmphasizeURLComponents(); + } +} + +void AutocompleteEditViewGtk::OpenURL(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url, + size_t selected_line, + const std::wstring& keyword) { + if (!url.is_valid()) + return; + + model_->SendOpenNotification(selected_line, keyword); + + if (disposition != NEW_BACKGROUND_TAB) + RevertAll(); // Revert the box to its unedited state + controller_->OnAutocompleteAccept(url, disposition, transition, + alternate_nav_url); +} + +std::wstring AutocompleteEditViewGtk::GetText() const { + GtkTextIter start, end; + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false); + std::wstring out(UTF8ToWide(utf8)); + g_free(utf8); + return out; +} + +void AutocompleteEditViewGtk::SetUserText(const std::wstring& text, + const std::wstring& display_text, + bool update_popup) { + NOTIMPLEMENTED(); +} + +void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const std::wstring& text, + size_t caret_pos) { + std::string utf8 = WideToUTF8(text); + gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); + EmphasizeURLComponents(); + + GtkTextIter cur_pos; + gtk_text_buffer_get_iter_at_offset(text_buffer_, &cur_pos, caret_pos); + gtk_text_buffer_place_cursor(text_buffer_, &cur_pos); +} + +bool AutocompleteEditViewGtk::IsSelectAll() { + NOTIMPLEMENTED(); + return false; +} + +void AutocompleteEditViewGtk::SelectAll(bool reversed) { + GtkTextIter start, end; + if (reversed) { + gtk_text_buffer_get_bounds(text_buffer_, &end, &start); + } else { + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + } + gtk_text_buffer_place_cursor(text_buffer_, &start); + gtk_text_buffer_select_range(text_buffer_, &start, &end); +} + +void AutocompleteEditViewGtk::RevertAll() { + ClosePopup(); + model_->Revert(); + TextChanged(); +} + +void AutocompleteEditViewGtk::UpdatePopup() { + model_->SetInputInProgress(true); + if (!model_->has_focus()) + return; + + // Don't inline autocomplete when the caret/selection isn't at the end of + // the text. + CharRange sel = GetSelection(); + model_->StartAutocomplete(sel.cp_max < GetTextLength()); +} + +void AutocompleteEditViewGtk::ClosePopup() { + popup_view_->model()->StopAutocomplete(); +} + +void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged( + const std::wstring& display_text, + bool save_original_selection) { + // TODO(deanm): Ignoring save_original_selection here, etc. + SetWindowTextAndCaretPos(display_text, display_text.length()); + TextChanged(); +} + +bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged( + const std::wstring& display_text, + size_t user_text_length) { + if (display_text == GetText()) + return false; + + SetWindowTextAndCaretPos(display_text, 0); + + // Select the part of the text that was inline autocompleted. + GtkTextIter bound, insert; + gtk_text_buffer_get_bounds(text_buffer_, &insert, &bound); + gtk_text_buffer_get_iter_at_offset(text_buffer_, &insert, user_text_length); + gtk_text_buffer_select_range(text_buffer_, &insert, &bound); + + TextChanged(); + return true; +} + +void AutocompleteEditViewGtk::OnRevertTemporaryText() { + NOTIMPLEMENTED(); +} + +void AutocompleteEditViewGtk::OnBeforePossibleChange() { + // Record our state. + text_before_change_ = GetText(); + sel_before_change_ = GetSelection(); +} + +// TODO(deanm): This is mostly stolen from Windows, and will need some work. +bool AutocompleteEditViewGtk::OnAfterPossibleChange() { + CharRange new_sel = GetSelection(); + int length = GetTextLength(); + bool selection_differs = (new_sel.cp_min != sel_before_change_.cp_min) || + (new_sel.cp_max != sel_before_change_.cp_max); + bool at_end_of_edit = (new_sel.cp_min == length && new_sel.cp_max == length); + + // See if the text or selection have changed since OnBeforePossibleChange(). + std::wstring new_text(GetText()); + bool text_differs = (new_text != text_before_change_); + + // When the user has deleted text, we don't allow inline autocomplete. Make + // sure to not flag cases like selecting part of the text and then pasting + // (or typing) the prefix of that selection. (We detect these by making + // sure the caret, which should be after any insertion, hasn't moved + // forward of the old selection start.) + bool just_deleted_text = + (text_before_change_.length() > new_text.length()) && + (new_sel.cp_min <= std::min(sel_before_change_.cp_min, + sel_before_change_.cp_max)); + + bool something_changed = model_->OnAfterPossibleChange(new_text, + selection_differs, text_differs, just_deleted_text, at_end_of_edit); + + if (something_changed && text_differs) + TextChanged(); + + return something_changed; +} + +void AutocompleteEditViewGtk::BottomLeftPosWidth(int* x, int* y, int* width) { + gdk_window_get_origin(text_view_->window, x, y); + *y += text_view_->allocation.height; + *width = text_view_->allocation.width; +} + +void AutocompleteEditViewGtk::HandleBeginUserAction() { + OnBeforePossibleChange(); +} + +void AutocompleteEditViewGtk::HandleEndUserAction() { + bool had_newline = false; + + // TODO(deanm): obviously super inefficient. + for(;;) { + GtkTextIter cur, end; + gtk_text_buffer_get_bounds(text_buffer_, &cur, &end); + + while (!gtk_text_iter_equal(&cur, &end)) { + if (gtk_text_iter_ends_line(&cur)) { + had_newline = true; + GtkTextIter next = cur; + gtk_text_iter_forward_char(&next); + gtk_text_buffer_delete(text_buffer_, &cur, &next); + + // We've invalidated our iterators, gotta start again. + break; + } + + gtk_text_iter_forward_char(&cur); + } + + // We've exhausted the whole input and there is now only 1 line, good. + if (gtk_text_iter_equal(&cur, &end)) + break; + } + + OnAfterPossibleChange(); + + if (had_newline) + model_->AcceptInput(CURRENT_TAB, false); +} + +// static +void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkWidget* view, + GtkRequisition* req, + gpointer unused) { + // Don't force a minimum size, allow our embedder to size us better. + req->height = req->width = 1; +} + +gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) { + // When the GtkTextView is clicked, it will call gtk_widget_grab_focus. + // I believe this causes the focus-in event to be fired before the main + // clicked handling code. If we were to try to set the selection from + // the focus-in event, it's just going to be undone by the click handler. + // This is a bit ugly. We shim in to get the click before the GtkTextView, + // then if we don't have focus, we (hopefully safely) assume that the click + // will cause us to become focused. We call GtkTextView's default handler + // and then stop propagation. This allows us to run our code after the + // default handler, even if that handler stopped propagation. + if (GTK_WIDGET_HAS_FOCUS(text_view_)) + return FALSE; // Continue to propagate into the GtkTextView handler. + + // 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_); + klass->button_press_event(text_view_, event); + + // Select the full input when we get focus. + SelectAll(false); + // So we told the buffer where the cursor should be, but make sure to tell + // the view so it can scroll it to be visible if needed. + // NOTE: This function doesn't seem to like a count of 0, looking at the + // code it will skip an important loop. Use -1 to achieve the same. + GtkTextIter start, end; + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); + + return TRUE; // Don't continue, we called the default handler already. +} + +gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { + model_->OnSetFocus(false); + // TODO(deanm): Some keyword hit business, etc here. + + return FALSE; // Continue propagation. +} + +gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { + // Close the popup. + ClosePopup(); + + // Tell the model to reset itself. + model_->OnKillFocus(); + + // TODO(deanm): This probably isn't right, and doesn't match Windows. We + // don't really want to match Windows though, because it probably feels + // wrong on Linux. Firefox doesn't have great behavior here also, imo. + // Deselect any selection and make sure the input is at the beginning. + GtkTextIter start, end; + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + gtk_text_buffer_place_cursor(text_buffer_, &start); + return FALSE; // Pass the event on to the GtkTextView. +} + +void AutocompleteEditViewGtk::HandleViewMoveCursor( + GtkMovementStep step, + gint count, + gboolean extendion_selection) { + // Handle up / down cursor movement on our own. + if (step == GTK_MOVEMENT_DISPLAY_LINES) { + model_->OnUpOrDownKeyPressed(count); + // move-cursor doesn't use a signal accumulator on the return value (it + // just ignores them), so we have to stop the propagation. + g_signal_stop_emission_by_name(text_view_, "move-cursor"); + return; + } + // Propagate into GtkTextView. +} + +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 + // selection was (if the selection was forwards or backwards). Get the + // actual marks so that we can preserve the selection direction. + GtkTextIter start, insert; + GtkTextMark* mark; + + mark = gtk_text_buffer_get_selection_bound(text_buffer_); + gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark); + + mark = gtk_text_buffer_get_insert(text_buffer_); + gtk_text_buffer_get_iter_at_mark(text_buffer_, &insert, mark); + + return CharRange(gtk_text_iter_get_offset(&start), + gtk_text_iter_get_offset(&insert)); +} + +void AutocompleteEditViewGtk::ItersFromCharRange(const CharRange& range, + GtkTextIter* iter_min, + GtkTextIter* iter_max) { + gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min); + gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max); +} + +int AutocompleteEditViewGtk::GetTextLength() { + GtkTextIter start, end; + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + return gtk_text_iter_get_offset(&end); +} + +void AutocompleteEditViewGtk::EmphasizeURLComponents() { + // See whether the contents are a URL with a non-empty host portion, which we + // should emphasize. To check for a URL, rather than using the type returned + // by Parse(), ask the model, which will check the desired page transition for + // this input. This can tell us whether an UNKNOWN input string is going to + // be treated as a search or a navigation, and is the same method the Paste + // And Go system uses. + url_parse::Parsed parts; + AutocompleteInput::Parse(GetText(), model_->GetDesiredTLD(), &parts, NULL); + bool emphasize = model_->CurrentTextIsURL() && (parts.host.len > 0); + + // Set the baseline emphasis. + GtkTextIter start, end; + gtk_text_buffer_get_bounds(text_buffer_, &start, &end); + gtk_text_buffer_remove_all_tags(text_buffer_, &start, &end); + if (emphasize) { + gtk_text_buffer_apply_tag(text_buffer_, base_tag_, &start, &end); + + // We've found a host name, give it more emphasis. + gtk_text_buffer_get_iter_at_line_index(text_buffer_, &start, 0, + parts.host.begin); + gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0, + parts.host.end()); + gtk_text_buffer_remove_all_tags(text_buffer_, &start, &end); + } + + // Emphasize the scheme for security UI display purposes (if necessary). + if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() && + (scheme_security_level_ != ToolbarModel::NORMAL)) { + gtk_text_buffer_get_iter_at_line_index(text_buffer_, &start, 0, + parts.scheme.begin); + gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0, + parts.scheme.end()); + const GdkColor* background; + if (scheme_security_level_ == ToolbarModel::SECURE) { + background = &kSecureBackgroundColor; + gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, + &start, &end); + } else { + background = &kInsecureBackgroundColor; + gtk_text_buffer_apply_tag(text_buffer_, insecure_scheme_tag_, + &start, &end); + } + gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background); + } +} + +void AutocompleteEditViewGtk::TextChanged() { + EmphasizeURLComponents(); + controller_->OnChanged(); +} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h new file mode 100644 index 0000000..85d16ae --- /dev/null +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -0,0 +1,201 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ + +#include <gtk/gtk.h> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/autocomplete/autocomplete_edit_view.h" +#include "chrome/browser/toolbar_model.h" +#include "chrome/common/page_transition_types.h" +#include "webkit/glue/window_open_disposition.h" + +class AutocompleteEditController; +class AutocompleteEditModel; +class AutocompletePopupViewGtk; +class CommandUpdater; +class Profile; +class TabContents; +class ToolbarModel; + +class AutocompleteEditViewGtk : public AutocompleteEditView { + public: + AutocompleteEditViewGtk(AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater); + ~AutocompleteEditViewGtk(); + + // Initialize, create the underlying widgets, etc. + void Init(); + + GtkWidget* widget() { return text_view_; } + + // Grab keyboard input focus, putting focus on the location widget. + void FocusLocation(); + + // Implement the AutocompleteEditView interface. + virtual AutocompleteEditModel* model() { return model_.get(); } + virtual const AutocompleteEditModel* model() const { return model_.get(); } + + virtual void SaveStateToTab(TabContents* tab); + + virtual void Update(const TabContents* tab_for_state_restoring); + + virtual void OpenURL(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url, + size_t selected_line, + const std::wstring& keyword); + + virtual std::wstring GetText() const; + + virtual void SetUserText(const std::wstring& text) { + SetUserText(text, text, true); + } + virtual void SetUserText(const std::wstring& text, + const std::wstring& display_text, + bool update_popup); + + virtual void SetWindowTextAndCaretPos(const std::wstring& text, + size_t caret_pos); + + virtual bool IsSelectAll(); + virtual void SelectAll(bool reversed); + virtual void RevertAll(); + + virtual void UpdatePopup(); + virtual void ClosePopup(); + + virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text, + bool save_original_selection); + virtual bool OnInlineAutocompleteTextMaybeChanged( + const std::wstring& display_text, size_t user_text_length); + virtual void OnRevertTemporaryText(); + virtual void OnBeforePossibleChange(); + virtual bool OnAfterPossibleChange(); + + // Return the position (root coordinates) of the bottom left corner and width + // of the location input box. Used by the popup view to position itself. + void BottomLeftPosWidth(int* x, int* y, int* width); + + private: + // Modeled like the Windows CHARRANGE. Represent a pair of cursor position + // offsets. Since GtkTextIters are invalid after the buffer is changed, we + // work in character offsets (not bytes). + struct CharRange { + CharRange() : cp_min(0), cp_max(0) { } + CharRange(int n, int x) : cp_min(n), cp_max(x) { } + + // Work in integers to match the gint GTK APIs. + int cp_min; // For a selection: Represents the start. + int cp_max; // For a selection: Represents the end (insert position). + }; + + // TODO(deanm): Would be nice to insulate the thunkers better, etc. + static void HandleBeginUserActionThunk(GtkTextBuffer* unused, gpointer self) { + reinterpret_cast<AutocompleteEditViewGtk*>(self)->HandleBeginUserAction(); + } + void HandleBeginUserAction(); + + static void HandleEndUserActionThunk(GtkTextBuffer* unused, gpointer self) { + reinterpret_cast<AutocompleteEditViewGtk*>(self)->HandleEndUserAction(); + } + void HandleEndUserAction(); + + static void HandleViewSizeRequest(GtkWidget* view, GtkRequisition* req, + gpointer unused); + + static gboolean HandleViewButtonPressThunk(GtkWidget* view, + GdkEventButton* event, + gpointer self) { + return reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + HandleViewButtonPress(event); + } + gboolean HandleViewButtonPress(GdkEventButton* event); + + static gboolean HandleViewFocusInThunk(GtkWidget* view, + GdkEventFocus* event, + gpointer self) { + return reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + HandleViewFocusIn(); + } + gboolean HandleViewFocusIn(); + + static gboolean HandleViewFocusOutThunk(GtkWidget* view, + GdkEventFocus* event, + gpointer self) { + return reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + HandleViewFocusOut(); + } + gboolean HandleViewFocusOut(); + + static void HandleViewMoveCursorThunk(GtkWidget* view, + GtkMovementStep step, + gint count, + gboolean extend_selection, + gpointer self) { + reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + HandleViewMoveCursor(step, count, extend_selection); + } + void HandleViewMoveCursor(GtkMovementStep step, + gint count, + gboolean extendion_selection); + + // Get the character indices of the current selection. This honors + // direction, cp_max is the insertion point, and cp_min is the bound. + CharRange GetSelection(); + + // Translate from character positions to iterators for the current buffer. + void ItersFromCharRange(const CharRange& range, + GtkTextIter* iter_min, + GtkTextIter* iter_max); + + // Return the number of characers in the current buffer. + int GetTextLength(); + + // Try to parse the current text as a URL and colorize the components. + void EmphasizeURLComponents(); + + // Internally invoked whenever the text changes in some way. + void TextChanged(); + + GtkWidget* text_view_; + + GtkTextTagTable* tag_table_; + GtkTextBuffer* text_buffer_; + + GtkTextTag* base_tag_; + GtkTextTag* secure_scheme_tag_; + GtkTextTag* insecure_scheme_tag_; + + scoped_ptr<AutocompleteEditModel> model_; + scoped_ptr<AutocompletePopupViewGtk> popup_view_; + AutocompleteEditController* controller_; + ToolbarModel* toolbar_model_; + + // The object that handles additional command functionality exposed on the + // edit, such as invoking the keyword editor. + CommandUpdater* command_updater_; + + // When true, the location bar view is read only and also is has a slightly + // different presentation (font size / color). This is used for popups. + // TODO(deanm). + bool popup_window_mode_; + + ToolbarModel::SecurityLevel scheme_security_level_; + + // Tracking state before and after a possible change. + std::wstring text_before_change_; + CharRange sel_before_change_; + + DISALLOW_COPY_AND_ASSIGN(AutocompleteEditViewGtk); +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_GTK_H_ diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc new file mode 100755 index 0000000..8f1b586 --- /dev/null +++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc @@ -0,0 +1,115 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" + +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" +#include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/common/notification_service.h" + +namespace { + +const GdkColor kPopupBorderColor = {0, 51143, 51914, 52942}; // #c7cace +const GdkColor kPopupBackground = {0, 65535, 65535, 65535}; // #ffffff +const GdkColor kHighlightColor = {0, 49601, 51400, 55769}; // #c1c8d9 + +} // namespace + +AutocompletePopupViewGtk::AutocompletePopupViewGtk( + AutocompleteEditViewGtk* edit_view, + AutocompleteEditModel* edit_model, + Profile* profile) + : model_(new AutocompletePopupModel(this, edit_model, profile)), + edit_view_(edit_view), + window_(gtk_window_new(GTK_WINDOW_POPUP)), + vbox_(NULL), + opened_(false) { + GTK_WIDGET_UNSET_FLAGS(window_, GTK_CAN_FOCUS); + // Don't allow the window to be resized. This also forces the window to + // shrink down to the size of its child contents. + gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); + // Set up a 1 pixel border around the popup. + gtk_container_set_border_width(GTK_CONTAINER(window_), 1); + gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kPopupBorderColor); + gtk_widget_modify_base(window_, GTK_STATE_NORMAL, &kPopupBorderColor); +} + +AutocompletePopupViewGtk::~AutocompletePopupViewGtk() { + if (vbox_) + gtk_widget_destroy(vbox_); + gtk_widget_destroy(window_); +} + +void AutocompletePopupViewGtk::InvalidateLine(size_t line) { + UpdatePopupAppearance(); +} + +void AutocompletePopupViewGtk::UpdatePopupAppearance() { + const AutocompleteResult& result = model_->result(); + if (result.empty()) { + Hide(); + return; + } + + // TODO(deanm): This could be done better, but the code is temporary + // and will need to be replaced with custom drawing and not widgets. + if (vbox_) + gtk_widget_destroy(vbox_); + + vbox_ = gtk_vbox_new(FALSE, 0); + + for (size_t i = 0; i < result.size(); ++i) { + std::string utf8; + utf8.append(WideToUTF8(result.match_at(i).contents)); + utf8.append(" - "); + utf8.append(WideToUTF8(result.match_at(i).description)); + GtkWidget* label = gtk_label_new(utf8.c_str()); + // We need to put the labels in an event box for background painting. + GtkWidget* ebox = gtk_event_box_new(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + gtk_container_add(GTK_CONTAINER(ebox), label); + gtk_box_pack_start(GTK_BOX(vbox_), ebox, FALSE, FALSE, 0); + gtk_widget_show(label); + gtk_widget_show(ebox); + if (i == model_->selected_line()) { + gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &kHighlightColor); + } else { + gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &kPopupBackground); + } + } + + gtk_widget_show(vbox_); + gtk_container_add(GTK_CONTAINER(window_), vbox_); + Show(); +} + +void AutocompletePopupViewGtk::OnHoverEnabledOrDisabled(bool disabled) { + NOTIMPLEMENTED(); +} + +void AutocompletePopupViewGtk::PaintUpdatesNow() { + UpdatePopupAppearance(); +} + +void AutocompletePopupViewGtk::Show() { + gint x, y, width; + edit_view_->BottomLeftPosWidth(&x, &y, &width); + gtk_window_move(GTK_WINDOW(window_), x, y); + gtk_widget_set_size_request(window_, width, -1); + gtk_widget_show(window_); + opened_ = true; +} + +void AutocompletePopupViewGtk::Hide() { + gtk_widget_hide(window_); + opened_ = false; +} diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h new file mode 100755 index 0000000..3c4fcc8 --- /dev/null +++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h @@ -0,0 +1,55 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_ + +#include <gtk/gtk.h> + +#include <string> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/autocomplete/autocomplete_popup_view.h" +#include "webkit/glue/window_open_disposition.h" + +class AutocompletePopupModel; +class AutocompleteEditModel; +class AutocompleteEditViewGtk; +class Profile; +class SkBitmap; + +class AutocompletePopupViewGtk : public AutocompletePopupView { + public: + AutocompletePopupViewGtk(AutocompleteEditViewGtk* edit_view, + AutocompleteEditModel* edit_model, + Profile* profile); + ~AutocompletePopupViewGtk(); + + // Implement the AutocompletePopupView interface. + virtual bool IsOpen() const { return opened_; } + virtual void InvalidateLine(size_t line); + virtual void UpdatePopupAppearance(); + virtual void OnHoverEnabledOrDisabled(bool disabled); + virtual void PaintUpdatesNow(); + + AutocompletePopupModel* model() { return model_.get(); } + + private: + void Show(); + void Hide(); + + scoped_ptr<AutocompletePopupModel> model_; + AutocompleteEditViewGtk* edit_view_; + + GtkWidget* window_; + GtkWidget* vbox_; + + bool opened_; + + DISALLOW_COPY_AND_ASSIGN(AutocompletePopupViewGtk); +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_ diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 0e6e74d..7c820b4 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -736,6 +736,8 @@ if not env.Bit('windows'): if env.Bit('linux'): input_files.Extend([ + 'autocomplete/autocomplete_edit_view_gtk.cc', + 'autocomplete/autocomplete_popup_view_gtk.cc', 'browser_main_gtk.cc', 'gtk/back_forward_menu_model_gtk.cc', 'gtk/browser_toolbar_gtk.cc', @@ -744,6 +746,7 @@ if env.Bit('linux'): 'gtk/custom_button.cc', 'gtk/download_item_gtk.cc', 'gtk/download_shelf_gtk.cc', + 'gtk/location_bar_view_gtk.cc', 'gtk/menu_gtk.cc', 'gtk/nine_box.cc', 'gtk/standard_menus.cc', diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index b218beb..c51d27d 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -11,8 +11,9 @@ #include "base/path_service.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser.h" -#include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/back_forward_menu_model_gtk.h" +#include "chrome/browser/gtk/custom_button.h" +#include "chrome/browser/gtk/location_bar_view_gtk.h" #include "chrome/browser/gtk/standard_menus.h" #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/common/l10n_util.h" @@ -21,17 +22,19 @@ #include "grit/generated_resources.h" #include "grit/theme_resources.h" -// TODO(deanm): Remove this when the LocationBarView is used. -class LocationBar; - const int BrowserToolbarGtk::kToolbarHeight = 38; // For the back/forward dropdown menus, the time in milliseconds between // when the user clicks and the popup menu appears. static const int kMenuTimerDelay = 500; +static void OnGrabFocusThunk(GtkWidget* toolbar, gpointer self) { + reinterpret_cast<BrowserToolbarGtk*>(self)->FocusLocationBar(); +} + BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser) : toolbar_(NULL), - entry_(NULL), + location_bar_(new LocationBarViewGtk(browser->command_updater(), + browser->toolbar_model())), model_(browser->toolbar_model()), browser_(browser), profile_(NULL), @@ -52,6 +55,9 @@ BrowserToolbarGtk::~BrowserToolbarGtk() { } void BrowserToolbarGtk::Init(Profile* profile, GtkAccelGroup* accel_group) { + // Make sure to tell the location bar the profile before calling its Init. + SetProfile(profile); + accel_group_ = accel_group; show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this); @@ -89,22 +95,17 @@ void BrowserToolbarGtk::Init(Profile* profile, GtkAccelGroup* accel_group) { star_.reset(BuildToolbarButton(IDR_STAR, IDR_STAR_P, IDR_STAR_H, IDR_STAR_D, l10n_util::GetString(IDS_TOOLTIP_STAR))); - entry_ = gtk_entry_new(); - gtk_widget_set_size_request(entry_, 0, 27); - g_signal_connect(G_OBJECT(entry_), "activate", - G_CALLBACK(OnEntryActivate), this); - g_signal_connect(G_OBJECT(entry_), "focus", - G_CALLBACK(OnEntryFocus), this); - g_signal_connect(G_OBJECT(entry_), "focus-in-event", - G_CALLBACK(OnEntryFocusIn), this); - g_signal_connect(G_OBJECT(entry_), "focus-out-event", - G_CALLBACK(OnEntryFocusOut), this); + location_bar_->Init(); + gtk_box_pack_start(GTK_BOX(toolbar_), location_bar_->widget(), TRUE, TRUE, 0); + + // We listen for ctrl-l which we have send a grab-focus action to the + // toolbar. We want our callback to just call FocusLocationBar(). + g_signal_connect(toolbar_, "grab-focus", + G_CALLBACK(OnGrabFocusThunk), this); gtk_widget_add_accelerator( - entry_, "grab-focus", accel_group_, GDK_l, + toolbar_, "grab-focus", accel_group_, GDK_l, GDK_CONTROL_MASK, GtkAccelFlags(0)); - gtk_box_pack_start(GTK_BOX(toolbar_), entry_, TRUE, TRUE, 0); - go_.reset(BuildToolbarButton(IDR_GO, IDR_GO_P, IDR_GO_H, 0, L"")); gtk_box_pack_start(GTK_BOX(toolbar_), gtk_label_new(" "), FALSE, FALSE, 0); @@ -117,8 +118,6 @@ void BrowserToolbarGtk::Init(Profile* profile, GtkAccelGroup* accel_group) { l10n_util::GetStringF(IDS_APPMENU_TOOLTIP, l10n_util::GetString(IDS_PRODUCT_NAME)))); app_menu_.reset(new MenuGtk(this, GetStandardAppMenu(), accel_group_)); - - SetProfile(profile); } void BrowserToolbarGtk::AddToolbarToBox(GtkWidget* box) { @@ -126,12 +125,11 @@ void BrowserToolbarGtk::AddToolbarToBox(GtkWidget* box) { } LocationBar* BrowserToolbarGtk::GetLocationBar() const { - NOTIMPLEMENTED(); - return NULL; + return location_bar_.get(); } void BrowserToolbarGtk::FocusLocationBar() { - gtk_widget_grab_focus(entry_); + location_bar_->FocusLocation(); } void BrowserToolbarGtk::EnabledStateChangedForCommand(int id, bool enabled) { @@ -195,16 +193,12 @@ void BrowserToolbarGtk::SetProfile(Profile* profile) { return; profile_ = profile; - // TODO(erg): location_bar_ is a normal gtk text box right now. Change this - // when we get omnibox support. - // location_bar_->SetProfile(profile); + location_bar_->SetProfile(profile); } void BrowserToolbarGtk::UpdateTabContents(TabContents* contents, bool should_restore_state) { - // Extract the UTF-8 representation of the URL. - gtk_entry_set_text(GTK_ENTRY(entry_), - contents->GetURL().possibly_invalid_spec().c_str()); + location_bar_->Update(should_restore_state ? contents : NULL); } CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton( @@ -249,45 +243,6 @@ CustomContainerButton* BrowserToolbarGtk::BuildToolbarMenuButton( } // static -void BrowserToolbarGtk::OnEntryActivate(GtkEntry *entry, - BrowserToolbarGtk* toolbar) { - GURL dest(URLFixerUpper::FixupURL(std::string(gtk_entry_get_text(entry)), - std::string())); - toolbar->browser_->GetSelectedTabContents()-> - OpenURL(dest, GURL(), CURRENT_TAB, PageTransition::TYPED); -} - -// static -gboolean BrowserToolbarGtk::OnEntryFocus(GtkWidget* widget, - GtkDirectionType direction, - BrowserToolbarGtk* host) { - if (!GTK_WIDGET_HAS_FOCUS(widget)) { - gtk_widget_grab_focus(widget); - return TRUE; - } - - return FALSE; -} - -// static -gboolean BrowserToolbarGtk::OnEntryFocusIn(GtkWidget* widget, - GdkEventFocus* focus, - BrowserToolbarGtk* host) { - // Set the caret at the end of the text. - gtk_editable_set_position(GTK_EDITABLE(widget), -1); - return FALSE; -} - -// static -gboolean BrowserToolbarGtk::OnEntryFocusOut(GtkWidget* widget, - GdkEventFocus* focus, - BrowserToolbarGtk* host) { - // Clear the selected text (if any). - gtk_editable_set_position(GTK_EDITABLE(widget), 0); - return FALSE; -} - -// static void BrowserToolbarGtk::OnButtonClick(GtkWidget* button, BrowserToolbarGtk* toolbar) { int tag = -1; diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index c943db4..9e854fd 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -19,6 +19,7 @@ class Browser; class CustomContainerButton; class CustomDrawButton; class LocationBar; +class LocationBarViewGtk; class Profile; class TabContents; class ToolbarModel; @@ -83,25 +84,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, unsigned int accelerator, unsigned int accelerator_mod); - // Gtk callback for the "activate" signal on the |entry_| widget. Responds to - // enter. - static void OnEntryActivate(GtkEntry *entry, BrowserToolbarGtk* toolbar); - - // Gtk callback for the "focus" signal on the |entry_| widget. - static gboolean OnEntryFocus(GtkWidget* widget, - GtkDirectionType direction, - BrowserToolbarGtk* host); - - // Gtk callback for the "focus-in" signal on the |entry_| widget. - static gboolean OnEntryFocusIn(GtkWidget* widget, - GdkEventFocus* focus, - BrowserToolbarGtk* host); - - // Gtk callback for the "focus-out" signal on the |entry_| widget. - static gboolean OnEntryFocusOut(GtkWidget* widget, - GdkEventFocus* focus, - BrowserToolbarGtk* host); - // Gtk callback for the "clicked" signal. static void OnButtonClick(GtkWidget* button, BrowserToolbarGtk* toolbar); @@ -126,8 +108,8 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, // Tooltip container for all GTK widgets in this class. GtkTooltips* toolbar_tooltips_; - // Our temporary URL bar (until we get the omnibox up). - GtkWidget* entry_; + // The location bar view. + scoped_ptr<LocationBarViewGtk> location_bar_; // A pointer to our window's accelerator list. GtkAccelGroup* accel_group_; diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc new file mode 100644 index 0000000..4e97032 --- /dev/null +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -0,0 +1,143 @@ +#include "chrome/browser/gtk/location_bar_view_gtk.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/alternate_nav_url_fetcher.h" +#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" +#include "chrome/browser/command_updater.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/page_transition_types.h" +#include "skia/include/SkBitmap.h" +#include "webkit/glue/window_open_disposition.h" + +LocationBarViewGtk::LocationBarViewGtk(CommandUpdater* command_updater, + ToolbarModel* toolbar_model) + : vbox_(NULL), + profile_(NULL), + command_updater_(command_updater), + toolbar_model_(toolbar_model), + disposition_(CURRENT_TAB), + transition_(PageTransition::TYPED) { +} + +LocationBarViewGtk::~LocationBarViewGtk(){ + // TODO(deanm): Should I destroy the widgets here, or leave it up to the + // embedder? When the embedder destroys their widget, if we're a child, we + // will also get destroyed, so the ownership is kinda unclear. +} + +void LocationBarViewGtk::Init(){ + edit_view_.reset(new AutocompleteEditViewGtk(this, toolbar_model_, profile_, + command_updater_)); + edit_view_->Init(); + + vbox_ = gtk_vbox_new(false, 0); + + // Get the location bar to fit nicely in the toolbar, kinda ugly. + static const int kTopPadding = 2; + static const int kBottomPadding = 3; + GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), + kTopPadding, kBottomPadding, 0, 0); + gtk_container_add(GTK_CONTAINER(alignment), edit_view_->widget()); + + gtk_box_pack_start(GTK_BOX(vbox_), alignment, TRUE, TRUE, 0); +} + +void LocationBarViewGtk::SetProfile(Profile* profile) { + profile_ = profile; +} + +void LocationBarViewGtk::Update(const TabContents* contents) { + edit_view_->Update(contents); +} + +void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url) { + if (!url.is_valid()) + return; + + location_input_ = UTF8ToWide(url.spec()); + disposition_ = disposition; + transition_ = transition; + + if (!command_updater_) + return; + + if (!alternate_nav_url.is_valid()) { + command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL); + return; + } + + scoped_ptr<AlternateNavURLFetcher> fetcher( + new AlternateNavURLFetcher(alternate_nav_url)); + // The AlternateNavURLFetcher will listen for the pending navigation + // notification that will be issued as a result of the "open URL." It + // will automatically install itself into that navigation controller. + command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL); + if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) { + // I'm not sure this should be reachable, but I'm not also sure enough + // that it shouldn't to stick in a NOTREACHED(). In any case, this is + // harmless; we can simply let the fetcher get deleted here and it will + // clean itself up properly. + } else { + fetcher.release(); // The navigation controller will delete the fetcher. + } +} + +void LocationBarViewGtk::OnChanged() { + // TODO(deanm): Here is where we would do layout when we have things like + // the keyword display, ssl icons, etc. +} + +void LocationBarViewGtk::OnInputInProgress(bool in_progress) { + NOTIMPLEMENTED(); +} + +SkBitmap LocationBarViewGtk::GetFavIcon() const { + NOTIMPLEMENTED(); + return SkBitmap(); +} + +std::wstring LocationBarViewGtk::GetTitle() const { + NOTIMPLEMENTED(); + return std::wstring(); +} + +void LocationBarViewGtk::ShowFirstRunBubble(){ + NOTIMPLEMENTED(); +} + +std::wstring LocationBarViewGtk::GetInputString() const{ + return location_input_; +} + +WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const{ + return disposition_; +} + +PageTransition::Type LocationBarViewGtk::GetPageTransition() const{ + return transition_; +} + +void LocationBarViewGtk::AcceptInput(){ + NOTIMPLEMENTED(); +} + +void LocationBarViewGtk::FocusLocation(){ + edit_view_->FocusLocation(); +} + +void LocationBarViewGtk::FocusSearch(){ + NOTIMPLEMENTED(); +} + +void LocationBarViewGtk::SaveStateToContents(TabContents* contents){ + NOTIMPLEMENTED(); +} diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h new file mode 100644 index 0000000..50b0775 --- /dev/null +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -0,0 +1,88 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_ +#define CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_ + +#include <gtk/gtk.h> + +#include <string> + +#include "base/basictypes.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/location_bar.h" +#include "chrome/common/page_transition_types.h" +#include "webkit/glue/window_open_disposition.h" + +class AutocompleteEditViewGtk; +class CommandUpdater; +class Profile; +class SkBitmap; +class TabContents; +class ToolbarModel; + +class LocationBarViewGtk : public AutocompleteEditController, + public LocationBar { + public: + LocationBarViewGtk(CommandUpdater* command_updater, + ToolbarModel* toolbar_model); + ~LocationBarViewGtk(); + + void Init(); + + void SetProfile(Profile* profile); + + // Return the native vbox widget. You must call Init() first, or the result + // will be NULL. This is the widget that an embedder should host. + GtkWidget* widget() { return vbox_; } + + // Updates the location bar. We also reset the bar's permanent text and + // security style, and, if |tab_for_state_restoring| is non-NULL, also + // restore saved state that the tab holds. + void Update(const TabContents* tab_for_state_restoring); + + // Implement the AutocompleteEditController interface. + virtual void OnAutocompleteAccept(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url); + virtual void OnChanged(); + virtual void OnInputInProgress(bool in_progress); + virtual SkBitmap GetFavIcon() const; + virtual std::wstring GetTitle() const; + + // Implement the LocationBar interface. + virtual void ShowFirstRunBubble(); + virtual std::wstring GetInputString() const; + virtual WindowOpenDisposition GetWindowOpenDisposition() const; + virtual PageTransition::Type GetPageTransition() const; + virtual void AcceptInput(); + virtual void FocusLocation(); + virtual void FocusSearch(); + virtual void SaveStateToContents(TabContents* contents); + + private: + GtkWidget* vbox_; + + scoped_ptr<AutocompleteEditViewGtk> edit_view_; + + Profile* profile_; + CommandUpdater* command_updater_; + ToolbarModel* toolbar_model_; + + // When we get an OnAutocompleteAccept notification from the autocomplete + // edit, we save the input string so we can give it back to the browser on + // the LocationBar interface via GetInputString(). + std::wstring location_input_; + + // The user's desired disposition for how their input should be opened + WindowOpenDisposition disposition_; + + // The transition type to use for the navigation + PageTransition::Type transition_; + + DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk); +}; + +#endif // CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_ |