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

Side by Side Diff: chrome/browser/ui/gtk/omnibox/omnibox_popup_view_gtk.cc

Issue 22679003: InstantExtended(gtk): Hide top match if told to so. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 7 years, 3 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_popup_view_gtk.h" 5 #include "chrome/browser/ui/gtk/omnibox/omnibox_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>
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 // UTF-8 Left-to-right embedding. 90 // UTF-8 Left-to-right embedding.
91 const char* kLRE = "\xe2\x80\xaa"; 91 const char* kLRE = "\xe2\x80\xaa";
92 92
93 // Return a Rect covering the whole area of |window|. 93 // Return a Rect covering the whole area of |window|.
94 gfx::Rect GetWindowRect(GdkWindow* window) { 94 gfx::Rect GetWindowRect(GdkWindow* window) {
95 gint width = gdk_window_get_width(window); 95 gint width = gdk_window_get_width(window);
96 gint height = gdk_window_get_height(window); 96 gint height = gdk_window_get_height(window);
97 return gfx::Rect(width, height); 97 return gfx::Rect(width, height);
98 } 98 }
99 99
100 // Return a Rect for the space for a result line. This excludes the border,
101 // but includes the padding. This is the area that is colored for a selection.
102 gfx::Rect GetRectForLine(size_t line, int width) {
103 return gfx::Rect(kBorderThickness,
104 (line * kHeightPerResult) + kBorderThickness,
105 width - (kBorderThickness * 2),
106 kHeightPerResult);
107 }
108
109 // TODO(deanm): Find some better home for this, and make it more efficient. 100 // TODO(deanm): Find some better home for this, and make it more efficient.
110 size_t GetUTF8Offset(const string16& text, size_t text_offset) { 101 size_t GetUTF8Offset(const string16& text, size_t text_offset) {
111 return UTF16ToUTF8(text.substr(0, text_offset)).length(); 102 return UTF16ToUTF8(text.substr(0, text_offset)).length();
112 } 103 }
113 104
114 // Generates the normal URL color, a green color used in unhighlighted URL 105 // Generates the normal URL color, a green color used in unhighlighted URL
115 // text. It is a mix of |kURLTextColor| and the current text color. Unlike the 106 // text. It is a mix of |kURLTextColor| and the current text color. Unlike the
116 // selected text color, it is more important to match the qualities of the 107 // selected text color, it is more important to match the qualities of the
117 // foreground typeface color instead of taking the background into account. 108 // foreground typeface color instead of taking the background into account.
118 GdkColor NormalURLColor(GdkColor foreground) { 109 GdkColor NormalURLColor(GdkColor foreground) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 // The luminance should match the luminance of the foreground text. Again, 153 // The luminance should match the luminance of the foreground text. Again,
163 // we clamp so as to have at some amount of color (green) in the text. 154 // we clamp so as to have at some amount of color (green) in the text.
164 double opposite_l = fg_hsl.l; 155 double opposite_l = fg_hsl.l;
165 double l = std::max(0.1, std::min(0.9, opposite_l)); 156 double l = std::max(0.1, std::min(0.9, opposite_l));
166 157
167 color_utils::HSL output = { hue_hsl.h, s, l }; 158 color_utils::HSL output = { hue_hsl.h, s, l };
168 return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255)); 159 return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255));
169 } 160 }
170 } // namespace 161 } // namespace
171 162
172 void OmniboxPopupViewGtk::SetupLayoutForMatch(
173 PangoLayout* layout,
174 const string16& text,
175 const AutocompleteMatch::ACMatchClassifications& classifications,
176 const GdkColor* base_color,
177 const GdkColor* dim_color,
178 const GdkColor* url_color,
179 const std::string& prefix_text) {
180 // In RTL, mark text with left-to-right embedding mark if there is no strong
181 // RTL characters inside it, so the ending punctuation displays correctly
182 // and the eliding ellipsis displays correctly. We only mark the text with
183 // LRE. Wrapping it with LRE and PDF by calling AdjustStringForLocaleDirection
184 // or WrapStringWithLTRFormatting will render the elllipsis at the left of the
185 // elided pure LTR text.
186 bool marked_with_lre = false;
187 string16 localized_text = text;
188 // Pango is really easy to overflow and send into a computational death
189 // spiral that can corrupt the screen. Assume that we'll never have more than
190 // 2000 characters, which should be a safe assumption until we all get robot
191 // eyes. http://crbug.com/66576
192 if (localized_text.length() > 2000)
193 localized_text = localized_text.substr(0, 2000);
194 bool is_rtl = base::i18n::IsRTL();
195 if (is_rtl && !base::i18n::StringContainsStrongRTLChars(localized_text)) {
196 localized_text.insert(0, 1, base::i18n::kLeftToRightEmbeddingMark);
197 marked_with_lre = true;
198 }
199
200 // We can have a prefix, or insert additional characters while processing the
201 // classifications. We need to take this in to account when we translate the
202 // UTF-16 offsets in the classification into text_utf8 byte offsets.
203 size_t additional_offset = prefix_text.length(); // Length in utf-8 bytes.
204 std::string text_utf8 = prefix_text + UTF16ToUTF8(localized_text);
205
206 PangoAttrList* attrs = pango_attr_list_new();
207
208 // TODO(deanm): This is a hack, just to handle coloring prefix_text.
209 // Hopefully I can clean up the match situation a bit and this will
210 // come out cleaner. For now, apply the base color to the whole text
211 // so that our prefix will have the base color applied.
212 PangoAttribute* base_fg_attr = pango_attr_foreground_new(
213 base_color->red, base_color->green, base_color->blue);
214 pango_attr_list_insert(attrs, base_fg_attr); // Ownership taken.
215
216 // Walk through the classifications, they are linear, in order, and should
217 // cover the entire text. We create a bunch of overlapping attributes,
218 // extending from the offset to the end of the string. The ones created
219 // later will override the previous ones, meaning we will still setup each
220 // portion correctly, we just don't need to compute the end offset.
221 for (ACMatchClassifications::const_iterator i = classifications.begin();
222 i != classifications.end(); ++i) {
223 size_t offset = GetUTF8Offset(localized_text, i->offset) +
224 additional_offset;
225
226 // TODO(deanm): All the colors should probably blend based on whether this
227 // result is selected or not. This would include the green URLs. Right
228 // now the caller is left to blend only the base color. Do we need to
229 // handle things like DIM urls? Turns out DIM means something different
230 // than you'd think, all of the description text is not DIM, it is a
231 // special case that is not very common, but we should figure out and
232 // support it.
233 const GdkColor* color = base_color;
234 if (i->style & ACMatchClassification::URL) {
235 color = url_color;
236 // Insert a left to right embedding to make sure that URLs are shown LTR.
237 if (is_rtl && !marked_with_lre) {
238 std::string lre(kLRE);
239 text_utf8.insert(offset, lre);
240 additional_offset += lre.length();
241 }
242 }
243
244 if (i->style & ACMatchClassification::DIM)
245 color = dim_color;
246
247 PangoAttribute* fg_attr = pango_attr_foreground_new(
248 color->red, color->green, color->blue);
249 fg_attr->start_index = offset;
250 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
251
252 // Matched portions are bold, otherwise use the normal weight.
253 PangoWeight weight = (i->style & ACMatchClassification::MATCH) ?
254 PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
255 PangoAttribute* weight_attr = pango_attr_weight_new(weight);
256 weight_attr->start_index = offset;
257 pango_attr_list_insert(attrs, weight_attr); // Ownership taken.
258 }
259
260 pango_layout_set_text(layout, text_utf8.data(), text_utf8.length());
261 pango_layout_set_attributes(layout, attrs); // Ref taken.
262 pango_attr_list_unref(attrs);
263 }
264
265 OmniboxPopupViewGtk::OmniboxPopupViewGtk(const gfx::Font& font, 163 OmniboxPopupViewGtk::OmniboxPopupViewGtk(const gfx::Font& font,
266 OmniboxView* omnibox_view, 164 OmniboxView* omnibox_view,
267 OmniboxEditModel* edit_model, 165 OmniboxEditModel* edit_model,
268 GtkWidget* location_bar) 166 GtkWidget* location_bar)
269 : model_(new OmniboxPopupModel(this, edit_model)), 167 : omnibox_view_(omnibox_view),
270 omnibox_view_(omnibox_view),
271 location_bar_(location_bar), 168 location_bar_(location_bar),
272 window_(gtk_window_new(GTK_WINDOW_POPUP)), 169 window_(gtk_window_new(GTK_WINDOW_POPUP)),
273 layout_(NULL), 170 layout_(NULL),
274 theme_service_(GtkThemeService::GetFrom(edit_model->profile())), 171 theme_service_(NULL),
275 font_(font.DeriveFont(kEditFontAdjust)), 172 font_(font.DeriveFont(kEditFontAdjust)),
276 ignore_mouse_drag_(false), 173 ignore_mouse_drag_(false),
277 opened_(false) { 174 opened_(false) {
175 // edit_model may be NULL in unit tests.
176 if (edit_model) {
177 model_.reset(new OmniboxPopupModel(this, edit_model));
178 theme_service_ = GtkThemeService::GetFrom(edit_model->profile());
179 }
180 }
181
182 void OmniboxPopupViewGtk::Init() {
278 gtk_widget_set_can_focus(window_, FALSE); 183 gtk_widget_set_can_focus(window_, FALSE);
279 // Don't allow the window to be resized. This also forces the window to 184 // Don't allow the window to be resized. This also forces the window to
280 // shrink down to the size of its child contents. 185 // shrink down to the size of its child contents.
281 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 186 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
282 gtk_widget_set_app_paintable(window_, TRUE); 187 gtk_widget_set_app_paintable(window_, TRUE);
283 // Have GTK double buffer around the expose signal. 188 // Have GTK double buffer around the expose signal.
284 gtk_widget_set_double_buffered(window_, TRUE); 189 gtk_widget_set_double_buffered(window_, TRUE);
285 190
286 // Cache the layout so we don't have to create it for every expose. If we 191 // Cache the layout so we don't have to create it for every expose. If we
287 // were a real widget we should handle changing directions, but we're not 192 // were a real widget we should handle changing directions, but we're not
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 // r25080 (the original patch that added rounded corners here) should 226 // r25080 (the original patch that added rounded corners here) should
322 // eventually be cherry picked once I know what's going 227 // eventually be cherry picked once I know what's going
323 // on. http://crbug.com/22015. 228 // on. http://crbug.com/22015.
324 } 229 }
325 230
326 OmniboxPopupViewGtk::~OmniboxPopupViewGtk() { 231 OmniboxPopupViewGtk::~OmniboxPopupViewGtk() {
327 // Explicitly destroy our model here, before we destroy our GTK widgets. 232 // Explicitly destroy our model here, before we destroy our GTK widgets.
328 // This is because the model destructor can call back into us, and we need 233 // This is because the model destructor can call back into us, and we need
329 // to make sure everything is still valid when it does. 234 // to make sure everything is still valid when it does.
330 model_.reset(); 235 model_.reset();
331 g_object_unref(layout_); 236 // layout_ may be NULL in unit tests.
332 gtk_widget_destroy(window_); 237 if (layout_) {
238 g_object_unref(layout_);
239 gtk_widget_destroy(window_);
240 }
333 } 241 }
334 242
335 bool OmniboxPopupViewGtk::IsOpen() const { 243 bool OmniboxPopupViewGtk::IsOpen() const {
336 return opened_; 244 return opened_;
337 } 245 }
338 246
339 void OmniboxPopupViewGtk::InvalidateLine(size_t line) { 247 void OmniboxPopupViewGtk::InvalidateLine(size_t line) {
Evan Stade 2013/09/04 23:33:47 perhaps DCHECK_LE(GetHiddenLineCount(), line);
Jered 2013/09/09 16:26:26 I added an if here to return early (this actually
340 // TODO(deanm): Is it possible to use some constant for the width, instead 248 // TODO(deanm): Is it possible to use some constant for the width, instead
341 // of having to query the width of the window? 249 // of having to query the width of the window?
342 GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_)); 250 GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
343 GdkRectangle line_rect = GetRectForLine( 251 GdkRectangle line_rect = GetRectForLine(
344 line, GetWindowRect(gdk_window).width()).ToGdkRectangle(); 252 line, GetWindowRect(gdk_window).width()).ToGdkRectangle();
345 gdk_window_invalidate_rect(gdk_window, &line_rect, FALSE); 253 gdk_window_invalidate_rect(gdk_window, &line_rect, FALSE);
346 } 254 }
347 255
348 void OmniboxPopupViewGtk::UpdatePopupAppearance() { 256 void OmniboxPopupViewGtk::UpdatePopupAppearance() {
349 const AutocompleteResult& result = model_->result(); 257 const AutocompleteResult& result = GetResult();
350 if (result.empty()) { 258 const size_t hidden_matches = GetHiddenMatchCount();
259 if (result.size() <= hidden_matches) {
351 Hide(); 260 Hide();
352 return; 261 return;
353 } 262 }
354 263
355 Show(result.size()); 264 Show(result.size() - hidden_matches);
356 gtk_widget_queue_draw(window_); 265 gtk_widget_queue_draw(window_);
357 } 266 }
358 267
359 gfx::Rect OmniboxPopupViewGtk::GetTargetBounds() { 268 gfx::Rect OmniboxPopupViewGtk::GetTargetBounds() {
360 if (!gtk_widget_get_realized(window_)) 269 if (!gtk_widget_get_realized(window_))
361 return gfx::Rect(); 270 return gfx::Rect();
362 271
363 gfx::Rect retval = ui::GetWidgetScreenBounds(window_); 272 gfx::Rect retval = ui::GetWidgetScreenBounds(window_);
364 273
365 // The widget bounds don't update synchronously so may be out of sync with 274 // The widget bounds don't update synchronously so may be out of sync with
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 gtk_util::AverageColors(content_text_color_, 329 gtk_util::AverageColors(content_text_color_,
421 background_color_); 330 background_color_);
422 selected_content_dim_text_color_ = 331 selected_content_dim_text_color_ =
423 gtk_util::AverageColors(selected_content_text_color_, 332 gtk_util::AverageColors(selected_content_text_color_,
424 selected_background_color_); 333 selected_background_color_);
425 334
426 // Set the background color, so we don't need to paint it manually. 335 // Set the background color, so we don't need to paint it manually.
427 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &background_color_); 336 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &background_color_);
428 } 337 }
429 338
339 size_t OmniboxPopupViewGtk::LineFromY(int y) const {
340 DCHECK_NE(0U, model_->result().size());
341 size_t line = std::max(y - kBorderThickness, 0) / kHeightPerResult;
342 return std::min(line + GetHiddenMatchCount(), GetResult().size() - 1);
343 }
344
345 gfx::Rect OmniboxPopupViewGtk::GetRectForLine(size_t line, int width) const {
346 size_t visible_line = line - GetHiddenMatchCount();
347 return gfx::Rect(kBorderThickness,
348 (visible_line * kHeightPerResult) + kBorderThickness,
349 width - (kBorderThickness * 2),
350 kHeightPerResult);
351 }
352
353 size_t OmniboxPopupViewGtk::GetHiddenMatchCount() const {
354 return GetResult().ShouldHideTopMatch() ? 1 : 0;
355 }
356
357 const AutocompleteResult& OmniboxPopupViewGtk::GetResult() const {
358 return model_->result();
359 }
360
361 // static
362 void OmniboxPopupViewGtk::SetupLayoutForMatch(
363 PangoLayout* layout,
364 const string16& text,
365 const AutocompleteMatch::ACMatchClassifications& classifications,
366 const GdkColor* base_color,
367 const GdkColor* dim_color,
368 const GdkColor* url_color,
369 const std::string& prefix_text) {
370 // In RTL, mark text with left-to-right embedding mark if there is no strong
371 // RTL characters inside it, so the ending punctuation displays correctly
372 // and the eliding ellipsis displays correctly. We only mark the text with
373 // LRE. Wrapping it with LRE and PDF by calling AdjustStringForLocaleDirection
374 // or WrapStringWithLTRFormatting will render the elllipsis at the left of the
375 // elided pure LTR text.
376 bool marked_with_lre = false;
377 string16 localized_text = text;
378 // Pango is really easy to overflow and send into a computational death
379 // spiral that can corrupt the screen. Assume that we'll never have more than
380 // 2000 characters, which should be a safe assumption until we all get robot
381 // eyes. http://crbug.com/66576
382 if (localized_text.length() > 2000)
383 localized_text = localized_text.substr(0, 2000);
384 bool is_rtl = base::i18n::IsRTL();
385 if (is_rtl && !base::i18n::StringContainsStrongRTLChars(localized_text)) {
386 localized_text.insert(0, 1, base::i18n::kLeftToRightEmbeddingMark);
387 marked_with_lre = true;
388 }
389
390 // We can have a prefix, or insert additional characters while processing the
391 // classifications. We need to take this in to account when we translate the
392 // UTF-16 offsets in the classification into text_utf8 byte offsets.
393 size_t additional_offset = prefix_text.length(); // Length in utf-8 bytes.
394 std::string text_utf8 = prefix_text + UTF16ToUTF8(localized_text);
395
396 PangoAttrList* attrs = pango_attr_list_new();
397
398 // TODO(deanm): This is a hack, just to handle coloring prefix_text.
399 // Hopefully I can clean up the match situation a bit and this will
400 // come out cleaner. For now, apply the base color to the whole text
401 // so that our prefix will have the base color applied.
402 PangoAttribute* base_fg_attr = pango_attr_foreground_new(
403 base_color->red, base_color->green, base_color->blue);
404 pango_attr_list_insert(attrs, base_fg_attr); // Ownership taken.
405
406 // Walk through the classifications, they are linear, in order, and should
407 // cover the entire text. We create a bunch of overlapping attributes,
408 // extending from the offset to the end of the string. The ones created
409 // later will override the previous ones, meaning we will still setup each
410 // portion correctly, we just don't need to compute the end offset.
411 for (ACMatchClassifications::const_iterator i = classifications.begin();
412 i != classifications.end(); ++i) {
413 size_t offset = GetUTF8Offset(localized_text, i->offset) +
414 additional_offset;
415
416 // TODO(deanm): All the colors should probably blend based on whether this
417 // result is selected or not. This would include the green URLs. Right
418 // now the caller is left to blend only the base color. Do we need to
419 // handle things like DIM urls? Turns out DIM means something different
420 // than you'd think, all of the description text is not DIM, it is a
421 // special case that is not very common, but we should figure out and
422 // support it.
423 const GdkColor* color = base_color;
424 if (i->style & ACMatchClassification::URL) {
425 color = url_color;
426 // Insert a left to right embedding to make sure that URLs are shown LTR.
427 if (is_rtl && !marked_with_lre) {
428 std::string lre(kLRE);
429 text_utf8.insert(offset, lre);
430 additional_offset += lre.length();
431 }
432 }
433
434 if (i->style & ACMatchClassification::DIM)
435 color = dim_color;
436
437 PangoAttribute* fg_attr = pango_attr_foreground_new(
438 color->red, color->green, color->blue);
439 fg_attr->start_index = offset;
440 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
441
442 // Matched portions are bold, otherwise use the normal weight.
443 PangoWeight weight = (i->style & ACMatchClassification::MATCH) ?
444 PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
445 PangoAttribute* weight_attr = pango_attr_weight_new(weight);
446 weight_attr->start_index = offset;
447 pango_attr_list_insert(attrs, weight_attr); // Ownership taken.
448 }
449
450 pango_layout_set_text(layout, text_utf8.data(), text_utf8.length());
451 pango_layout_set_attributes(layout, attrs); // Ref taken.
452 pango_attr_list_unref(attrs);
453 }
454
430 void OmniboxPopupViewGtk::Show(size_t num_results) { 455 void OmniboxPopupViewGtk::Show(size_t num_results) {
431 gint origin_x, origin_y; 456 gint origin_x, origin_y;
432 GdkWindow* gdk_window = gtk_widget_get_window(location_bar_); 457 GdkWindow* gdk_window = gtk_widget_get_window(location_bar_);
433 gdk_window_get_origin(gdk_window, &origin_x, &origin_y); 458 gdk_window_get_origin(gdk_window, &origin_x, &origin_y);
434 GtkAllocation allocation; 459 GtkAllocation allocation;
435 gtk_widget_get_allocation(location_bar_, &allocation); 460 gtk_widget_get_allocation(location_bar_, &allocation);
436 461
437 int horizontal_offset = 1; 462 int horizontal_offset = 1;
438 gtk_window_move(GTK_WINDOW(window_), 463 gtk_window_move(GTK_WINDOW(window_),
439 origin_x + allocation.x - kBorderThickness + horizontal_offset, 464 origin_x + allocation.x - kBorderThickness + horizontal_offset,
(...skipping 13 matching lines...) Expand all
453 } 478 }
454 479
455 void OmniboxPopupViewGtk::StackWindow() { 480 void OmniboxPopupViewGtk::StackWindow() {
456 gfx::NativeView omnibox_view = omnibox_view_->GetNativeView(); 481 gfx::NativeView omnibox_view = omnibox_view_->GetNativeView();
457 DCHECK(GTK_IS_WIDGET(omnibox_view)); 482 DCHECK(GTK_IS_WIDGET(omnibox_view));
458 GtkWidget* toplevel = gtk_widget_get_toplevel(omnibox_view); 483 GtkWidget* toplevel = gtk_widget_get_toplevel(omnibox_view);
459 DCHECK(gtk_widget_is_toplevel(toplevel)); 484 DCHECK(gtk_widget_is_toplevel(toplevel));
460 ui::StackPopupWindow(window_, toplevel); 485 ui::StackPopupWindow(window_, toplevel);
461 } 486 }
462 487
463 size_t OmniboxPopupViewGtk::LineFromY(int y) {
464 DCHECK_NE(0U, model_->result().size());
465 size_t line = std::max(y - kBorderThickness, 0) / kHeightPerResult;
466 return std::min(line, model_->result().size() - 1);
467 }
468
469 void OmniboxPopupViewGtk::AcceptLine(size_t line, 488 void OmniboxPopupViewGtk::AcceptLine(size_t line,
470 WindowOpenDisposition disposition) { 489 WindowOpenDisposition disposition) {
471 // OpenMatch() may close the popup, which will clear the result set and, by 490 // OpenMatch() may close the popup, which will clear the result set and, by
472 // extension, |match| and its contents. So copy the relevant match out to 491 // extension, |match| and its contents. So copy the relevant match out to
473 // make sure it stays alive until the call completes. 492 // make sure it stays alive until the call completes.
474 AutocompleteMatch match = model_->result().match_at(line); 493 AutocompleteMatch match = GetResult().match_at(line);
475 omnibox_view_->OpenMatch(match, disposition, GURL(), line); 494 omnibox_view_->OpenMatch(match, disposition, GURL(), line);
476 } 495 }
477 496
478 gfx::Image OmniboxPopupViewGtk::IconForMatch( 497 gfx::Image OmniboxPopupViewGtk::IconForMatch(
479 const AutocompleteMatch& match, 498 const AutocompleteMatch& match,
480 bool selected, 499 bool selected,
481 bool is_selected_keyword) { 500 bool is_selected_keyword) {
482 const gfx::Image image = model_->GetIconIfExtensionMatch(match); 501 const gfx::Image image = model_->GetIconIfExtensionMatch(match);
483 if (!image.IsEmpty()) 502 if (!image.IsEmpty())
484 return image; 503 return image;
(...skipping 29 matching lines...) Expand all
514 } 533 }
515 } 534 }
516 535
517 return theme_service_->GetImageNamed(icon); 536 return theme_service_->GetImageNamed(icon);
518 } 537 }
519 538
520 void OmniboxPopupViewGtk::GetVisibleMatchForInput( 539 void OmniboxPopupViewGtk::GetVisibleMatchForInput(
521 size_t index, 540 size_t index,
522 const AutocompleteMatch** match, 541 const AutocompleteMatch** match,
523 bool* is_selected_keyword) { 542 bool* is_selected_keyword) {
524 const AutocompleteResult& result = model_->result(); 543 const AutocompleteResult& result = GetResult();
525 544
526 if (result.match_at(index).associated_keyword.get() && 545 if (result.match_at(index).associated_keyword.get() &&
527 model_->selected_line() == index && 546 model_->selected_line() == index &&
528 model_->selected_line_state() == OmniboxPopupModel::KEYWORD) { 547 model_->selected_line_state() == OmniboxPopupModel::KEYWORD) {
529 *match = result.match_at(index).associated_keyword.get(); 548 *match = result.match_at(index).associated_keyword.get();
530 *is_selected_keyword = true; 549 *is_selected_keyword = true;
531 return; 550 return;
532 } 551 }
533 552
534 *match = &result.match_at(index); 553 *match = &result.match_at(index);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 default: 606 default:
588 // Don't open the result. 607 // Don't open the result.
589 break; 608 break;
590 } 609 }
591 return TRUE; 610 return TRUE;
592 } 611 }
593 612
594 gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget, 613 gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget,
595 GdkEventExpose* event) { 614 GdkEventExpose* event) {
596 bool ltr = !base::i18n::IsRTL(); 615 bool ltr = !base::i18n::IsRTL();
597 const AutocompleteResult& result = model_->result(); 616 const AutocompleteResult& result = GetResult();
598 617
599 gfx::Rect window_rect = GetWindowRect(event->window); 618 gfx::Rect window_rect = GetWindowRect(event->window);
600 gfx::Rect damage_rect = gfx::Rect(event->area); 619 gfx::Rect damage_rect = gfx::Rect(event->area);
601 // Handle when our window is super narrow. A bunch of the calculations 620 // Handle when our window is super narrow. A bunch of the calculations
602 // below would go negative, and really we're not going to fit anything 621 // below would go negative, and really we're not going to fit anything
603 // useful in such a small window anyway. Just don't paint anything. 622 // useful in such a small window anyway. Just don't paint anything.
604 // This means we won't draw the border, but, yeah, whatever. 623 // This means we won't draw the border, but, yeah, whatever.
605 // TODO(deanm): Make the code more robust and remove this check. 624 // TODO(deanm): Make the code more robust and remove this check.
606 if (window_rect.width() < (kIconAreaWidth * 3)) 625 if (window_rect.width() < (kIconAreaWidth * 3))
607 return TRUE; 626 return TRUE;
608 627
609 cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget)); 628 cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
610 gdk_cairo_rectangle(cr, &event->area); 629 gdk_cairo_rectangle(cr, &event->area);
611 cairo_clip(cr); 630 cairo_clip(cr);
612 631
613 // This assert is kinda ugly, but it would be more currently unneeded work 632 // This assert is kinda ugly, but it would be more currently unneeded work
614 // to support painting a border that isn't 1 pixel thick. There is no point 633 // to support painting a border that isn't 1 pixel thick. There is no point
615 // in writing that code now, and explode if that day ever comes. 634 // in writing that code now, and explode if that day ever comes.
616 COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied); 635 COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied);
617 // Draw the 1px border around the entire window. 636 // Draw the 1px border around the entire window.
618 gdk_cairo_set_source_color(cr, &border_color_); 637 gdk_cairo_set_source_color(cr, &border_color_);
619 cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height()); 638 cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height());
620 cairo_stroke(cr); 639 cairo_stroke(cr);
621 640
622 pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE); 641 pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE);
623 642
624 for (size_t i = 0; i < result.size(); ++i) { 643 for (size_t i = GetHiddenMatchCount(); i < result.size(); ++i) {
625 gfx::Rect line_rect = GetRectForLine(i, window_rect.width()); 644 gfx::Rect line_rect = GetRectForLine(i, window_rect.width());
626 // Only repaint and layout damaged lines. 645 // Only repaint and layout damaged lines.
627 if (!line_rect.Intersects(damage_rect)) 646 if (!line_rect.Intersects(damage_rect))
628 continue; 647 continue;
629 648
630 const AutocompleteMatch* match = NULL; 649 const AutocompleteMatch* match = NULL;
631 bool is_selected_keyword = false; 650 bool is_selected_keyword = false;
632 GetVisibleMatchForInput(i, &match, &is_selected_keyword); 651 GetVisibleMatchForInput(i, &match, &is_selected_keyword);
633 bool is_selected = (model_->selected_line() == i); 652 bool is_selected = (model_->selected_line() == i);
634 bool is_hovered = (model_->hovered_line() == i); 653 bool is_hovered = (model_->hovered_line() == i);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 theme_service_->GetImageNamed( 744 theme_service_->GetImageNamed(
726 is_selected ? IDR_OMNIBOX_TTS_DARK : 745 is_selected ? IDR_OMNIBOX_TTS_DARK :
727 IDR_OMNIBOX_TTS), 746 IDR_OMNIBOX_TTS),
728 icon_start_x, line_rect.y() + kIconTopPadding); 747 icon_start_x, line_rect.y() + kIconTopPadding);
729 } 748 }
730 } 749 }
731 750
732 cairo_destroy(cr); 751 cairo_destroy(cr);
733 return TRUE; 752 return TRUE;
734 } 753 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698