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

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

Powered by Google App Engine
This is Rietveld 408576698