| 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 "views/widget/widget_gtk.h" | 5 #include "views/widget/widget_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdk.h> | 7 #include <gdk/gdk.h> |
| 8 #include <gdk/gdkx.h> | 8 #include <gdk/gdkx.h> |
| 9 #include <X11/extensions/shape.h> | 9 #include <X11/extensions/shape.h> |
| 10 | 10 |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 if (parent) { | 590 if (parent) { |
| 591 SetBounds(bounds); | 591 SetBounds(bounds); |
| 592 } | 592 } |
| 593 } else { | 593 } else { |
| 594 if (bounds.width() > 0 && bounds.height() > 0) | 594 if (bounds.width() > 0 && bounds.height() > 0) |
| 595 gtk_window_resize(GTK_WINDOW(widget_), bounds.width(), bounds.height()); | 595 gtk_window_resize(GTK_WINDOW(widget_), bounds.width(), bounds.height()); |
| 596 gtk_window_move(GTK_WINDOW(widget_), bounds.x(), bounds.y()); | 596 gtk_window_move(GTK_WINDOW(widget_), bounds.x(), bounds.y()); |
| 597 } | 597 } |
| 598 } | 598 } |
| 599 | 599 |
| 600 void WidgetGtk::SetBounds(const gfx::Rect& bounds) { | |
| 601 if (type_ == TYPE_CHILD) { | |
| 602 GtkWidget* parent = gtk_widget_get_parent(widget_); | |
| 603 if (GTK_IS_VIEWS_FIXED(parent)) { | |
| 604 WidgetGtk* parent_widget = static_cast<WidgetGtk*>( | |
| 605 NativeWidget::GetNativeWidgetForNativeView(parent)); | |
| 606 parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), | |
| 607 bounds.width(), bounds.height()); | |
| 608 } else { | |
| 609 DCHECK(GTK_IS_FIXED(parent)) | |
| 610 << "Parent of WidgetGtk has to be Fixed or ViewsFixed"; | |
| 611 // Just request the size if the parent is not WidgetGtk but plain | |
| 612 // GtkFixed. WidgetGtk does not know the minimum size so we assume | |
| 613 // the caller of the SetBounds knows exactly how big it wants to be. | |
| 614 gtk_widget_set_size_request(widget_, bounds.width(), bounds.height()); | |
| 615 if (parent != null_parent_) | |
| 616 gtk_fixed_move(GTK_FIXED(parent), widget_, bounds.x(), bounds.y()); | |
| 617 } | |
| 618 } else { | |
| 619 if (GTK_WIDGET_MAPPED(widget_)) { | |
| 620 // If the widget is mapped (on screen), we can move and resize with one | |
| 621 // call, which avoids two separate window manager steps. | |
| 622 gdk_window_move_resize(widget_->window, bounds.x(), bounds.y(), | |
| 623 bounds.width(), bounds.height()); | |
| 624 } | |
| 625 | |
| 626 // Always call gtk_window_move and gtk_window_resize so that GtkWindow's | |
| 627 // geometry info is up-to-date. | |
| 628 GtkWindow* gtk_window = GTK_WINDOW(widget_); | |
| 629 // TODO: this may need to set an initial size if not showing. | |
| 630 // TODO: need to constrain based on screen size. | |
| 631 if (!bounds.IsEmpty()) { | |
| 632 gtk_window_resize(gtk_window, bounds.width(), bounds.height()); | |
| 633 } | |
| 634 gtk_window_move(gtk_window, bounds.x(), bounds.y()); | |
| 635 } | |
| 636 } | |
| 637 | |
| 638 void WidgetGtk::MoveAbove(Widget* widget) { | |
| 639 DCHECK(widget_); | |
| 640 DCHECK(widget_->window); | |
| 641 // TODO(oshima): gdk_window_restack is not available in gtk2.0, so | |
| 642 // we're simply raising the window to the top. We should switch to | |
| 643 // gdk_window_restack when we upgrade gtk to 2.18 or up. | |
| 644 gdk_window_raise(widget_->window); | |
| 645 } | |
| 646 | |
| 647 void WidgetGtk::SetShape(gfx::NativeRegion region) { | |
| 648 DCHECK(widget_); | |
| 649 DCHECK(widget_->window); | |
| 650 gdk_window_shape_combine_region(widget_->window, region, 0, 0); | |
| 651 gdk_region_destroy(region); | |
| 652 } | |
| 653 | |
| 654 void WidgetGtk::Close() { | |
| 655 if (!widget_) | |
| 656 return; // No need to do anything. | |
| 657 | |
| 658 // Hide first. | |
| 659 Hide(); | |
| 660 if (close_widget_factory_.empty()) { | |
| 661 // And we delay the close just in case we're on the stack. | |
| 662 MessageLoop::current()->PostTask(FROM_HERE, | |
| 663 close_widget_factory_.NewRunnableMethod( | |
| 664 &WidgetGtk::CloseNow)); | |
| 665 } | |
| 666 } | |
| 667 | |
| 668 void WidgetGtk::CloseNow() { | |
| 669 if (widget_) { | |
| 670 gtk_widget_destroy(widget_); // Triggers OnDestroy(). | |
| 671 } | |
| 672 } | |
| 673 | |
| 674 void WidgetGtk::Show() { | |
| 675 if (widget_) { | |
| 676 gtk_widget_show(widget_); | |
| 677 if (widget_->window) | |
| 678 gdk_window_raise(widget_->window); | |
| 679 } | |
| 680 } | |
| 681 | |
| 682 void WidgetGtk::Hide() { | |
| 683 if (widget_) { | |
| 684 gtk_widget_hide(widget_); | |
| 685 if (widget_->window) | |
| 686 gdk_window_lower(widget_->window); | |
| 687 } | |
| 688 } | |
| 689 | |
| 690 gfx::NativeView WidgetGtk::GetNativeView() const { | 600 gfx::NativeView WidgetGtk::GetNativeView() const { |
| 691 return widget_; | 601 return widget_; |
| 692 } | 602 } |
| 693 | 603 |
| 694 void WidgetGtk::SetOpacity(unsigned char opacity) { | |
| 695 opacity_ = opacity; | |
| 696 if (widget_) { | |
| 697 // We can only set the opacity when the widget has been realized. | |
| 698 gdk_window_set_opacity(widget_->window, static_cast<gdouble>(opacity) / | |
| 699 static_cast<gdouble>(255)); | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 void WidgetGtk::SetAlwaysOnTop(bool on_top) { | |
| 704 DCHECK(type_ != TYPE_CHILD); | |
| 705 always_on_top_ = on_top; | |
| 706 if (widget_) | |
| 707 gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top); | |
| 708 } | |
| 709 | |
| 710 bool WidgetGtk::IsVisible() const { | |
| 711 return GTK_WIDGET_VISIBLE(widget_); | |
| 712 } | |
| 713 | |
| 714 bool WidgetGtk::IsActive() const { | |
| 715 DCHECK(type_ != TYPE_CHILD); | |
| 716 return is_active_; | |
| 717 } | |
| 718 | |
| 719 bool WidgetGtk::IsAccessibleWidget() const { | |
| 720 return false; | |
| 721 } | |
| 722 | |
| 723 void WidgetGtk::GenerateMousePressedForView(View* view, | 604 void WidgetGtk::GenerateMousePressedForView(View* view, |
| 724 const gfx::Point& point) { | 605 const gfx::Point& point) { |
| 725 NOTIMPLEMENTED(); | 606 NOTIMPLEMENTED(); |
| 726 } | 607 } |
| 727 | 608 |
| 728 bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { | 609 bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { |
| 729 NOTIMPLEMENTED(); | 610 NOTIMPLEMENTED(); |
| 730 return false; | 611 return false; |
| 731 } | 612 } |
| 732 | 613 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 // enough for our uses. | 731 // enough for our uses. |
| 851 gtk_window_get_size(GTK_WINDOW(widget_), &w, &h); | 732 gtk_window_get_size(GTK_WINDOW(widget_), &w, &h); |
| 852 } else { | 733 } else { |
| 853 GetWidgetPositionOnScreen(widget_, &x, &y); | 734 GetWidgetPositionOnScreen(widget_, &x, &y); |
| 854 w = widget_->allocation.width; | 735 w = widget_->allocation.width; |
| 855 h = widget_->allocation.height; | 736 h = widget_->allocation.height; |
| 856 } | 737 } |
| 857 return gfx::Rect(x, y, w, h); | 738 return gfx::Rect(x, y, w, h); |
| 858 } | 739 } |
| 859 | 740 |
| 741 void WidgetGtk::SetBounds(const gfx::Rect& bounds) { |
| 742 if (type_ == TYPE_CHILD) { |
| 743 GtkWidget* parent = gtk_widget_get_parent(widget_); |
| 744 if (GTK_IS_VIEWS_FIXED(parent)) { |
| 745 WidgetGtk* parent_widget = static_cast<WidgetGtk*>( |
| 746 NativeWidget::GetNativeWidgetForNativeView(parent)); |
| 747 parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), |
| 748 bounds.width(), bounds.height()); |
| 749 } else { |
| 750 DCHECK(GTK_IS_FIXED(parent)) |
| 751 << "Parent of WidgetGtk has to be Fixed or ViewsFixed"; |
| 752 // Just request the size if the parent is not WidgetGtk but plain |
| 753 // GtkFixed. WidgetGtk does not know the minimum size so we assume |
| 754 // the caller of the SetBounds knows exactly how big it wants to be. |
| 755 gtk_widget_set_size_request(widget_, bounds.width(), bounds.height()); |
| 756 if (parent != null_parent_) |
| 757 gtk_fixed_move(GTK_FIXED(parent), widget_, bounds.x(), bounds.y()); |
| 758 } |
| 759 } else { |
| 760 if (GTK_WIDGET_MAPPED(widget_)) { |
| 761 // If the widget is mapped (on screen), we can move and resize with one |
| 762 // call, which avoids two separate window manager steps. |
| 763 gdk_window_move_resize(widget_->window, bounds.x(), bounds.y(), |
| 764 bounds.width(), bounds.height()); |
| 765 } |
| 766 |
| 767 // Always call gtk_window_move and gtk_window_resize so that GtkWindow's |
| 768 // geometry info is up-to-date. |
| 769 GtkWindow* gtk_window = GTK_WINDOW(widget_); |
| 770 // TODO: this may need to set an initial size if not showing. |
| 771 // TODO: need to constrain based on screen size. |
| 772 if (!bounds.IsEmpty()) { |
| 773 gtk_window_resize(gtk_window, bounds.width(), bounds.height()); |
| 774 } |
| 775 gtk_window_move(gtk_window, bounds.x(), bounds.y()); |
| 776 } |
| 777 } |
| 778 |
| 779 void WidgetGtk::MoveAbove(Widget* widget) { |
| 780 DCHECK(widget_); |
| 781 DCHECK(widget_->window); |
| 782 // TODO(oshima): gdk_window_restack is not available in gtk2.0, so |
| 783 // we're simply raising the window to the top. We should switch to |
| 784 // gdk_window_restack when we upgrade gtk to 2.18 or up. |
| 785 gdk_window_raise(widget_->window); |
| 786 } |
| 787 |
| 788 void WidgetGtk::SetShape(gfx::NativeRegion region) { |
| 789 DCHECK(widget_); |
| 790 DCHECK(widget_->window); |
| 791 gdk_window_shape_combine_region(widget_->window, region, 0, 0); |
| 792 gdk_region_destroy(region); |
| 793 } |
| 794 |
| 795 void WidgetGtk::Close() { |
| 796 if (!widget_) |
| 797 return; // No need to do anything. |
| 798 |
| 799 // Hide first. |
| 800 Hide(); |
| 801 if (close_widget_factory_.empty()) { |
| 802 // And we delay the close just in case we're on the stack. |
| 803 MessageLoop::current()->PostTask(FROM_HERE, |
| 804 close_widget_factory_.NewRunnableMethod( |
| 805 &WidgetGtk::CloseNow)); |
| 806 } |
| 807 } |
| 808 |
| 809 void WidgetGtk::CloseNow() { |
| 810 if (widget_) { |
| 811 gtk_widget_destroy(widget_); // Triggers OnDestroy(). |
| 812 } |
| 813 } |
| 814 |
| 815 void WidgetGtk::Show() { |
| 816 if (widget_) { |
| 817 gtk_widget_show(widget_); |
| 818 if (widget_->window) |
| 819 gdk_window_raise(widget_->window); |
| 820 } |
| 821 } |
| 822 |
| 823 void WidgetGtk::Hide() { |
| 824 if (widget_) { |
| 825 gtk_widget_hide(widget_); |
| 826 if (widget_->window) |
| 827 gdk_window_lower(widget_->window); |
| 828 } |
| 829 } |
| 830 |
| 831 void WidgetGtk::SetOpacity(unsigned char opacity) { |
| 832 opacity_ = opacity; |
| 833 if (widget_) { |
| 834 // We can only set the opacity when the widget has been realized. |
| 835 gdk_window_set_opacity(widget_->window, static_cast<gdouble>(opacity) / |
| 836 static_cast<gdouble>(255)); |
| 837 } |
| 838 } |
| 839 |
| 840 void WidgetGtk::SetAlwaysOnTop(bool on_top) { |
| 841 DCHECK(type_ != TYPE_CHILD); |
| 842 always_on_top_ = on_top; |
| 843 if (widget_) |
| 844 gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top); |
| 845 } |
| 846 |
| 847 bool WidgetGtk::IsVisible() const { |
| 848 return GTK_WIDGET_VISIBLE(widget_); |
| 849 } |
| 850 |
| 851 bool WidgetGtk::IsActive() const { |
| 852 DCHECK(type_ != TYPE_CHILD); |
| 853 return is_active_; |
| 854 } |
| 855 |
| 856 bool WidgetGtk::IsAccessibleWidget() const { |
| 857 return false; |
| 858 } |
| 859 |
| 860 bool WidgetGtk::ContainsNativeView(gfx::NativeView native_view) const { | 860 bool WidgetGtk::ContainsNativeView(gfx::NativeView native_view) const { |
| 861 // TODO(port) See implementation in WidgetWin::ContainsNativeView. | 861 // TODO(port) See implementation in WidgetWin::ContainsNativeView. |
| 862 NOTREACHED() << "WidgetGtk::ContainsNativeView is not implemented."; | 862 NOTREACHED() << "WidgetGtk::ContainsNativeView is not implemented."; |
| 863 return false; | 863 return false; |
| 864 } | 864 } |
| 865 | 865 |
| 866 void WidgetGtk::RunShellDrag(View* view, | 866 void WidgetGtk::RunShellDrag(View* view, |
| 867 const ui::OSExchangeData& data, | 867 const ui::OSExchangeData& data, |
| 868 int operation) { | 868 int operation) { |
| 869 DoDrag(data, operation); | 869 DoDrag(data, operation); |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 | 1578 |
| 1579 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); | 1579 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); |
| 1580 if (native_widget) | 1580 if (native_widget) |
| 1581 children->insert(native_widget); | 1581 children->insert(native_widget); |
| 1582 gtk_container_foreach(GTK_CONTAINER(native_view), | 1582 gtk_container_foreach(GTK_CONTAINER(native_view), |
| 1583 EnumerateChildWidgetsForNativeWidgets, | 1583 EnumerateChildWidgetsForNativeWidgets, |
| 1584 reinterpret_cast<gpointer>(children)); | 1584 reinterpret_cast<gpointer>(children)); |
| 1585 } | 1585 } |
| 1586 | 1586 |
| 1587 } // namespace views | 1587 } // namespace views |
| OLD | NEW |