OLD | NEW |
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 13 matching lines...) Expand all Loading... |
24 #include "chrome/browser/search_engines/template_url_service.h" | 24 #include "chrome/browser/search_engines/template_url_service.h" |
25 #include "chrome/browser/ui/gtk/gtk_util.h" | 25 #include "chrome/browser/ui/gtk/gtk_util.h" |
26 #include "chrome/browser/ui/gtk/theme_service_gtk.h" | 26 #include "chrome/browser/ui/gtk/theme_service_gtk.h" |
27 #include "chrome/browser/ui/omnibox/omnibox_view.h" | 27 #include "chrome/browser/ui/omnibox/omnibox_view.h" |
28 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
29 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
30 #include "grit/theme_resources.h" | 30 #include "grit/theme_resources.h" |
31 #include "ui/base/gtk/gtk_compat.h" | 31 #include "ui/base/gtk/gtk_compat.h" |
32 #include "ui/base/gtk/gtk_hig_constants.h" | 32 #include "ui/base/gtk/gtk_hig_constants.h" |
33 #include "ui/base/gtk/gtk_screen_util.h" | 33 #include "ui/base/gtk/gtk_screen_util.h" |
| 34 #include "ui/base/gtk/gtk_signal_registrar.h" |
34 #include "ui/base/gtk/gtk_windowing.h" | 35 #include "ui/base/gtk/gtk_windowing.h" |
35 #include "ui/gfx/color_utils.h" | 36 #include "ui/gfx/color_utils.h" |
36 #include "ui/gfx/font.h" | 37 #include "ui/gfx/font.h" |
37 #include "ui/gfx/gtk_util.h" | 38 #include "ui/gfx/gtk_util.h" |
38 #include "ui/gfx/image/cairo_cached_surface.h" | 39 #include "ui/gfx/image/cairo_cached_surface.h" |
39 #include "ui/gfx/image/image.h" | 40 #include "ui/gfx/image/image.h" |
40 #include "ui/gfx/rect.h" | 41 #include "ui/gfx/rect.h" |
41 #include "ui/gfx/skia_utils_gtk.h" | 42 #include "ui/gfx/skia_utils_gtk.h" |
42 | 43 |
43 namespace { | 44 namespace { |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 | 270 |
270 pango_layout_set_text(layout, text_utf8.data(), text_utf8.length()); | 271 pango_layout_set_text(layout, text_utf8.data(), text_utf8.length()); |
271 pango_layout_set_attributes(layout, attrs); // Ref taken. | 272 pango_layout_set_attributes(layout, attrs); // Ref taken. |
272 pango_attr_list_unref(attrs); | 273 pango_attr_list_unref(attrs); |
273 } | 274 } |
274 | 275 |
275 OmniboxPopupViewGtk::OmniboxPopupViewGtk(const gfx::Font& font, | 276 OmniboxPopupViewGtk::OmniboxPopupViewGtk(const gfx::Font& font, |
276 OmniboxView* omnibox_view, | 277 OmniboxView* omnibox_view, |
277 AutocompleteEditModel* edit_model, | 278 AutocompleteEditModel* edit_model, |
278 GtkWidget* location_bar) | 279 GtkWidget* location_bar) |
279 : model_(new AutocompletePopupModel(this, edit_model)), | 280 : signal_registrar_(new ui::GtkSignalRegistrar), |
| 281 model_(new AutocompletePopupModel(this, edit_model)), |
280 omnibox_view_(omnibox_view), | 282 omnibox_view_(omnibox_view), |
281 location_bar_(location_bar), | 283 location_bar_(location_bar), |
282 window_(gtk_window_new(GTK_WINDOW_POPUP)), | 284 window_(gtk_window_new(GTK_WINDOW_POPUP)), |
283 layout_(NULL), | 285 layout_(NULL), |
284 theme_service_(ThemeServiceGtk::GetFrom(edit_model->profile())), | 286 theme_service_(ThemeServiceGtk::GetFrom(edit_model->profile())), |
285 font_(font.DeriveFont(kEditFontAdjust)), | 287 font_(font.DeriveFont(kEditFontAdjust)), |
286 ignore_mouse_drag_(false), | 288 ignore_mouse_drag_(false), |
287 opened_(false) { | 289 opened_(false) { |
288 gtk_widget_set_can_focus(window_, FALSE); | 290 gtk_widget_set_can_focus(window_, FALSE); |
289 // Don't allow the window to be resized. This also forces the window to | 291 // Don't allow the window to be resized. This also forces the window to |
290 // shrink down to the size of its child contents. | 292 // shrink down to the size of its child contents. |
291 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); | 293 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); |
292 gtk_widget_set_app_paintable(window_, TRUE); | 294 gtk_widget_set_app_paintable(window_, TRUE); |
293 // Have GTK double buffer around the expose signal. | 295 // Have GTK double buffer around the expose signal. |
294 gtk_widget_set_double_buffered(window_, TRUE); | 296 gtk_widget_set_double_buffered(window_, TRUE); |
295 | 297 |
296 // Cache the layout so we don't have to create it for every expose. If we | 298 // Cache the layout so we don't have to create it for every expose. If we |
297 // were a real widget we should handle changing directions, but we're not | 299 // were a real widget we should handle changing directions, but we're not |
298 // doing RTL or anything yet, so it shouldn't be important now. | 300 // doing RTL or anything yet, so it shouldn't be important now. |
299 layout_ = gtk_widget_create_pango_layout(window_, NULL); | 301 layout_ = gtk_widget_create_pango_layout(window_, NULL); |
300 // We don't want the layout of search results depending on their language. | 302 // We don't want the layout of search results depending on their language. |
301 pango_layout_set_auto_dir(layout_, FALSE); | 303 pango_layout_set_auto_dir(layout_, FALSE); |
302 // We always ellipsize when drawing our text runs. | 304 // We always ellipsize when drawing our text runs. |
303 pango_layout_set_ellipsize(layout_, PANGO_ELLIPSIZE_END); | 305 pango_layout_set_ellipsize(layout_, PANGO_ELLIPSIZE_END); |
304 | 306 |
305 gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK | | 307 gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK | |
306 GDK_POINTER_MOTION_MASK | | 308 GDK_POINTER_MOTION_MASK | |
307 GDK_BUTTON_PRESS_MASK | | 309 GDK_BUTTON_PRESS_MASK | |
308 GDK_BUTTON_RELEASE_MASK); | 310 GDK_BUTTON_RELEASE_MASK); |
309 g_signal_connect(window_, "motion-notify-event", | 311 signal_registrar_->Connect(window_, "motion-notify-event", |
310 G_CALLBACK(HandleMotionThunk), this); | 312 G_CALLBACK(HandleMotionThunk), this); |
311 g_signal_connect(window_, "button-press-event", | 313 signal_registrar_->Connect(window_, "button-press-event", |
312 G_CALLBACK(HandleButtonPressThunk), this); | 314 G_CALLBACK(HandleButtonPressThunk), this); |
313 g_signal_connect(window_, "button-release-event", | 315 signal_registrar_->Connect(window_, "button-release-event", |
314 G_CALLBACK(HandleButtonReleaseThunk), this); | 316 G_CALLBACK(HandleButtonReleaseThunk), this); |
315 g_signal_connect(window_, "expose-event", | 317 signal_registrar_->Connect(window_, "expose-event", |
316 G_CALLBACK(HandleExposeThunk), this); | 318 G_CALLBACK(HandleExposeThunk), this); |
317 | 319 |
318 registrar_.Add(this, | 320 registrar_.Add(this, |
319 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | 321 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
320 content::Source<ThemeService>(theme_service_)); | 322 content::Source<ThemeService>(theme_service_)); |
321 theme_service_->InitThemesFor(this); | 323 theme_service_->InitThemesFor(this); |
322 | 324 |
323 // TODO(erg): There appears to be a bug somewhere in something which shows | 325 // TODO(erg): There appears to be a bug somewhere in something which shows |
324 // itself when we're in NX. Previously, we called | 326 // itself when we're in NX. Previously, we called |
325 // gtk_util::ActAsRoundedWindow() to make this popup have rounded | 327 // gtk_util::ActAsRoundedWindow() to make this popup have rounded |
326 // corners. This worked on the standard xorg server (both locally and | 328 // corners. This worked on the standard xorg server (both locally and |
327 // remotely), but broke over NX. My current hypothesis is that it can't | 329 // remotely), but broke over NX. My current hypothesis is that it can't |
328 // handle shaping top-level windows during an expose event, but I'm not sure | 330 // handle shaping top-level windows during an expose event, but I'm not sure |
329 // how else to get accurate shaping information. | 331 // how else to get accurate shaping information. |
330 // | 332 // |
331 // r25080 (the original patch that added rounded corners here) should | 333 // r25080 (the original patch that added rounded corners here) should |
332 // eventually be cherry picked once I know what's going | 334 // eventually be cherry picked once I know what's going |
333 // on. http://crbug.com/22015. | 335 // on. http://crbug.com/22015. |
334 } | 336 } |
335 | 337 |
336 OmniboxPopupViewGtk::~OmniboxPopupViewGtk() { | 338 OmniboxPopupViewGtk::~OmniboxPopupViewGtk() { |
| 339 // Stop listening to our signals before we destroy the model. I suspect that |
| 340 // we can race window destruction, otherwise. |
| 341 signal_registrar_.reset(); |
| 342 |
337 // Explicitly destroy our model here, before we destroy our GTK widgets. | 343 // Explicitly destroy our model here, before we destroy our GTK widgets. |
338 // This is because the model destructor can call back into us, and we need | 344 // This is because the model destructor can call back into us, and we need |
339 // to make sure everything is still valid when it does. | 345 // to make sure everything is still valid when it does. |
340 model_.reset(); | 346 model_.reset(); |
341 g_object_unref(layout_); | 347 g_object_unref(layout_); |
342 gtk_widget_destroy(window_); | 348 gtk_widget_destroy(window_); |
343 | 349 |
344 for (ImageMap::iterator it = images_.begin(); it != images_.end(); ++it) | 350 for (ImageMap::iterator it = images_.begin(); it != images_.end(); ++it) |
345 delete it->second; | 351 delete it->second; |
346 } | 352 } |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 DrawFullImage(cr, widget, | 741 DrawFullImage(cr, widget, |
736 theme_service_->GetImageNamed( | 742 theme_service_->GetImageNamed( |
737 is_selected ? IDR_OMNIBOX_TTS_DARK : IDR_OMNIBOX_TTS), | 743 is_selected ? IDR_OMNIBOX_TTS_DARK : IDR_OMNIBOX_TTS), |
738 icon_start_x, line_rect.y() + kIconTopPadding); | 744 icon_start_x, line_rect.y() + kIconTopPadding); |
739 } | 745 } |
740 } | 746 } |
741 | 747 |
742 cairo_destroy(cr); | 748 cairo_destroy(cr); |
743 return TRUE; | 749 return TRUE; |
744 } | 750 } |
OLD | NEW |