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

Side by Side Diff: chrome/browser/gtk/info_bubble_gtk.cc

Issue 1170001: GTK: allow inspecting of extension popups. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 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
« no previous file with comments | « chrome/browser/gtk/info_bubble_gtk.h ('k') | chrome/browser/gtk/location_bar_view_gtk.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/gtk/info_bubble_gtk.h" 5 #include "chrome/browser/gtk/info_bubble_gtk.h"
6 6
7 #include <gdk/gdkkeysyms.h> 7 #include <gdk/gdkkeysyms.h>
8 #include <gtk/gtk.h> 8 #include <gtk/gtk.h>
9 9
10 #include "app/l10n_util.h" 10 #include "app/l10n_util.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); 42 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);
43 43
44 } // namespace 44 } // namespace
45 45
46 // static 46 // static
47 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window, 47 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window,
48 const gfx::Rect& rect, 48 const gfx::Rect& rect,
49 GtkWidget* content, 49 GtkWidget* content,
50 ArrowLocationGtk arrow_location, 50 ArrowLocationGtk arrow_location,
51 bool match_system_theme, 51 bool match_system_theme,
52 bool grab_input,
52 GtkThemeProvider* provider, 53 GtkThemeProvider* provider,
53 InfoBubbleGtkDelegate* delegate) { 54 InfoBubbleGtkDelegate* delegate) {
54 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider, match_system_theme); 55 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider, match_system_theme);
55 bubble->Init(toplevel_window, rect, content, arrow_location); 56 bubble->Init(toplevel_window, rect, content, arrow_location, grab_input);
56 bubble->set_delegate(delegate); 57 bubble->set_delegate(delegate);
57 return bubble; 58 return bubble;
58 } 59 }
59 60
60 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider, 61 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider,
61 bool match_system_theme) 62 bool match_system_theme)
62 : delegate_(NULL), 63 : delegate_(NULL),
63 window_(NULL), 64 window_(NULL),
64 theme_provider_(provider), 65 theme_provider_(provider),
65 accel_group_(gtk_accel_group_new()), 66 accel_group_(gtk_accel_group_new()),
66 toplevel_window_(NULL), 67 toplevel_window_(NULL),
67 mask_region_(NULL), 68 mask_region_(NULL),
68 preferred_arrow_location_(ARROW_LOCATION_TOP_LEFT), 69 preferred_arrow_location_(ARROW_LOCATION_TOP_LEFT),
69 current_arrow_location_(ARROW_LOCATION_TOP_LEFT), 70 current_arrow_location_(ARROW_LOCATION_TOP_LEFT),
70 match_system_theme_(match_system_theme) { 71 match_system_theme_(match_system_theme),
72 grab_input_(true),
73 closed_by_escape_(false) {
71 } 74 }
72 75
73 InfoBubbleGtk::~InfoBubbleGtk() { 76 InfoBubbleGtk::~InfoBubbleGtk() {
77 // Notify the delegate that we're about to close. This gives the chance
78 // to save state / etc from the hosted widget before it's destroyed.
79 if (delegate_)
80 delegate_->InfoBubbleClosing(this, closed_by_escape_);
81
74 g_object_unref(accel_group_); 82 g_object_unref(accel_group_);
75 if (mask_region_) { 83 if (mask_region_) {
76 gdk_region_destroy(mask_region_); 84 gdk_region_destroy(mask_region_);
77 mask_region_ = NULL; 85 mask_region_ = NULL;
78 } 86 }
79 87
80 g_signal_handlers_disconnect_by_func( 88 if (toplevel_window_) {
81 toplevel_window_, 89 g_signal_handlers_disconnect_by_func(
82 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk), 90 toplevel_window_,
83 this); 91 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk),
84 g_signal_handlers_disconnect_by_func( 92 this);
85 toplevel_window_, 93 g_signal_handlers_disconnect_by_func(
86 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk), 94 toplevel_window_,
87 this); 95 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk),
96 this);
97 }
88 toplevel_window_ = NULL; 98 toplevel_window_ = NULL;
89 } 99 }
90 100
91 void InfoBubbleGtk::Init(GtkWindow* toplevel_window, 101 void InfoBubbleGtk::Init(GtkWindow* toplevel_window,
92 const gfx::Rect& rect, 102 const gfx::Rect& rect,
93 GtkWidget* content, 103 GtkWidget* content,
94 ArrowLocationGtk arrow_location) { 104 ArrowLocationGtk arrow_location,
105 bool grab_input) {
95 DCHECK(!window_); 106 DCHECK(!window_);
96 toplevel_window_ = toplevel_window; 107 toplevel_window_ = toplevel_window;
97 rect_ = rect; 108 rect_ = rect;
98 preferred_arrow_location_ = arrow_location; 109 preferred_arrow_location_ = arrow_location;
99 110
100 window_ = gtk_window_new(GTK_WINDOW_POPUP); 111 grab_input_ = grab_input;
112 // Using a TOPLEVEL window may cause placement issues with certain WMs but it
113 // is necessary to be able to focus the window.
114 window_ = gtk_window_new(grab_input ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
115
101 gtk_widget_set_app_paintable(window_, TRUE); 116 gtk_widget_set_app_paintable(window_, TRUE);
102 // Resizing is handled by the program, not user. 117 // Resizing is handled by the program, not user.
103 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 118 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
104 119
105 // Attach our accelerator group to the window with an escape accelerator. 120 // Attach our accelerator group to the window with an escape accelerator.
106 gtk_accel_group_connect(accel_group_, GDK_Escape, 121 gtk_accel_group_connect(accel_group_, GDK_Escape,
107 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0), 122 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0),
108 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL)); 123 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL));
109 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_); 124 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_);
110 125
(...skipping 22 matching lines...) Expand all
133 G_CALLBACK(HandleSizeAllocateThunk), this); 148 G_CALLBACK(HandleSizeAllocateThunk), this);
134 g_signal_connect(window_, "button-press-event", 149 g_signal_connect(window_, "button-press-event",
135 G_CALLBACK(&HandleButtonPressThunk), this); 150 G_CALLBACK(&HandleButtonPressThunk), this);
136 g_signal_connect(window_, "destroy", 151 g_signal_connect(window_, "destroy",
137 G_CALLBACK(&HandleDestroyThunk), this); 152 G_CALLBACK(&HandleDestroyThunk), this);
138 153
139 g_signal_connect(toplevel_window, "configure-event", 154 g_signal_connect(toplevel_window, "configure-event",
140 G_CALLBACK(&HandleToplevelConfigureThunk), this); 155 G_CALLBACK(&HandleToplevelConfigureThunk), this);
141 g_signal_connect(toplevel_window, "unmap-event", 156 g_signal_connect(toplevel_window, "unmap-event",
142 G_CALLBACK(&HandleToplevelUnmapThunk), this); 157 G_CALLBACK(&HandleToplevelUnmapThunk), this);
158 // Set |toplevel_window_| to NULL if it gets destroyed.
159 g_signal_connect(toplevel_window, "destroy",
160 G_CALLBACK(gtk_widget_destroyed), &toplevel_window_);
143 161
144 gtk_widget_show_all(window_); 162 gtk_widget_show_all(window_);
145 163
146 // We add a GTK (application-level) grab. This means we will get all 164 if (grab_input_) {
147 // mouse events for our application, even if they were delivered on another 165 // We add a GTK (application-level) grab. This means we will get all
148 // window. We don't need this to get button presses outside of the bubble's 166 // mouse events for our application, even if they were delivered on another
149 // window so we'll know to close it (the pointer grab takes care of that), but 167 // window. We don't need this to get button presses outside of the bubble's
150 // it prevents other widgets from getting highlighted when the pointer moves 168 // window so we'll know to close it (the pointer grab takes care of that),
151 // over them. 169 // but it prevents other widgets from getting highlighted when the pointer
152 // 170 // moves over them.
153 // (Ideally we wouldn't add the window to a group and it would just get all 171 //
154 // the mouse events, but gtk_grab_add() doesn't appear to do anything in that 172 // (Ideally we wouldn't add the window to a group and it would just get all
155 // case. Adding it to the toplevel window's group first appears to block 173 // the mouse events, but gtk_grab_add() doesn't appear to do anything in
156 // enter/leave events for that window and its subwindows, although other 174 // that case. Adding it to the toplevel window's group first appears to
157 // browser windows still receive them). 175 // block enter/leave events for that window and its subwindows, although
158 gtk_window_group_add_window(gtk_window_get_group(toplevel_window), 176 // other browser windows still receive them).
159 GTK_WINDOW(window_)); 177 gtk_window_group_add_window(gtk_window_get_group(toplevel_window),
160 gtk_grab_add(window_); 178 GTK_WINDOW(window_));
179 gtk_grab_add(window_);
161 180
162 GrabPointerAndKeyboard(); 181 GrabPointerAndKeyboard();
182 }
163 183
164 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, 184 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
165 NotificationService::AllSources()); 185 NotificationService::AllSources());
166 theme_provider_->InitThemesFor(this); 186 theme_provider_->InitThemesFor(this);
167 } 187 }
168 188
169 // NOTE: This seems a bit overcomplicated, but it requires a bunch of careful 189 // NOTE: This seems a bit overcomplicated, but it requires a bunch of careful
170 // fudging to get the pixels rasterized exactly where we want them, the arrow to 190 // fudging to get the pixels rasterized exactly where we want them, the arrow to
171 // have a 1 pixel point, etc. 191 // have a 1 pixel point, etc.
172 // TODO(deanm): Windows draws with Skia and uses some PNG images for the 192 // TODO(deanm): Windows draws with Skia and uses some PNG images for the
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED); 334 DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
315 if (theme_provider_->UseGtkTheme() && match_system_theme_) { 335 if (theme_provider_->UseGtkTheme() && match_system_theme_) {
316 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL); 336 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL);
317 } else { 337 } else {
318 // Set the background color, so we don't need to paint it manually. 338 // Set the background color, so we don't need to paint it manually.
319 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor); 339 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor);
320 } 340 }
321 } 341 }
322 342
323 void InfoBubbleGtk::HandlePointerAndKeyboardUngrabbedByContent() { 343 void InfoBubbleGtk::HandlePointerAndKeyboardUngrabbedByContent() {
324 GrabPointerAndKeyboard(); 344 if (grab_input_)
345 GrabPointerAndKeyboard();
325 } 346 }
326 347
327 void InfoBubbleGtk::CloseInternal(bool closed_by_escape) { 348 void InfoBubbleGtk::Close() {
328 // Notify the delegate that we're about to close. This gives the chance
329 // to save state / etc from the hosted widget before it's destroyed.
330 if (delegate_)
331 delegate_->InfoBubbleClosing(this, closed_by_escape);
332
333 // We don't need to ungrab the pointer or keyboard here; the X server will 349 // We don't need to ungrab the pointer or keyboard here; the X server will
334 // automatically do that when we destroy our window. 350 // automatically do that when we destroy our window.
335
336 DCHECK(window_); 351 DCHECK(window_);
337 gtk_widget_destroy(window_); 352 gtk_widget_destroy(window_);
338 // |this| has been deleted, see HandleDestroy. 353 // |this| has been deleted, see HandleDestroy.
339 } 354 }
340 355
341 void InfoBubbleGtk::GrabPointerAndKeyboard() { 356 void InfoBubbleGtk::GrabPointerAndKeyboard() {
342 // Install X pointer and keyboard grabs to make sure that we have the focus 357 // Install X pointer and keyboard grabs to make sure that we have the focus
343 // and get all mouse and keyboard events until we're closed. 358 // and get all mouse and keyboard events until we're closed.
344 GdkGrabStatus pointer_grab_status = 359 GdkGrabStatus pointer_grab_status =
345 gdk_pointer_grab(window_->window, 360 gdk_pointer_grab(window_->window,
(...skipping 12 matching lines...) Expand all
358 gdk_keyboard_grab(window_->window, 373 gdk_keyboard_grab(window_->window,
359 FALSE, // owner_events 374 FALSE, // owner_events
360 GDK_CURRENT_TIME); 375 GDK_CURRENT_TIME);
361 if (keyboard_grab_status != GDK_GRAB_SUCCESS) { 376 if (keyboard_grab_status != GDK_GRAB_SUCCESS) {
362 DLOG(ERROR) << "Unable to grab keyboard (status=" 377 DLOG(ERROR) << "Unable to grab keyboard (status="
363 << keyboard_grab_status << ")"; 378 << keyboard_grab_status << ")";
364 } 379 }
365 } 380 }
366 381
367 gboolean InfoBubbleGtk::HandleEscape() { 382 gboolean InfoBubbleGtk::HandleEscape() {
368 CloseInternal(true); // Close by escape. 383 closed_by_escape_ = true;
384 Close();
369 return TRUE; 385 return TRUE;
370 } 386 }
371 387
372 gboolean InfoBubbleGtk::HandleExpose() { 388 gboolean InfoBubbleGtk::HandleExpose() {
373 GdkDrawable* drawable = GDK_DRAWABLE(window_->window); 389 GdkDrawable* drawable = GDK_DRAWABLE(window_->window);
374 GdkGC* gc = gdk_gc_new(drawable); 390 GdkGC* gc = gdk_gc_new(drawable);
375 gdk_gc_set_rgb_fg_color(gc, &kFrameColor); 391 gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
376 392
377 // Stroke the frame border. 393 // Stroke the frame border.
378 std::vector<GdkPoint> points = MakeFramePolygonPoints( 394 std::vector<GdkPoint> points = MakeFramePolygonPoints(
(...skipping 25 matching lines...) Expand all
404 (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) { 420 (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) {
405 return FALSE; // Propagate. 421 return FALSE; // Propagate.
406 } 422 }
407 423
408 // Our content widget got a click. 424 // Our content widget got a click.
409 if (event->window != window_->window && 425 if (event->window != window_->window &&
410 gdk_window_get_toplevel(event->window) == window_->window) { 426 gdk_window_get_toplevel(event->window) == window_->window) {
411 return FALSE; 427 return FALSE;
412 } 428 }
413 429
414 // Otherwise we had a click outside of our window, close ourself. 430 if (grab_input_) {
415 Close(); 431 // Otherwise we had a click outside of our window, close ourself.
416 return TRUE; 432 Close();
433 return TRUE;
434 }
435
436 return FALSE;
417 } 437 }
418 438
419 gboolean InfoBubbleGtk::HandleDestroy() { 439 gboolean InfoBubbleGtk::HandleDestroy() {
420 // We are self deleting, we have a destroy signal setup to catch when we 440 // We are self deleting, we have a destroy signal setup to catch when we
421 // destroy the widget manually, or the window was closed via X. This will 441 // destroy the widget manually, or the window was closed via X. This will
422 // delete the InfoBubbleGtk object. 442 // delete the InfoBubbleGtk object.
423 delete this; 443 delete this;
424 return FALSE; // Propagate. 444 return FALSE; // Propagate.
425 } 445 }
426 446
427 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) { 447 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) {
428 if (!UpdateArrowLocation(false)) 448 if (!UpdateArrowLocation(false))
429 MoveWindow(); 449 MoveWindow();
430 StackWindow(); 450 StackWindow();
431 return FALSE; 451 return FALSE;
432 } 452 }
433 453
434 gboolean InfoBubbleGtk::HandleToplevelUnmap() { 454 gboolean InfoBubbleGtk::HandleToplevelUnmap() {
435 Close(); 455 Close();
436 return FALSE; 456 return FALSE;
437 } 457 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/info_bubble_gtk.h ('k') | chrome/browser/gtk/location_bar_view_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698