| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/autocomplete/autocomplete_popup_view_gtk.h" | 5 #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "app/resource_bundle.h" | 12 #include "app/resource_bundle.h" |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/stl_util-inl.h" |
| 16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete.h" | 18 #include "chrome/browser/autocomplete/autocomplete.h" |
| 18 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 19 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
| 19 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" | 20 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" |
| 20 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 21 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
| 21 #include "chrome/browser/defaults.h" | 22 #include "chrome/browser/defaults.h" |
| 22 #include "chrome/browser/gtk/gtk_theme_provider.h" | 23 #include "chrome/browser/gtk/gtk_theme_provider.h" |
| 23 #include "chrome/browser/gtk/gtk_util.h" | 24 #include "chrome/browser/gtk/gtk_util.h" |
| 24 #include "chrome/browser/profile.h" | 25 #include "chrome/browser/profile.h" |
| 25 #include "chrome/browser/search_engines/template_url.h" | 26 #include "chrome/browser/search_engines/template_url.h" |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 PangoAttribute* weight_attr = pango_attr_weight_new(weight); | 190 PangoAttribute* weight_attr = pango_attr_weight_new(weight); |
| 190 weight_attr->start_index = offset; | 191 weight_attr->start_index = offset; |
| 191 pango_attr_list_insert(attrs, weight_attr); // Ownership taken. | 192 pango_attr_list_insert(attrs, weight_attr); // Ownership taken. |
| 192 } | 193 } |
| 193 | 194 |
| 194 pango_layout_set_text(layout, text_utf8.data(), text_utf8.size()); | 195 pango_layout_set_text(layout, text_utf8.data(), text_utf8.size()); |
| 195 pango_layout_set_attributes(layout, attrs); // Ref taken. | 196 pango_layout_set_attributes(layout, attrs); // Ref taken. |
| 196 pango_attr_list_unref(attrs); | 197 pango_attr_list_unref(attrs); |
| 197 } | 198 } |
| 198 | 199 |
| 199 GdkPixbuf* IconForMatch(BrowserThemeProvider* theme, | |
| 200 const AutocompleteMatch& match, | |
| 201 bool selected) { | |
| 202 int icon = match.starred ? | |
| 203 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); | |
| 204 if (selected) { | |
| 205 switch (icon) { | |
| 206 case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break; | |
| 207 case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break; | |
| 208 case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break; | |
| 209 case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break; | |
| 210 case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break; | |
| 211 default: NOTREACHED(); break; | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 // TODO(estade): Do we want to flip these for RTL? (Windows doesn't). | |
| 216 return theme->GetPixbufNamed(icon); | |
| 217 } | |
| 218 | |
| 219 // Generates the normal URL color, a green color used in unhighlighted URL | 200 // Generates the normal URL color, a green color used in unhighlighted URL |
| 220 // text. It is a mix of |kURLTextColor| and the current text color. Unlike the | 201 // text. It is a mix of |kURLTextColor| and the current text color. Unlike the |
| 221 // selected text color, It is more important to match the qualities of the | 202 // selected text color, It is more important to match the qualities of the |
| 222 // foreground typeface color instead of taking the background into account. | 203 // foreground typeface color instead of taking the background into account. |
| 223 GdkColor NormalURLColor(GdkColor foreground) { | 204 GdkColor NormalURLColor(GdkColor foreground) { |
| 224 color_utils::HSL fg_hsl; | 205 color_utils::HSL fg_hsl; |
| 225 color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl); | 206 color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl); |
| 226 | 207 |
| 227 color_utils::HSL hue_hsl; | 208 color_utils::HSL hue_hsl; |
| 228 color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl); | 209 color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // on. http://crbug.com/22015. | 326 // on. http://crbug.com/22015. |
| 346 } | 327 } |
| 347 | 328 |
| 348 AutocompletePopupViewGtk::~AutocompletePopupViewGtk() { | 329 AutocompletePopupViewGtk::~AutocompletePopupViewGtk() { |
| 349 // Explicitly destroy our model here, before we destroy our GTK widgets. | 330 // Explicitly destroy our model here, before we destroy our GTK widgets. |
| 350 // This is because the model destructor can call back into us, and we need | 331 // This is because the model destructor can call back into us, and we need |
| 351 // to make sure everything is still valid when it does. | 332 // to make sure everything is still valid when it does. |
| 352 model_.reset(); | 333 model_.reset(); |
| 353 g_object_unref(layout_); | 334 g_object_unref(layout_); |
| 354 gtk_widget_destroy(window_); | 335 gtk_widget_destroy(window_); |
| 336 |
| 337 for (PixbufMap::iterator it = pixbufs_.begin(); it != pixbufs_.end(); ++it) |
| 338 g_object_unref(it->second); |
| 355 } | 339 } |
| 356 | 340 |
| 357 void AutocompletePopupViewGtk::InvalidateLine(size_t line) { | 341 void AutocompletePopupViewGtk::InvalidateLine(size_t line) { |
| 358 // TODO(deanm): Is it possible to use some constant for the width, instead | 342 // TODO(deanm): Is it possible to use some constant for the width, instead |
| 359 // of having to query the width of the window? | 343 // of having to query the width of the window? |
| 360 GdkRectangle line_rect = GetRectForLine( | 344 GdkRectangle line_rect = GetRectForLine( |
| 361 line, GetWindowRect(window_->window).width()).ToGdkRectangle(); | 345 line, GetWindowRect(window_->window).width()).ToGdkRectangle(); |
| 362 gdk_window_invalidate_rect(window_->window, &line_rect, FALSE); | 346 gdk_window_invalidate_rect(window_->window, &line_rect, FALSE); |
| 363 } | 347 } |
| 364 | 348 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 // OpenURL() may close the popup, which will clear the result set and, by | 475 // OpenURL() may close the popup, which will clear the result set and, by |
| 492 // extension, |match| and its contents. So copy the relevant strings out to | 476 // extension, |match| and its contents. So copy the relevant strings out to |
| 493 // make sure they stay alive until the call completes. | 477 // make sure they stay alive until the call completes. |
| 494 const GURL url(match.destination_url); | 478 const GURL url(match.destination_url); |
| 495 std::wstring keyword; | 479 std::wstring keyword; |
| 496 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); | 480 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); |
| 497 edit_view_->OpenURL(url, disposition, match.transition, GURL(), line, | 481 edit_view_->OpenURL(url, disposition, match.transition, GURL(), line, |
| 498 is_keyword_hint ? std::wstring() : keyword); | 482 is_keyword_hint ? std::wstring() : keyword); |
| 499 } | 483 } |
| 500 | 484 |
| 485 GdkPixbuf* AutocompletePopupViewGtk::IconForMatch( |
| 486 const AutocompleteMatch& match, bool selected) { |
| 487 const SkBitmap* bitmap = model_->GetSpecialIconForMatch(match); |
| 488 if (bitmap) { |
| 489 if (!ContainsKey(pixbufs_, bitmap)) |
| 490 pixbufs_[bitmap] = gfx::GdkPixbufFromSkBitmap(bitmap); |
| 491 return pixbufs_[bitmap]; |
| 492 } |
| 493 |
| 494 int icon = match.starred ? |
| 495 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); |
| 496 if (selected) { |
| 497 switch (icon) { |
| 498 case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break; |
| 499 case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break; |
| 500 case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break; |
| 501 case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break; |
| 502 case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break; |
| 503 default: NOTREACHED(); break; |
| 504 } |
| 505 } |
| 506 |
| 507 // TODO(estade): Do we want to flip these for RTL? (Windows doesn't). |
| 508 return theme_provider_->GetPixbufNamed(icon); |
| 509 } |
| 510 |
| 501 gboolean AutocompletePopupViewGtk::HandleMotion(GtkWidget* widget, | 511 gboolean AutocompletePopupViewGtk::HandleMotion(GtkWidget* widget, |
| 502 GdkEventMotion* event) { | 512 GdkEventMotion* event) { |
| 503 // TODO(deanm): Windows has a bunch of complicated logic here. | 513 // TODO(deanm): Windows has a bunch of complicated logic here. |
| 504 size_t line = LineFromY(static_cast<int>(event->y)); | 514 size_t line = LineFromY(static_cast<int>(event->y)); |
| 505 // There is both a hovered and selected line, hovered just means your mouse | 515 // There is both a hovered and selected line, hovered just means your mouse |
| 506 // is over it, but selected is what's showing in the location edit. | 516 // is over it, but selected is what's showing in the location edit. |
| 507 model_->SetHoveredLine(line); | 517 model_->SetHoveredLine(line); |
| 508 // Select the line if the user has the left mouse button down. | 518 // Select the line if the user has the left mouse button down. |
| 509 if (!ignore_mouse_drag_ && (event->state & GDK_BUTTON1_MASK)) | 519 if (!ignore_mouse_drag_ && (event->state & GDK_BUTTON1_MASK)) |
| 510 model_->SetSelectedLine(line, false); | 520 model_->SetSelectedLine(line, false); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 // This entry is selected or hovered, fill a rect with the color. | 613 // This entry is selected or hovered, fill a rect with the color. |
| 604 gdk_draw_rectangle(drawable, gc, TRUE, | 614 gdk_draw_rectangle(drawable, gc, TRUE, |
| 605 line_rect.x(), line_rect.y(), | 615 line_rect.x(), line_rect.y(), |
| 606 line_rect.width(), line_rect.height()); | 616 line_rect.width(), line_rect.height()); |
| 607 } | 617 } |
| 608 | 618 |
| 609 int icon_start_x = ltr ? (kIconLeftPadding - gtk_offset) : | 619 int icon_start_x = ltr ? (kIconLeftPadding - gtk_offset) : |
| 610 (line_rect.width() - kIconLeftPadding - kIconWidth + gtk_offset); | 620 (line_rect.width() - kIconLeftPadding - kIconWidth + gtk_offset); |
| 611 // Draw the icon for this result. | 621 // Draw the icon for this result. |
| 612 DrawFullPixbuf(drawable, gc, | 622 DrawFullPixbuf(drawable, gc, |
| 613 IconForMatch(theme_provider_, match, is_selected), | 623 IconForMatch(match, is_selected), |
| 614 icon_start_x, line_rect.y() + kIconTopPadding); | 624 icon_start_x, line_rect.y() + kIconTopPadding); |
| 615 | 625 |
| 616 // Draw the results text vertically centered in the results space. | 626 // Draw the results text vertically centered in the results space. |
| 617 // First draw the contents / url, but don't let it take up the whole width | 627 // First draw the contents / url, but don't let it take up the whole width |
| 618 // if there is also a description to be shown. | 628 // if there is also a description to be shown. |
| 619 bool has_description = !match.description.empty(); | 629 bool has_description = !match.description.empty(); |
| 620 int text_width = window_rect.width() - (kIconAreaWidth + kRightPadding); | 630 int text_width = window_rect.width() - (kIconAreaWidth + kRightPadding); |
| 621 int allocated_content_width = has_description ? | 631 int allocated_content_width = has_description ? |
| 622 static_cast<int>(text_width * kContentWidthPercentage) : text_width; | 632 static_cast<int>(text_width * kContentWidthPercentage) : text_width; |
| 623 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE); | 633 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 (text_width - actual_content_width + gtk_offset - | 672 (text_width - actual_content_width + gtk_offset - |
| 663 (actual_description_width / PANGO_SCALE)), | 673 (actual_description_width / PANGO_SCALE)), |
| 664 content_y, layout_); | 674 content_y, layout_); |
| 665 } | 675 } |
| 666 } | 676 } |
| 667 | 677 |
| 668 g_object_unref(gc); | 678 g_object_unref(gc); |
| 669 | 679 |
| 670 return TRUE; | 680 return TRUE; |
| 671 } | 681 } |
| OLD | NEW |