| OLD | NEW |
| 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/tab_contents/tab_contents_view_gtk.h" | 5 #include "chrome/browser/tab_contents/tab_contents_view_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdk.h> | 7 #include <gdk/gdk.h> |
| 8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
| 9 #include <gtk/gtk.h> | 9 #include <gtk/gtk.h> |
| 10 | 10 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 182 |
| 183 if (event->hardware_keycode < arraysize(kHardwareCodeToGdkKeyval)) { | 183 if (event->hardware_keycode < arraysize(kHardwareCodeToGdkKeyval)) { |
| 184 int keyval = kHardwareCodeToGdkKeyval[event->hardware_keycode]; | 184 int keyval = kHardwareCodeToGdkKeyval[event->hardware_keycode]; |
| 185 if (keyval) | 185 if (keyval) |
| 186 return keyval; | 186 return keyval; |
| 187 } | 187 } |
| 188 | 188 |
| 189 return event->keyval; | 189 return event->keyval; |
| 190 } | 190 } |
| 191 | 191 |
| 192 // Get the current location of the mouse cursor relative to the screen. |
| 193 gfx::Point ScreenPoint(GtkWidget* widget) { |
| 194 int x, y; |
| 195 gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y, |
| 196 NULL); |
| 197 return gfx::Point(x, y); |
| 198 } |
| 199 |
| 200 // Get the current location of the mouse cursor relative to the widget. |
| 201 gfx::Point ClientPoint(GtkWidget* widget) { |
| 202 int x, y; |
| 203 gtk_widget_get_pointer(widget, &x, &y); |
| 204 return gfx::Point(x, y); |
| 205 } |
| 206 |
| 192 } // namespace | 207 } // namespace |
| 193 | 208 |
| 194 // A helper class that handles DnD for drops in the renderer. In GTK parlance, | 209 // A helper class that handles DnD for drops in the renderer. In GTK parlance, |
| 195 // this handles destination-side DnD, but not source-side DnD. | 210 // this handles destination-side DnD, but not source-side DnD. |
| 196 class WebDragDest { | 211 class WebDragDest { |
| 197 public: | 212 public: |
| 198 explicit WebDragDest(TabContents* tab_contents, GtkWidget* widget) | 213 explicit WebDragDest(TabContents* tab_contents, GtkWidget* widget) |
| 199 : tab_contents_(tab_contents), | 214 : tab_contents_(tab_contents), |
| 200 widget_(widget), | 215 widget_(widget), |
| 201 context_(NULL), | 216 context_(NULL), |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 }; | 295 }; |
| 281 | 296 |
| 282 data_requests_ = arraysize(supported_targets); | 297 data_requests_ = arraysize(supported_targets); |
| 283 for (size_t i = 0; i < arraysize(supported_targets); ++i) { | 298 for (size_t i = 0; i < arraysize(supported_targets); ++i) { |
| 284 gtk_drag_get_data(widget_, context, | 299 gtk_drag_get_data(widget_, context, |
| 285 GtkDndUtil::GetAtomForTarget(supported_targets[i]), | 300 GtkDndUtil::GetAtomForTarget(supported_targets[i]), |
| 286 time); | 301 time); |
| 287 } | 302 } |
| 288 } else if (data_requests_ == 0) { | 303 } else if (data_requests_ == 0) { |
| 289 tab_contents_->render_view_host()-> | 304 tab_contents_->render_view_host()-> |
| 290 DragTargetDragOver(ClientPoint(), ScreenPoint()); | 305 DragTargetDragOver(ClientPoint(widget_), ScreenPoint(widget_)); |
| 291 drag_over_time_ = time; | 306 drag_over_time_ = time; |
| 292 } | 307 } |
| 293 | 308 |
| 294 // Pretend we are a drag destination because we don't want to wait for | 309 // Pretend we are a drag destination because we don't want to wait for |
| 295 // the renderer to tell us if we really are or not. | 310 // the renderer to tell us if we really are or not. |
| 296 return TRUE; | 311 return TRUE; |
| 297 } | 312 } |
| 298 | 313 |
| 299 // We make a series of requests for the drag data when the drag first enters | 314 // We make a series of requests for the drag data when the drag first enters |
| 300 // the render view. This is the callback that is used to give us the data | 315 // the render view. This is the callback that is used to give us the data |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 drop_data_->text_html = UTF8ToUTF16(std::string( | 356 drop_data_->text_html = UTF8ToUTF16(std::string( |
| 342 reinterpret_cast<char*>(data->data), data->length)); | 357 reinterpret_cast<char*>(data->data), data->length)); |
| 343 // We leave the base URL empty. | 358 // We leave the base URL empty. |
| 344 } | 359 } |
| 345 } | 360 } |
| 346 | 361 |
| 347 if (data_requests_ == 0) { | 362 if (data_requests_ == 0) { |
| 348 // Tell the renderer about the drag. | 363 // Tell the renderer about the drag. |
| 349 // |x| and |y| are seemingly arbitrary at this point. | 364 // |x| and |y| are seemingly arbitrary at this point. |
| 350 tab_contents_->render_view_host()-> | 365 tab_contents_->render_view_host()-> |
| 351 DragTargetDragEnter(*drop_data_.get(), ClientPoint(), ScreenPoint()); | 366 DragTargetDragEnter(*drop_data_.get(), |
| 367 ClientPoint(widget_), ScreenPoint(widget_)); |
| 352 drag_over_time_ = time; | 368 drag_over_time_ = time; |
| 353 } | 369 } |
| 354 } | 370 } |
| 355 | 371 |
| 356 // The drag has left our widget; forward this information to the renderer. | 372 // The drag has left our widget; forward this information to the renderer. |
| 357 void OnDragLeave(GdkDragContext* context, guint time) { | 373 void OnDragLeave(GdkDragContext* context, guint time) { |
| 358 // Set |context_| to NULL to make sure we will recognize the next DragMotion | 374 // Set |context_| to NULL to make sure we will recognize the next DragMotion |
| 359 // as an enter. | 375 // as an enter. |
| 360 context_ = NULL; | 376 context_ = NULL; |
| 361 drop_data_.reset(); | 377 drop_data_.reset(); |
| 362 // When GTK sends us a drag-drop signal, it is shortly (and synchronously) | 378 // When GTK sends us a drag-drop signal, it is shortly (and synchronously) |
| 363 // preceded by a drag-leave. The renderer doesn't like getting the signals | 379 // preceded by a drag-leave. The renderer doesn't like getting the signals |
| 364 // in this order so delay telling it about the drag-leave till we are sure | 380 // in this order so delay telling it about the drag-leave till we are sure |
| 365 // we are not getting a drop as well. | 381 // we are not getting a drop as well. |
| 366 MessageLoop::current()->PostTask(FROM_HERE, | 382 MessageLoop::current()->PostTask(FROM_HERE, |
| 367 method_factory_.NewRunnableMethod(&WebDragDest::DragLeave)); | 383 method_factory_.NewRunnableMethod(&WebDragDest::DragLeave)); |
| 368 } | 384 } |
| 369 | 385 |
| 370 // Called by GTK when the user releases the mouse, executing a drop. | 386 // Called by GTK when the user releases the mouse, executing a drop. |
| 371 gboolean OnDragDrop(GdkDragContext* context, gint x, gint y, guint time) { | 387 gboolean OnDragDrop(GdkDragContext* context, gint x, gint y, guint time) { |
| 372 // Cancel that drag leave! | 388 // Cancel that drag leave! |
| 373 method_factory_.RevokeAll(); | 389 method_factory_.RevokeAll(); |
| 374 | 390 |
| 375 tab_contents_->render_view_host()-> | 391 tab_contents_->render_view_host()-> |
| 376 DragTargetDrop(ClientPoint(), ScreenPoint()); | 392 DragTargetDrop(ClientPoint(widget_), ScreenPoint(widget_)); |
| 377 | 393 |
| 378 // The second parameter is just an educated guess, but at least we will | 394 // The second parameter is just an educated guess, but at least we will |
| 379 // get the drag-end animation right sometimes. | 395 // get the drag-end animation right sometimes. |
| 380 gtk_drag_finish(context, is_drop_target_, FALSE, time); | 396 gtk_drag_finish(context, is_drop_target_, FALSE, time); |
| 381 return TRUE; | 397 return TRUE; |
| 382 } | 398 } |
| 383 | 399 |
| 384 // Get the current location of the mouse cursor, relative to the screen. | |
| 385 gfx::Point ScreenPoint() { | |
| 386 int x, y; | |
| 387 gdk_display_get_pointer(gtk_widget_get_display(widget_), NULL, &x, &y, | |
| 388 NULL); | |
| 389 return gfx::Point(x, y); | |
| 390 } | |
| 391 | |
| 392 // Get the current location of the mouse cursor, relative to the render view. | |
| 393 gfx::Point ClientPoint() { | |
| 394 int x, y; | |
| 395 gtk_widget_get_pointer(widget_, &x, &y); | |
| 396 return gfx::Point(x, y); | |
| 397 } | |
| 398 | 400 |
| 399 TabContents* tab_contents_; | 401 TabContents* tab_contents_; |
| 400 // The render view. | 402 // The render view. |
| 401 GtkWidget* widget_; | 403 GtkWidget* widget_; |
| 402 // The current drag context for system drags over our render view, or NULL if | 404 // The current drag context for system drags over our render view, or NULL if |
| 403 // there is no system drag or the system drag is not over our render view. | 405 // there is no system drag or the system drag is not over our render view. |
| 404 GdkDragContext* context_; | 406 GdkDragContext* context_; |
| 405 // The data for the current drag, or NULL if |context_| is NULL. | 407 // The data for the current drag, or NULL if |context_| is NULL. |
| 406 scoped_ptr<WebDropData> drop_data_; | 408 scoped_ptr<WebDropData> drop_data_; |
| 407 | 409 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 428 | 430 |
| 429 // static | 431 // static |
| 430 TabContentsView* TabContentsView::Create(TabContents* tab_contents) { | 432 TabContentsView* TabContentsView::Create(TabContents* tab_contents) { |
| 431 return new TabContentsViewGtk(tab_contents); | 433 return new TabContentsViewGtk(tab_contents); |
| 432 } | 434 } |
| 433 | 435 |
| 434 TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) | 436 TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) |
| 435 : TabContentsView(tab_contents), | 437 : TabContentsView(tab_contents), |
| 436 floating_(gtk_floating_container_new()), | 438 floating_(gtk_floating_container_new()), |
| 437 fixed_(gtk_fixed_new()), | 439 fixed_(gtk_fixed_new()), |
| 438 popup_view_(NULL) { | 440 popup_view_(NULL), |
| 441 drag_failed_(false), |
| 442 drag_widget_(NULL) { |
| 439 g_signal_connect(fixed_, "size-allocate", | 443 g_signal_connect(fixed_, "size-allocate", |
| 440 G_CALLBACK(OnSizeAllocate), this); | 444 G_CALLBACK(OnSizeAllocate), this); |
| 441 g_signal_connect(floating_.get(), "set-floating-position", | 445 g_signal_connect(floating_.get(), "set-floating-position", |
| 442 G_CALLBACK(OnSetFloatingPosition), this); | 446 G_CALLBACK(OnSetFloatingPosition), this); |
| 443 | 447 |
| 444 gtk_container_add(GTK_CONTAINER(floating_.get()), fixed_); | 448 gtk_container_add(GTK_CONTAINER(floating_.get()), fixed_); |
| 445 gtk_widget_show(fixed_); | 449 gtk_widget_show(fixed_); |
| 446 gtk_widget_show(floating_.get()); | 450 gtk_widget_show(floating_.get()); |
| 447 registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, | 451 registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, |
| 448 Source<TabContents>(tab_contents)); | 452 Source<TabContents>(tab_contents)); |
| 453 |
| 454 // Renderer source DnD. |
| 455 drag_widget_ = gtk_invisible_new(); |
| 456 g_signal_connect(drag_widget_, "drag-failed", |
| 457 G_CALLBACK(OnDragFailedThunk), this); |
| 458 g_signal_connect(drag_widget_, "drag-end", G_CALLBACK(OnDragEndThunk), this); |
| 459 g_signal_connect(drag_widget_, "drag-data-get", |
| 460 G_CALLBACK(OnDragDataGetThunk), this); |
| 461 g_object_ref_sink(drag_widget_); |
| 449 } | 462 } |
| 450 | 463 |
| 451 TabContentsViewGtk::~TabContentsViewGtk() { | 464 TabContentsViewGtk::~TabContentsViewGtk() { |
| 452 floating_.Destroy(); | 465 floating_.Destroy(); |
| 453 } | 466 } |
| 454 | 467 |
| 455 void TabContentsViewGtk::AttachBlockedPopupView( | 468 void TabContentsViewGtk::AttachBlockedPopupView( |
| 456 BlockedPopupContainerViewGtk* popup_view) { | 469 BlockedPopupContainerViewGtk* popup_view) { |
| 457 DCHECK(popup_view_ == NULL); | 470 DCHECK(popup_view_ == NULL); |
| 458 popup_view_ = popup_view; | 471 popup_view_ = popup_view; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 g_signal_connect(content_view, "leave-notify-event", | 528 g_signal_connect(content_view, "leave-notify-event", |
| 516 G_CALLBACK(OnLeaveNotify), tab_contents()); | 529 G_CALLBACK(OnLeaveNotify), tab_contents()); |
| 517 g_signal_connect(content_view, "motion-notify-event", | 530 g_signal_connect(content_view, "motion-notify-event", |
| 518 G_CALLBACK(OnMouseMove), tab_contents()); | 531 G_CALLBACK(OnMouseMove), tab_contents()); |
| 519 g_signal_connect(content_view, "scroll-event", | 532 g_signal_connect(content_view, "scroll-event", |
| 520 G_CALLBACK(OnMouseScroll), tab_contents()); | 533 G_CALLBACK(OnMouseScroll), tab_contents()); |
| 521 gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK | | 534 gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK | |
| 522 GDK_POINTER_MOTION_MASK); | 535 GDK_POINTER_MOTION_MASK); |
| 523 g_signal_connect(content_view, "button-press-event", | 536 g_signal_connect(content_view, "button-press-event", |
| 524 G_CALLBACK(OnMouseDown), this); | 537 G_CALLBACK(OnMouseDown), this); |
| 538 InsertIntoContentArea(content_view); |
| 525 | 539 |
| 526 // Renderer DnD. | 540 // Renderer target DnD. |
| 527 g_signal_connect(content_view, "drag-end", G_CALLBACK(OnDragEnd), this); | |
| 528 g_signal_connect(content_view, "drag-data-get", G_CALLBACK(OnDragDataGet), | |
| 529 this); | |
| 530 drag_dest_.reset(new WebDragDest(tab_contents(), content_view)); | 541 drag_dest_.reset(new WebDragDest(tab_contents(), content_view)); |
| 531 | 542 |
| 532 InsertIntoContentArea(content_view); | |
| 533 return view; | 543 return view; |
| 534 } | 544 } |
| 535 | 545 |
| 536 gfx::NativeView TabContentsViewGtk::GetNativeView() const { | 546 gfx::NativeView TabContentsViewGtk::GetNativeView() const { |
| 537 return floating_.get(); | 547 return floating_.get(); |
| 538 } | 548 } |
| 539 | 549 |
| 540 gfx::NativeView TabContentsViewGtk::GetContentNativeView() const { | 550 gfx::NativeView TabContentsViewGtk::GetContentNativeView() const { |
| 541 if (!tab_contents()->render_widget_host_view()) | 551 if (!tab_contents()->render_widget_host_view()) |
| 542 return NULL; | 552 return NULL; |
| 543 return tab_contents()->render_widget_host_view()->GetNativeView(); | 553 return tab_contents()->render_widget_host_view()->GetNativeView(); |
| 544 } | 554 } |
| 545 | 555 |
| 546 | |
| 547 gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const { | 556 gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const { |
| 548 GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW); | 557 GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW); |
| 549 return window ? GTK_WINDOW(window) : NULL; | 558 return window ? GTK_WINDOW(window) : NULL; |
| 550 } | 559 } |
| 551 | 560 |
| 552 void TabContentsViewGtk::InitRendererPrefs(RendererPreferences* prefs) { | 561 void TabContentsViewGtk::InitRendererPrefs(RendererPreferences* prefs) { |
| 553 GtkSettings* gtk_settings = gtk_settings_get_default(); | 562 GtkSettings* gtk_settings = gtk_settings_get_default(); |
| 554 | 563 |
| 555 gint antialias = 0; | 564 gint antialias = 0; |
| 556 gint hinting = 0; | 565 gint hinting = 0; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 // animation. | 614 // animation. |
| 606 int x = 0; | 615 int x = 0; |
| 607 int y = 0; | 616 int y = 0; |
| 608 if (fixed_->window) | 617 if (fixed_->window) |
| 609 gdk_window_get_origin(fixed_->window, &x, &y); | 618 gdk_window_get_origin(fixed_->window, &x, &y); |
| 610 out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y, | 619 out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y, |
| 611 fixed_->allocation.width, fixed_->allocation.height); | 620 fixed_->allocation.width, fixed_->allocation.height); |
| 612 } | 621 } |
| 613 | 622 |
| 614 void TabContentsViewGtk::OnContentsDestroy() { | 623 void TabContentsViewGtk::OnContentsDestroy() { |
| 615 // TODO(estade): Windows uses this for some sort of plugin-related stuff. | 624 // We don't want to try to handle drag events from this point on. |
| 625 g_signal_handlers_disconnect_by_func(drag_widget_, |
| 626 reinterpret_cast<gpointer>(OnDragFailedThunk), this); |
| 627 g_signal_handlers_disconnect_by_func(drag_widget_, |
| 628 reinterpret_cast<gpointer>(OnDragEndThunk), this); |
| 629 g_signal_handlers_disconnect_by_func(drag_widget_, |
| 630 reinterpret_cast<gpointer>(OnDragDataGetThunk), this); |
| 631 |
| 632 // Break the current drag, if any. |
| 633 if (drop_data_.get()) { |
| 634 gtk_grab_add(drag_widget_); |
| 635 gtk_grab_remove(drag_widget_); |
| 636 MessageLoopForUI::current()->RemoveObserver(this); |
| 637 drop_data_.reset(); |
| 638 } |
| 639 |
| 640 gtk_widget_destroy(drag_widget_); |
| 641 g_object_unref(drag_widget_); |
| 642 drag_widget_ = NULL; |
| 616 } | 643 } |
| 617 | 644 |
| 618 void TabContentsViewGtk::SetPageTitle(const std::wstring& title) { | 645 void TabContentsViewGtk::SetPageTitle(const std::wstring& title) { |
| 619 // Set the window name to include the page title so it's easier to spot | 646 // Set the window name to include the page title so it's easier to spot |
| 620 // when debugging (e.g. via xwininfo -tree). | 647 // when debugging (e.g. via xwininfo -tree). |
| 621 gfx::NativeView content_view = GetContentNativeView(); | 648 gfx::NativeView content_view = GetContentNativeView(); |
| 622 if (content_view && content_view->window) | 649 if (content_view && content_view->window) |
| 623 gdk_window_set_title(content_view->window, WideToUTF8(title).c_str()); | 650 gdk_window_set_title(content_view->window, WideToUTF8(title).c_str()); |
| 624 } | 651 } |
| 625 | 652 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 // vbox's children. | 742 // vbox's children. |
| 716 sad_tab_.reset(); | 743 sad_tab_.reset(); |
| 717 break; | 744 break; |
| 718 } | 745 } |
| 719 default: | 746 default: |
| 720 NOTREACHED() << "Got a notification we didn't register for."; | 747 NOTREACHED() << "Got a notification we didn't register for."; |
| 721 break; | 748 break; |
| 722 } | 749 } |
| 723 } | 750 } |
| 724 | 751 |
| 752 void TabContentsViewGtk::WillProcessEvent(GdkEvent* event) { |
| 753 // No-op. |
| 754 } |
| 755 |
| 756 void TabContentsViewGtk::DidProcessEvent(GdkEvent* event) { |
| 757 if (event->type != GDK_MOTION_NOTIFY) |
| 758 return; |
| 759 |
| 760 GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event); |
| 761 gfx::Point client = ClientPoint(GetContentNativeView()); |
| 762 |
| 763 if (tab_contents()->render_view_host()) { |
| 764 tab_contents()->render_view_host()->DragSourceMovedTo( |
| 765 client.x(), client.y(), event_motion->x_root, event_motion->y_root); |
| 766 } |
| 767 } |
| 768 |
| 725 void TabContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) { | 769 void TabContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) { |
| 726 context_menu_.reset(new RenderViewContextMenuGtk(tab_contents(), params, | 770 context_menu_.reset(new RenderViewContextMenuGtk(tab_contents(), params, |
| 727 last_mouse_down_.time)); | 771 last_mouse_down_.time)); |
| 728 context_menu_->Init(); | 772 context_menu_->Init(); |
| 729 context_menu_->Popup(); | 773 context_menu_->Popup(); |
| 730 } | 774 } |
| 731 | 775 |
| 732 // Render view DnD ------------------------------------------------------------- | 776 // Render view DnD ------------------------------------------------------------- |
| 733 | 777 |
| 734 void TabContentsViewGtk::DragEnded() { | |
| 735 if (tab_contents()->render_view_host()) | |
| 736 tab_contents()->render_view_host()->DragSourceSystemDragEnded(); | |
| 737 } | |
| 738 | |
| 739 void TabContentsViewGtk::StartDragging(const WebDropData& drop_data) { | 778 void TabContentsViewGtk::StartDragging(const WebDropData& drop_data) { |
| 740 DCHECK(GetContentNativeView()); | 779 DCHECK(GetContentNativeView()); |
| 741 | 780 |
| 742 int targets_mask = 0; | 781 int targets_mask = 0; |
| 743 | 782 |
| 744 if (!drop_data.plain_text.empty()) | 783 if (!drop_data.plain_text.empty()) |
| 745 targets_mask |= GtkDndUtil::TEXT_PLAIN; | 784 targets_mask |= GtkDndUtil::TEXT_PLAIN; |
| 746 if (drop_data.url.is_valid()) { | 785 if (drop_data.url.is_valid()) { |
| 747 targets_mask |= GtkDndUtil::TEXT_URI_LIST; | 786 targets_mask |= GtkDndUtil::TEXT_URI_LIST; |
| 748 targets_mask |= GtkDndUtil::CHROME_NAMED_URL; | 787 targets_mask |= GtkDndUtil::CHROME_NAMED_URL; |
| 749 } | 788 } |
| 750 if (!drop_data.text_html.empty()) | 789 if (!drop_data.text_html.empty()) |
| 751 targets_mask |= GtkDndUtil::TEXT_HTML; | 790 targets_mask |= GtkDndUtil::TEXT_HTML; |
| 752 if (!drop_data.file_contents.empty()) | 791 if (!drop_data.file_contents.empty()) |
| 753 targets_mask |= GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS; | 792 targets_mask |= GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS; |
| 754 | 793 |
| 755 if (targets_mask == 0) { | 794 if (targets_mask == 0) { |
| 756 NOTIMPLEMENTED(); | 795 NOTIMPLEMENTED(); |
| 757 DragEnded(); | 796 if (tab_contents()->render_view_host()) |
| 758 return; | 797 tab_contents()->render_view_host()->DragSourceSystemDragEnded(); |
| 759 } | 798 } |
| 760 | 799 |
| 761 drop_data_.reset(new WebDropData(drop_data)); | 800 drop_data_.reset(new WebDropData(drop_data)); |
| 762 | 801 |
| 763 GtkTargetList* list = GtkDndUtil::GetTargetListFromCodeMask(targets_mask); | 802 GtkTargetList* list = GtkDndUtil::GetTargetListFromCodeMask(targets_mask); |
| 764 if (targets_mask & GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS) { | 803 if (targets_mask & GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS) { |
| 765 drag_file_mime_type_ = gdk_atom_intern( | 804 drag_file_mime_type_ = gdk_atom_intern( |
| 766 mime_util::GetDataMimeType(drop_data.file_contents).c_str(), FALSE); | 805 mime_util::GetDataMimeType(drop_data.file_contents).c_str(), FALSE); |
| 767 gtk_target_list_add(list, drag_file_mime_type_, | 806 gtk_target_list_add(list, drag_file_mime_type_, |
| 768 0, GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS); | 807 0, GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS); |
| 769 } | 808 } |
| 770 | 809 |
| 810 drag_failed_ = false; |
| 771 // If we don't pass an event, GDK won't know what event time to start grabbing | 811 // If we don't pass an event, GDK won't know what event time to start grabbing |
| 772 // mouse events. Technically it's the mouse motion event and not the mouse | 812 // mouse events. Technically it's the mouse motion event and not the mouse |
| 773 // down event that causes the drag, but there's no reliable way to know | 813 // down event that causes the drag, but there's no reliable way to know |
| 774 // *which* motion event initiated the drag, so this will have to do. | 814 // *which* motion event initiated the drag, so this will have to do. |
| 775 // TODO(estade): This can sometimes be very far off, e.g. if the user clicks | 815 // TODO(estade): This can sometimes be very far off, e.g. if the user clicks |
| 776 // and holds and doesn't start dragging for a long time. I doubt it matters | 816 // and holds and doesn't start dragging for a long time. I doubt it matters |
| 777 // much, but we should probably look into the possibility of getting the | 817 // much, but we should probably look into the possibility of getting the |
| 778 // initiating event from webkit. | 818 // initiating event from webkit. |
| 779 gtk_drag_begin(GetContentNativeView(), list, GDK_ACTION_COPY, | 819 gtk_drag_begin(drag_widget_, list, GDK_ACTION_COPY, |
| 780 1, // Drags are always initiated by the left button. | 820 1, // Drags are always initiated by the left button. |
| 781 reinterpret_cast<GdkEvent*>(&last_mouse_down_)); | 821 reinterpret_cast<GdkEvent*>(&last_mouse_down_)); |
| 822 MessageLoopForUI::current()->AddObserver(this); |
| 782 // The drag adds a ref; let it own the list. | 823 // The drag adds a ref; let it own the list. |
| 783 gtk_target_list_unref(list); | 824 gtk_target_list_unref(list); |
| 784 } | 825 } |
| 785 | 826 |
| 786 // static | |
| 787 void TabContentsViewGtk::OnDragDataGet( | 827 void TabContentsViewGtk::OnDragDataGet( |
| 788 GtkWidget* drag_widget, | |
| 789 GdkDragContext* context, GtkSelectionData* selection_data, | 828 GdkDragContext* context, GtkSelectionData* selection_data, |
| 790 guint target_type, guint time, TabContentsViewGtk* view) { | 829 guint target_type, guint time) { |
| 791 const int bits_per_byte = 8; | 830 const int bits_per_byte = 8; |
| 792 | 831 |
| 793 switch (target_type) { | 832 switch (target_type) { |
| 794 case GtkDndUtil::TEXT_PLAIN: { | 833 case GtkDndUtil::TEXT_PLAIN: { |
| 795 std::string utf8_text = UTF16ToUTF8(view->drop_data_->plain_text); | 834 std::string utf8_text = UTF16ToUTF8(drop_data_->plain_text); |
| 796 gtk_selection_data_set_text(selection_data, utf8_text.c_str(), | 835 gtk_selection_data_set_text(selection_data, utf8_text.c_str(), |
| 797 utf8_text.length()); | 836 utf8_text.length()); |
| 798 break; | 837 break; |
| 799 } | 838 } |
| 800 | 839 |
| 801 case GtkDndUtil::TEXT_URI_LIST: { | 840 case GtkDndUtil::TEXT_URI_LIST: { |
| 802 gchar* uri_array[2]; | 841 gchar* uri_array[2]; |
| 803 uri_array[0] = strdup(view->drop_data_->url.spec().c_str()); | 842 uri_array[0] = strdup(drop_data_->url.spec().c_str()); |
| 804 uri_array[1] = NULL; | 843 uri_array[1] = NULL; |
| 805 gtk_selection_data_set_uris(selection_data, uri_array); | 844 gtk_selection_data_set_uris(selection_data, uri_array); |
| 806 free(uri_array[0]); | 845 free(uri_array[0]); |
| 807 break; | 846 break; |
| 808 } | 847 } |
| 809 | 848 |
| 810 case GtkDndUtil::TEXT_HTML: { | 849 case GtkDndUtil::TEXT_HTML: { |
| 811 // TODO(estade): change relative links to be absolute using | 850 // TODO(estade): change relative links to be absolute using |
| 812 // |html_base_url|. | 851 // |html_base_url|. |
| 813 std::string utf8_text = UTF16ToUTF8(view->drop_data_->text_html); | 852 std::string utf8_text = UTF16ToUTF8(drop_data_->text_html); |
| 814 gtk_selection_data_set(selection_data, | 853 gtk_selection_data_set(selection_data, |
| 815 GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_HTML), | 854 GtkDndUtil::GetAtomForTarget(GtkDndUtil::TEXT_HTML), |
| 816 bits_per_byte, | 855 bits_per_byte, |
| 817 reinterpret_cast<const guchar*>(utf8_text.c_str()), | 856 reinterpret_cast<const guchar*>(utf8_text.c_str()), |
| 818 utf8_text.length()); | 857 utf8_text.length()); |
| 819 break; | 858 break; |
| 820 } | 859 } |
| 821 | 860 |
| 822 case GtkDndUtil::CHROME_NAMED_URL: { | 861 case GtkDndUtil::CHROME_NAMED_URL: { |
| 823 Pickle pickle; | 862 Pickle pickle; |
| 824 pickle.WriteString(UTF16ToUTF8(view->drop_data_->url_title)); | 863 pickle.WriteString(UTF16ToUTF8(drop_data_->url_title)); |
| 825 pickle.WriteString(view->drop_data_->url.spec()); | 864 pickle.WriteString(drop_data_->url.spec()); |
| 826 gtk_selection_data_set(selection_data, | 865 gtk_selection_data_set(selection_data, |
| 827 GtkDndUtil::GetAtomForTarget(GtkDndUtil::CHROME_NAMED_URL), | 866 GtkDndUtil::GetAtomForTarget(GtkDndUtil::CHROME_NAMED_URL), |
| 828 bits_per_byte, | 867 bits_per_byte, |
| 829 reinterpret_cast<const guchar*>(pickle.data()), | 868 reinterpret_cast<const guchar*>(pickle.data()), |
| 830 pickle.size()); | 869 pickle.size()); |
| 831 break; | 870 break; |
| 832 } | 871 } |
| 833 | 872 |
| 834 case GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS: { | 873 case GtkDndUtil::CHROME_WEBDROP_FILE_CONTENTS: { |
| 835 gtk_selection_data_set(selection_data, | 874 gtk_selection_data_set(selection_data, |
| 836 view->drag_file_mime_type_, bits_per_byte, | 875 drag_file_mime_type_, bits_per_byte, |
| 837 reinterpret_cast<const guchar*>( | 876 reinterpret_cast<const guchar*>(drop_data_->file_contents.data()), |
| 838 view->drop_data_->file_contents.data()), | 877 drop_data_->file_contents.length()); |
| 839 view->drop_data_->file_contents.length()); | |
| 840 break; | 878 break; |
| 841 } | 879 } |
| 842 | 880 |
| 843 default: | 881 default: |
| 844 NOTREACHED(); | 882 NOTREACHED(); |
| 845 } | 883 } |
| 846 } | 884 } |
| 847 | 885 |
| 848 // static | 886 gboolean TabContentsViewGtk::OnDragFailed() { |
| 849 void TabContentsViewGtk::OnDragEnd(GtkWidget* widget, | 887 drag_failed_ = true; |
| 850 GdkDragContext* drag_context, TabContentsViewGtk* view) { | 888 |
| 851 view->DragEnded(); | 889 gfx::Point root = ScreenPoint(GetContentNativeView()); |
| 852 view->drop_data_.reset(); | 890 gfx::Point client = ClientPoint(GetContentNativeView()); |
| 891 |
| 892 if (tab_contents()->render_view_host()) { |
| 893 tab_contents()->render_view_host()->DragSourceCancelledAt( |
| 894 client.x(), client.y(), root.x(), root.y()); |
| 895 } |
| 896 |
| 897 // Let the native failure animation run. |
| 898 return FALSE; |
| 899 } |
| 900 |
| 901 void TabContentsViewGtk::OnDragEnd() { |
| 902 MessageLoopForUI::current()->RemoveObserver(this); |
| 903 |
| 904 if (!drag_failed_) { |
| 905 gfx::Point root = ScreenPoint(GetContentNativeView()); |
| 906 gfx::Point client = ClientPoint(GetContentNativeView()); |
| 907 |
| 908 if (tab_contents()->render_view_host()) { |
| 909 tab_contents()->render_view_host()->DragSourceEndedAt( |
| 910 client.x(), client.y(), root.x(), root.y()); |
| 911 } |
| 912 } |
| 913 |
| 914 if (tab_contents()->render_view_host()) |
| 915 tab_contents()->render_view_host()->DragSourceSystemDragEnded(); |
| 916 |
| 917 drop_data_.reset(); |
| 853 } | 918 } |
| 854 | 919 |
| 855 // ----------------------------------------------------------------------------- | 920 // ----------------------------------------------------------------------------- |
| 856 | 921 |
| 857 void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) { | 922 void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) { |
| 858 gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0); | 923 gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0); |
| 859 } | 924 } |
| 860 | 925 |
| 861 gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget, | 926 gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget, |
| 862 GdkEventButton* event, TabContentsViewGtk* view) { | 927 GdkEventButton* event, TabContentsViewGtk* view) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 995 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
| 931 widget, "x", &value); | 996 widget, "x", &value); |
| 932 | 997 |
| 933 int child_y = std::max(half_view_height - (requisition.height / 2), 0); | 998 int child_y = std::max(half_view_height - (requisition.height / 2), 0); |
| 934 g_value_set_int(&value, child_y); | 999 g_value_set_int(&value, child_y); |
| 935 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 1000 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
| 936 widget, "y", &value); | 1001 widget, "y", &value); |
| 937 g_value_unset(&value); | 1002 g_value_unset(&value); |
| 938 } | 1003 } |
| 939 } | 1004 } |
| OLD | NEW |