| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/chromeos/views/domui_menu_widget.h" | 5 #include "chrome/browser/chromeos/views/webui_menu_widget.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
| 10 #include "base/singleton.h" | 10 #include "base/singleton.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "chrome/browser/chromeos/views/menu_locator.h" | 12 #include "chrome/browser/chromeos/views/menu_locator.h" |
| 13 #include "chrome/browser/chromeos/views/native_menu_domui.h" | 13 #include "chrome/browser/chromeos/views/native_menu_domui.h" |
| 14 #include "chrome/browser/chromeos/wm_ipc.h" | 14 #include "chrome/browser/chromeos/wm_ipc.h" |
| 15 #include "chrome/browser/renderer_host/render_view_host.h" | 15 #include "chrome/browser/renderer_host/render_view_host.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 gfx::Insets insets = host->GetInsets(); | 97 gfx::Insets insets = host->GetInsets(); |
| 98 gfx::Size size = host->GetChildViewAt(0)->GetPreferredSize(); | 98 gfx::Size size = host->GetChildViewAt(0)->GetPreferredSize(); |
| 99 return gfx::Size(size.width() + insets.width(), | 99 return gfx::Size(size.width() + insets.width(), |
| 100 size.height() + insets.height()); | 100 size.height() + insets.height()); |
| 101 } | 101 } |
| 102 | 102 |
| 103 DISALLOW_COPY_AND_ASSIGN(InsetsLayout); | 103 DISALLOW_COPY_AND_ASSIGN(InsetsLayout); |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 // A gtk widget key used to test if a given WidgetGtk instance is | 106 // A gtk widget key used to test if a given WidgetGtk instance is |
| 107 // DOMUIMenuWidgetKey. | 107 // a WebUIMenuWidgetKey. |
| 108 const char* kDOMUIMenuWidgetKey = "__DOMUI_MENU_WIDGET__"; | 108 const char* kWebUIMenuWidgetKey = "__WEBUI_MENU_WIDGET__"; |
| 109 | 109 |
| 110 } // namespace | 110 } // namespace |
| 111 | 111 |
| 112 namespace chromeos { | 112 namespace chromeos { |
| 113 | 113 |
| 114 // static | 114 // static |
| 115 DOMUIMenuWidget* DOMUIMenuWidget::FindDOMUIMenuWidget(gfx::NativeView native) { | 115 WebUIMenuWidget* WebUIMenuWidget::FindWebUIMenuWidget(gfx::NativeView native) { |
| 116 DCHECK(native); | 116 DCHECK(native); |
| 117 native = gtk_widget_get_toplevel(native); | 117 native = gtk_widget_get_toplevel(native); |
| 118 if (!native) | 118 if (!native) |
| 119 return NULL; | 119 return NULL; |
| 120 return static_cast<chromeos::DOMUIMenuWidget*>( | 120 return static_cast<chromeos::WebUIMenuWidget*>( |
| 121 g_object_get_data(G_OBJECT(native), kDOMUIMenuWidgetKey)); | 121 g_object_get_data(G_OBJECT(native), kWebUIMenuWidgetKey)); |
| 122 } | 122 } |
| 123 | 123 |
| 124 /////////////////////////////////////////////////////////////////////////////// | 124 /////////////////////////////////////////////////////////////////////////////// |
| 125 // DOMUIMenuWidget public: | 125 // WebUIMenuWidget public: |
| 126 | 126 |
| 127 DOMUIMenuWidget::DOMUIMenuWidget(chromeos::NativeMenuDOMUI* domui_menu, | 127 WebUIMenuWidget::WebUIMenuWidget(chromeos::NativeMenuDOMUI* domui_menu, |
| 128 bool root) | 128 bool root) |
| 129 : views::WidgetGtk(views::WidgetGtk::TYPE_POPUP), | 129 : views::WidgetGtk(views::WidgetGtk::TYPE_POPUP), |
| 130 domui_menu_(domui_menu), | 130 domui_menu_(domui_menu), |
| 131 dom_view_(NULL), | 131 dom_view_(NULL), |
| 132 did_input_grab_(false), | 132 did_input_grab_(false), |
| 133 is_root_(root) { | 133 is_root_(root) { |
| 134 DCHECK(domui_menu_); | 134 DCHECK(domui_menu_); |
| 135 // TODO(oshima): Disabling transparent until we migrate bookmark | 135 // TODO(oshima): Disabling transparent until we migrate bookmark |
| 136 // menus to DOMUI. See crosbug.com/7718. | 136 // menus to DOMUI. See crosbug.com/7718. |
| 137 // MakeTransparent(); | 137 // MakeTransparent(); |
| 138 } | 138 } |
| 139 | 139 |
| 140 DOMUIMenuWidget::~DOMUIMenuWidget() { | 140 WebUIMenuWidget::~WebUIMenuWidget() { |
| 141 } | 141 } |
| 142 | 142 |
| 143 void DOMUIMenuWidget::Init(gfx::NativeView parent, const gfx::Rect& bounds) { | 143 void WebUIMenuWidget::Init(gfx::NativeView parent, const gfx::Rect& bounds) { |
| 144 WidgetGtk::Init(parent, bounds); | 144 WidgetGtk::Init(parent, bounds); |
| 145 gtk_window_set_destroy_with_parent(GTK_WINDOW(GetNativeView()), TRUE); | 145 gtk_window_set_destroy_with_parent(GTK_WINDOW(GetNativeView()), TRUE); |
| 146 gtk_window_set_type_hint(GTK_WINDOW(GetNativeView()), | 146 gtk_window_set_type_hint(GTK_WINDOW(GetNativeView()), |
| 147 GDK_WINDOW_TYPE_HINT_MENU); | 147 GDK_WINDOW_TYPE_HINT_MENU); |
| 148 g_object_set_data(G_OBJECT(GetNativeView()), kDOMUIMenuWidgetKey, this); | 148 g_object_set_data(G_OBJECT(GetNativeView()), kWebUIMenuWidgetKey, this); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void DOMUIMenuWidget::Hide() { | 151 void WebUIMenuWidget::Hide() { |
| 152 ReleaseGrab(); | 152 ReleaseGrab(); |
| 153 WidgetGtk::Hide(); | 153 WidgetGtk::Hide(); |
| 154 // Clears the content. | 154 // Clears the content. |
| 155 ExecuteJavascript(L"updateModel({'items':[]})"); | 155 ExecuteJavascript(L"updateModel({'items':[]})"); |
| 156 } | 156 } |
| 157 | 157 |
| 158 void DOMUIMenuWidget::Close() { | 158 void WebUIMenuWidget::Close() { |
| 159 if (dom_view_ != NULL) { | 159 if (dom_view_ != NULL) { |
| 160 dom_view_->GetParent()->RemoveChildView(dom_view_); | 160 dom_view_->GetParent()->RemoveChildView(dom_view_); |
| 161 delete dom_view_; | 161 delete dom_view_; |
| 162 dom_view_ = NULL; | 162 dom_view_ = NULL; |
| 163 } | 163 } |
| 164 | 164 |
| 165 // Detach the domui_menu_ which is being deleted. | 165 // Detach the domui_menu_ which is being deleted. |
| 166 domui_menu_ = NULL; | 166 domui_menu_ = NULL; |
| 167 views::WidgetGtk::Close(); | 167 views::WidgetGtk::Close(); |
| 168 } | 168 } |
| 169 | 169 |
| 170 void DOMUIMenuWidget::ReleaseGrab() { | 170 void WebUIMenuWidget::ReleaseGrab() { |
| 171 WidgetGtk::ReleaseGrab(); | 171 WidgetGtk::ReleaseGrab(); |
| 172 if (did_input_grab_) { | 172 if (did_input_grab_) { |
| 173 did_input_grab_ = false; | 173 did_input_grab_ = false; |
| 174 gdk_pointer_ungrab(GDK_CURRENT_TIME); | 174 gdk_pointer_ungrab(GDK_CURRENT_TIME); |
| 175 gdk_keyboard_ungrab(GDK_CURRENT_TIME); | 175 gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
| 176 | 176 |
| 177 ClearGrabWidget(); | 177 ClearGrabWidget(); |
| 178 } | 178 } |
| 179 } | 179 } |
| 180 | 180 |
| 181 gboolean DOMUIMenuWidget::OnGrabBrokeEvent(GtkWidget* widget, | 181 gboolean WebUIMenuWidget::OnGrabBrokeEvent(GtkWidget* widget, |
| 182 GdkEvent* event) { | 182 GdkEvent* event) { |
| 183 did_input_grab_ = false; | 183 did_input_grab_ = false; |
| 184 Hide(); | 184 Hide(); |
| 185 return WidgetGtk::OnGrabBrokeEvent(widget, event); | 185 return WidgetGtk::OnGrabBrokeEvent(widget, event); |
| 186 } | 186 } |
| 187 | 187 |
| 188 void DOMUIMenuWidget::OnSizeAllocate(GtkWidget* widget, | 188 void WebUIMenuWidget::OnSizeAllocate(GtkWidget* widget, |
| 189 GtkAllocation* allocation) { | 189 GtkAllocation* allocation) { |
| 190 views::WidgetGtk::OnSizeAllocate(widget, allocation); | 190 views::WidgetGtk::OnSizeAllocate(widget, allocation); |
| 191 // Adjust location when menu gets resized. | 191 // Adjust location when menu gets resized. |
| 192 gfx::Rect bounds; | 192 gfx::Rect bounds; |
| 193 GetBounds(&bounds, false); | 193 GetBounds(&bounds, false); |
| 194 // Don't move until the menu gets contents. | 194 // Don't move until the menu gets contents. |
| 195 if (bounds.height() > 1) { | 195 if (bounds.height() > 1) { |
| 196 menu_locator_->Move(this); | 196 menu_locator_->Move(this); |
| 197 domui_menu_->InputIsReady(); | 197 domui_menu_->InputIsReady(); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 gboolean MapToFocus(GtkWidget* widget, GdkEvent* event, gpointer data) { | 201 gboolean MapToFocus(GtkWidget* widget, GdkEvent* event, gpointer data) { |
| 202 DOMUIMenuWidget* menu_widget = DOMUIMenuWidget::FindDOMUIMenuWidget(widget); | 202 WebUIMenuWidget* menu_widget = WebUIMenuWidget::FindWebUIMenuWidget(widget); |
| 203 if (menu_widget) { | 203 if (menu_widget) { |
| 204 // See EnableInput for the meaning of data. | 204 // See EnableInput for the meaning of data. |
| 205 bool select_item = data != NULL; | 205 bool select_item = data != NULL; |
| 206 menu_widget->EnableInput(select_item); | 206 menu_widget->EnableInput(select_item); |
| 207 } | 207 } |
| 208 return true; | 208 return true; |
| 209 } | 209 } |
| 210 | 210 |
| 211 void DOMUIMenuWidget::EnableScroll(bool enable) { | 211 void WebUIMenuWidget::EnableScroll(bool enable) { |
| 212 ExecuteJavascript(StringPrintf( | 212 ExecuteJavascript(StringPrintf( |
| 213 L"enableScroll(%ls)", enable ? L"true" : L"false")); | 213 L"enableScroll(%ls)", enable ? L"true" : L"false")); |
| 214 } | 214 } |
| 215 | 215 |
| 216 void DOMUIMenuWidget::EnableInput(bool select_item) { | 216 void WebUIMenuWidget::EnableInput(bool select_item) { |
| 217 if (!dom_view_) | 217 if (!dom_view_) |
| 218 return; | 218 return; |
| 219 DCHECK(dom_view_->tab_contents()->render_view_host()); | 219 DCHECK(dom_view_->tab_contents()->render_view_host()); |
| 220 DCHECK(dom_view_->tab_contents()->render_view_host()->view()); | 220 DCHECK(dom_view_->tab_contents()->render_view_host()->view()); |
| 221 GtkWidget* target = | 221 GtkWidget* target = |
| 222 dom_view_->tab_contents()->render_view_host()->view()->GetNativeView(); | 222 dom_view_->tab_contents()->render_view_host()->view()->GetNativeView(); |
| 223 DCHECK(target); | 223 DCHECK(target); |
| 224 // Skip if the widget already own the input. | 224 // Skip if the widget already own the input. |
| 225 if (gtk_grab_get_current() == target) | 225 if (gtk_grab_get_current() == target) |
| 226 return; | 226 return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 237 return; | 237 return; |
| 238 } | 238 } |
| 239 | 239 |
| 240 gtk_grab_add(target); | 240 gtk_grab_add(target); |
| 241 dom_view_->tab_contents()->Focus(); | 241 dom_view_->tab_contents()->Focus(); |
| 242 if (select_item) { | 242 if (select_item) { |
| 243 ExecuteJavascript(L"selectItem()"); | 243 ExecuteJavascript(L"selectItem()"); |
| 244 } | 244 } |
| 245 } | 245 } |
| 246 | 246 |
| 247 void DOMUIMenuWidget::ExecuteJavascript(const std::wstring& script) { | 247 void WebUIMenuWidget::ExecuteJavascript(const std::wstring& script) { |
| 248 // Don't exeute there is no DOMView associated. This is fine because | 248 // Don't execute if there is no DOMView associated. This is fine because |
| 249 // 1) selectItem make sense only when DOMView is associated. | 249 // 1) selectItem make sense only when DOMView is associated. |
| 250 // 2) updateModel will be called again when a DOMView is created/assigned. | 250 // 2) updateModel will be called again when a DOMView is created/assigned. |
| 251 if (!dom_view_) | 251 if (!dom_view_) |
| 252 return; | 252 return; |
| 253 | 253 |
| 254 DCHECK(dom_view_->tab_contents()->render_view_host()); | 254 DCHECK(dom_view_->tab_contents()->render_view_host()); |
| 255 dom_view_->tab_contents()->render_view_host()-> | 255 dom_view_->tab_contents()->render_view_host()-> |
| 256 ExecuteJavascriptInWebFrame(std::wstring(), script); | 256 ExecuteJavascriptInWebFrame(std::wstring(), script); |
| 257 } | 257 } |
| 258 | 258 |
| 259 void DOMUIMenuWidget::ShowAt(chromeos::MenuLocator* locator) { | 259 void WebUIMenuWidget::ShowAt(chromeos::MenuLocator* locator) { |
| 260 DCHECK(domui_menu_); | 260 DCHECK(domui_menu_); |
| 261 menu_locator_.reset(locator); | 261 menu_locator_.reset(locator); |
| 262 if (!dom_view_) { | 262 if (!dom_view_) { |
| 263 // TODO(oshima): Replace DOMView with direct use of RVH for beta. | 263 // TODO(oshima): Replace DOMView with direct use of RVH for beta. |
| 264 // DOMView should be refactored to use RVH directly, but | 264 // DOMView should be refactored to use RVH directly, but |
| 265 // it'll require a lot of change and will take time. | 265 // it'll require a lot of change and will take time. |
| 266 dom_view_ = new DOMView(); | 266 dom_view_ = new DOMView(); |
| 267 dom_view_->Init(domui_menu_->GetProfile(), NULL); | 267 dom_view_->Init(domui_menu_->GetProfile(), NULL); |
| 268 // TODO(oshima): remove extra view to draw rounded corner. | 268 // TODO(oshima): remove extra view to draw rounded corner. |
| 269 views::View* container = new views::View(); | 269 views::View* container = new views::View(); |
| 270 container->AddChildView(dom_view_); | 270 container->AddChildView(dom_view_); |
| 271 container->set_border(new RoundedBorder(locator)); | 271 container->set_border(new RoundedBorder(locator)); |
| 272 container->SetLayoutManager(new InsetsLayout()); | 272 container->SetLayoutManager(new InsetsLayout()); |
| 273 SetContentsView(container); | 273 SetContentsView(container); |
| 274 dom_view_->LoadURL(domui_menu_->menu_url()); | 274 dom_view_->LoadURL(domui_menu_->menu_url()); |
| 275 } else { | 275 } else { |
| 276 domui_menu_->UpdateStates(); | 276 domui_menu_->UpdateStates(); |
| 277 dom_view_->GetParent()->set_border(new RoundedBorder(locator)); | 277 dom_view_->GetParent()->set_border(new RoundedBorder(locator)); |
| 278 menu_locator_->Move(this); | 278 menu_locator_->Move(this); |
| 279 } | 279 } |
| 280 Show(); | 280 Show(); |
| 281 | 281 |
| 282 // The pointer grab is captured only on the top level menu, | 282 // The pointer grab is captured only on the top level menu, |
| 283 // all mouse event events are delivered to submenu using gtk_add_grab. | 283 // all mouse event events are delivered to submenu using gtk_add_grab. |
| 284 if (is_root_) { | 284 if (is_root_) { |
| 285 CaptureGrab(); | 285 CaptureGrab(); |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 | 288 |
| 289 void DOMUIMenuWidget::SetSize(const gfx::Size& new_size) { | 289 void WebUIMenuWidget::SetSize(const gfx::Size& new_size) { |
| 290 DCHECK(domui_menu_); | 290 DCHECK(domui_menu_); |
| 291 // Ignore the empty new_size request which is called when | 291 // Ignore the empty new_size request which is called when |
| 292 // menu.html is loaded. | 292 // menu.html is loaded. |
| 293 if (new_size.IsEmpty()) | 293 if (new_size.IsEmpty()) |
| 294 return; | 294 return; |
| 295 int width, height; | 295 int width, height; |
| 296 gtk_widget_get_size_request(GetNativeView(), &width, &height); | 296 gtk_widget_get_size_request(GetNativeView(), &width, &height); |
| 297 gfx::Size real_size(std::max(new_size.width(), width), | 297 gfx::Size real_size(std::max(new_size.width(), width), |
| 298 new_size.height()); | 298 new_size.height()); |
| 299 // Ignore the size request with the same size. | 299 // Ignore the size request with the same size. |
| 300 gfx::Rect bounds; | 300 gfx::Rect bounds; |
| 301 GetBounds(&bounds, false); | 301 GetBounds(&bounds, false); |
| 302 if (bounds.size() == real_size) | 302 if (bounds.size() == real_size) |
| 303 return; | 303 return; |
| 304 menu_locator_->SetBounds(this, real_size); | 304 menu_locator_->SetBounds(this, real_size); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /////////////////////////////////////////////////////////////////////////////// | 307 /////////////////////////////////////////////////////////////////////////////// |
| 308 // DOMUIMenuWidget private: | 308 // WebUIMenuWidget private: |
| 309 | 309 |
| 310 void DOMUIMenuWidget::CaptureGrab() { | 310 void WebUIMenuWidget::CaptureGrab() { |
| 311 // Release the current grab. | 311 // Release the current grab. |
| 312 ClearGrabWidget(); | 312 ClearGrabWidget(); |
| 313 | 313 |
| 314 // NOTE: we do this to ensure we get mouse/keyboard events from | 314 // NOTE: we do this to ensure we get mouse/keyboard events from |
| 315 // other apps, a grab done with gtk_grab_add doesn't get events from | 315 // other apps, a grab done with gtk_grab_add doesn't get events from |
| 316 // other apps. | 316 // other apps. |
| 317 GdkGrabStatus pointer_grab_status = | 317 GdkGrabStatus pointer_grab_status = |
| 318 gdk_pointer_grab(window_contents()->window, FALSE, | 318 gdk_pointer_grab(window_contents()->window, FALSE, |
| 319 static_cast<GdkEventMask>( | 319 static_cast<GdkEventMask>( |
| 320 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | | 320 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | |
| 321 GDK_POINTER_MOTION_MASK), | 321 GDK_POINTER_MOTION_MASK), |
| 322 NULL, NULL, GDK_CURRENT_TIME); | 322 NULL, NULL, GDK_CURRENT_TIME); |
| 323 GdkGrabStatus keyboard_grab_status = | 323 GdkGrabStatus keyboard_grab_status = |
| 324 gdk_keyboard_grab(window_contents()->window, FALSE, | 324 gdk_keyboard_grab(window_contents()->window, FALSE, |
| 325 GDK_CURRENT_TIME); | 325 GDK_CURRENT_TIME); |
| 326 | 326 |
| 327 did_input_grab_ = pointer_grab_status == GDK_GRAB_SUCCESS && | 327 did_input_grab_ = pointer_grab_status == GDK_GRAB_SUCCESS && |
| 328 keyboard_grab_status == GDK_GRAB_SUCCESS; | 328 keyboard_grab_status == GDK_GRAB_SUCCESS; |
| 329 DCHECK(did_input_grab_); | 329 DCHECK(did_input_grab_); |
| 330 | 330 |
| 331 EnableInput(false /* no selection */); | 331 EnableInput(false /* no selection */); |
| 332 } | 332 } |
| 333 | 333 |
| 334 void DOMUIMenuWidget::ClearGrabWidget() { | 334 void WebUIMenuWidget::ClearGrabWidget() { |
| 335 GtkWidget* grab_widget; | 335 GtkWidget* grab_widget; |
| 336 while ((grab_widget = gtk_grab_get_current())) | 336 while ((grab_widget = gtk_grab_get_current())) |
| 337 gtk_grab_remove(grab_widget); | 337 gtk_grab_remove(grab_widget); |
| 338 } | 338 } |
| 339 | 339 |
| 340 } // namespace chromeos | 340 } // namespace chromeos |
| OLD | NEW |