summaryrefslogtreecommitdiffstats
path: root/views/widget/widget_gtk.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-13 16:03:53 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-13 16:03:53 +0000
commit4672de6247fe7a865b2abeaac1b4a76c9369b7a3 (patch)
treeeaa314bbb797dae5152877b1ad170f44d1eb51b4 /views/widget/widget_gtk.cc
parent37ae86f0c4b50dc83b13da17ae1a9ef7083fa76f (diff)
downloadchromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.zip
chromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.tar.gz
chromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.tar.bz2
Split the hierarchy.
* Widget ---- Now recognizes a supplied NativeWidget via InitParams. If this is specified then a default one is not created. Is now created directly rather than using a factory. NativeWidget creation is not performed until Init() is called. This means some functions that rely on a NativeWidget must not be called until _AFTER_ Init() (explains some of the function call reordering in this CL, e.g. moving SetOpacity() until after Init()). ResetLastMouseMovedFlag() moved to this API so that BaseTabStrip can call it in a cross-platform way. Made last remaining unimplemented methods on Widget pass-thru to NativeWidget implementations. * WidgetWin/WidgetGtk ---- The NativeWidget implementations now both require a NativeWidgetDelegate implementation upon construction. This is passed through the constructor by the static factory method NativeWidget::CreateNativeWidget and by subclasses such as WindowWin, BubbleWidgetWin, etc. Some classes that are constructed directly (e.g. LockWindow, in ChromeOS) never have a Widget created for them, so they create the Widget themselves in their base class initializer. Code in these classes (and their WindowWin/WindowGtk, BrowserFrameWin, BrowserFrameGtk subclasses) must now call GetWidget() etc to call Widget API methods since they are no longer subclasses. static_casting to this (and derived) types must now be done on the Widget's native_widget(). GetWindow() is renamed to GetContainingWindow() to avoid naming conflicts. * Window ---- Window is now a subclass of Widget. Now recognizes a supplied NativeWindow via InitParams. If this is specified then a default one is not created. Window::CloseWindow becomes an override of Widget::Close. CloseAllSecondaryWindows() becomes CloseAllSecondaryWidgets() and moves to widget.h IsAppWindow() is removed and replaced by set_is_secondary_widget on Widget. * MenuHost ---- Subclasses Widget now. * TabContentsViewViews ---- It looks like the Gtk-views code here was still using the old implementation of the Native version of this class - i.e. a class that subclassed TabContentsView AND WidgetGtk. A no-no. I had to write NativeTabContentsViewGtk, which is almost identical to NativeTabContentsViewWin with the Gtk bits of TabContentsViewGtk thrown in. * BrowserFrame ---- Platform-specific functionality is now restricted to BrowserFrameWin/BrowserFrameGtk behind a NativeBrowserFrame interface. Construction is exposed via a static factory method on NativeBrowserFrame. BrowserFrame becomes a concrete class that now subclasses Window. As a result, it no longer needs a GetWindow() accessor method, so people with a BrowserFrame* can just call Window methods directly on it. It is constructed directly, replacing the BrowserFrame::Create() method. NativeBrowserFrameDelegate is no longer needed. BrowserFrameChromeos is simpler as a couple of #ifdefs in BrowserFrame, so I got rid of that too. * AutocompletePopupWin/Gtk ---- No longer required. AutocompletePopupContentsView now just uses a Widget directly. * There is some lingering ugliness: - If you set a native_window field on Window::InitParams you must also manually set widget_init_params.native_widget. I will make InitParams do more of this automatically later. - It'd be nice for the ContentsView to be specified via InitParams. I'll get to this later. - NativeBrowserFrame could probably disappear as an interface. It only exists to provide a couple of methods that may be implemented in other ways. - delete_on_destroy should now be an ownership directionality enum. I will do this later. - Secondary-widgetness should somehow be inferred from transience. Later. - set_focus_on_creation for both the NativeWidgets should probably move to Widget if it is really needed. - WidgetWin/Gtk::SetInitialFocus seems like it could move to Widget. - I need to clean up function order in some cases. BUG=72040 TEST=none Review URL: http://codereview.chromium.org/7012006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85269 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget/widget_gtk.cc')
-rw-r--r--views/widget/widget_gtk.cc223
1 files changed, 139 insertions, 84 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index b506dac..bbb0fd5 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -284,9 +284,9 @@ bool WidgetGtk::debug_paint_enabled_ = false;
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, public:
-WidgetGtk::WidgetGtk()
+WidgetGtk::WidgetGtk(internal::NativeWidgetDelegate* delegate)
: is_window_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)),
+ delegate_(delegate),
widget_(NULL),
window_contents_(NULL),
child_(false),
@@ -301,6 +301,7 @@ WidgetGtk::WidgetGtk()
transient_to_parent_(false),
got_initial_focus_in_(false),
has_focus_(false),
+ focus_on_creation_(true),
always_on_top_(false),
is_double_buffered_(false),
should_handle_menu_key_release_(false),
@@ -311,7 +312,6 @@ WidgetGtk::WidgetGtk()
// the widget.
TouchFactory::GetInstance();
#endif
- set_native_widget(this);
static bool installed_message_loop_observer = false;
if (!installed_message_loop_observer) {
installed_message_loop_observer = true;
@@ -325,8 +325,9 @@ WidgetGtk::~WidgetGtk() {
// We need to delete the input method before calling DestroyRootView(),
// because it'll set focus_manager_ to NULL.
input_method_.reset();
- DestroyRootView();
DCHECK(delete_on_destroy_ || widget_ == NULL);
+ if (delete_on_destroy_)
+ delete delegate_;
}
GtkWindow* WidgetGtk::GetTransientParent() const {
@@ -443,7 +444,7 @@ void WidgetGtk::DoDrag(const OSExchangeData& data, int operation) {
}
void WidgetGtk::IsActiveChanged() {
- WidgetDelegate* d = widget_delegate();
+ WidgetDelegate* d = GetWidget()->widget_delegate();
if (d) {
bool a = IsActive();
d->OnWidgetActivated(a);
@@ -451,8 +452,11 @@ void WidgetGtk::IsActiveChanged() {
}
void WidgetGtk::SetInitialFocus() {
- View* v = widget_delegate() ?
- widget_delegate()->GetInitiallyFocusedView() : NULL;
+ if (!focus_on_creation_)
+ return;
+
+ View* v = GetWidget()->widget_delegate() ?
+ GetWidget()->widget_delegate()->GetInitiallyFocusedView() : NULL;
if (v)
v->RequestFocus();
}
@@ -496,52 +500,13 @@ void WidgetGtk::ActiveWindowChanged(GdkWindow* active_window) {
}
if (was_active != IsActive()) {
IsActiveChanged();
- GetRootView()->SchedulePaint();
+ GetWidget()->GetRootView()->SchedulePaint();
}
}
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, Widget implementation:
-gfx::NativeView WidgetGtk::GetNativeView() const {
- return widget_;
-}
-
-gfx::NativeWindow WidgetGtk::GetNativeWindow() const {
- return child_ ? NULL : GTK_WINDOW(widget_);
-}
-
-bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
- NOTIMPLEMENTED();
- return false;
-}
-
-Window* WidgetGtk::GetWindow() {
- return GetWindowImpl(widget_);
-}
-
-const Window* WidgetGtk::GetWindow() const {
- return GetWindowImpl(widget_);
-}
-
-void WidgetGtk::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
- Widget::ViewHierarchyChanged(is_add, parent, child);
- if (drop_target_.get())
- drop_target_->ResetTargetViewIfEquals(child);
-}
-
-void WidgetGtk::NotifyAccessibilityEvent(
- View* view,
- ui::AccessibilityTypes::Event event_type,
- bool send_native_event) {
- // Send the notification to the delegate.
- if (ViewsDelegate::views_delegate)
- ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type);
-
- // In the future if we add native GTK accessibility support, the
- // notification should be sent here.
-}
-
void WidgetGtk::ClearNativeFocus() {
DCHECK(!child_);
if (!GetNativeView()) {
@@ -552,7 +517,7 @@ void WidgetGtk::ClearNativeFocus() {
}
bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
- if (!GetFocusManager())
+ if (!GetWidget()->GetFocusManager())
return false;
const int key_code = key.key_code();
@@ -569,7 +534,7 @@ bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
// VKEY_MENU is triggered by key release event.
// FocusManager::OnKeyEvent() returns false when the key has been consumed.
if (key_code != ui::VKEY_MENU)
- handled = !GetFocusManager()->OnKeyEvent(key);
+ handled = !GetWidget()->GetFocusManager()->OnKeyEvent(key);
else
should_handle_menu_key_release_ = true;
} else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ &&
@@ -577,7 +542,7 @@ bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
// Trigger VKEY_MENU when only this key is pressed and released, and both
// press and release events are not handled by others.
Accelerator accelerator(ui::VKEY_MENU, false, false, false);
- handled = GetFocusManager()->ProcessAccelerator(accelerator);
+ handled = GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
}
return handled;
@@ -626,10 +591,10 @@ void WidgetGtk::RegisterChildExposeHandler(GtkWidget* child) {
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, NativeWidget implementation:
-void WidgetGtk::InitNativeWidget(const InitParams& params) {
+void WidgetGtk::InitNativeWidget(const Widget::InitParams& params) {
SetInitParams(params);
- InitParams modified_params = params;
+ Widget::InitParams modified_params = params;
gfx::NativeView parent = params.parent;
if (params.parent_widget) {
WidgetGtk* parent_gtk =
@@ -766,7 +731,32 @@ void WidgetGtk::InitNativeWidget(const InitParams& params) {
}
Widget* WidgetGtk::GetWidget() {
- return this;
+ return delegate_->AsWidget();
+}
+
+const Widget* WidgetGtk::GetWidget() const {
+ return delegate_->AsWidget();
+}
+
+gfx::NativeView WidgetGtk::GetNativeView() const {
+ return widget_;
+}
+
+gfx::NativeWindow WidgetGtk::GetNativeWindow() const {
+ return child_ ? NULL : GTK_WINDOW(widget_);
+}
+
+Window* WidgetGtk::GetContainingWindow() {
+ return GetWindowImpl(widget_);
+}
+
+const Window* WidgetGtk::GetContainingWindow() const {
+ return GetWindowImpl(widget_);
+}
+
+void WidgetGtk::ViewRemoved(View* view) {
+ if (drop_target_.get())
+ drop_target_->ResetTargetViewIfEquals(view);
}
void WidgetGtk::SetNativeWindowProperty(const char* name, void* value) {
@@ -785,6 +775,13 @@ bool WidgetGtk::IsScreenReaderActive() const {
return false;
}
+void WidgetGtk::SendNativeAccessibilityEvent(
+ View* view,
+ ui::AccessibilityTypes::Event event_type) {
+ // In the future if we add native GTK accessibility support, the
+ // notification should be sent here.
+}
+
void WidgetGtk::SetMouseCapture() {
DCHECK(!HasMouseCapture());
gtk_grab_add(window_contents_);
@@ -801,6 +798,18 @@ bool WidgetGtk::HasMouseCapture() const {
return GTK_WIDGET_HAS_GRAB(window_contents_);
}
+bool WidgetGtk::IsMouseButtonDown() const {
+ bool button_pressed = false;
+ GdkEvent* event = gtk_get_current_event();
+ if (event) {
+ button_pressed = event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS ||
+ event->type == GDK_3BUTTON_PRESS;
+ gdk_event_free(event);
+ }
+ return button_pressed;
+}
+
InputMethod* WidgetGtk::GetInputMethodNative() {
return input_method_.get();
}
@@ -1018,7 +1027,7 @@ void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) {
// preferred size for these would prevents us from setting smaller window
// sizes.
if (child_) {
- gfx::Size size(GetRootView()->GetPreferredSize());
+ gfx::Size size(GetWidget()->GetRootView()->GetPreferredSize());
requisition->width = size.width();
requisition->height = size.height();
}
@@ -1153,7 +1162,7 @@ gboolean WidgetGtk::OnDragMotion(GtkWidget* widget,
gint y,
guint time) {
if (!drop_target_.get())
- drop_target_.reset(new DropTargetGtk(GetRootView(), context));
+ drop_target_.reset(new DropTargetGtk(GetWidget()->GetRootView(), context));
return drop_target_->OnDragMotion(context, x, y, time);
}
@@ -1164,7 +1173,8 @@ gboolean WidgetGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) {
return false;
}
- if (!last_mouse_event_was_move_ && !is_mouse_button_pressed_) {
+ if (!GetWidget()->last_mouse_event_was_move_ &&
+ !GetWidget()->is_mouse_button_pressed_) {
// When a mouse button is pressed gtk generates a leave, enter, press.
// RootView expects to get a mouse move before a press, otherwise enter is
// not set. So we generate a move here.
@@ -1180,13 +1190,13 @@ gboolean WidgetGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) {
MouseEvent mouse_event(TransformEvent(&motion));
delegate_->OnMouseEvent(mouse_event);
}
-
return false;
}
gboolean WidgetGtk::OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) {
- last_mouse_event_was_move_ = false;
- if (!HasMouseCapture() && !is_mouse_button_pressed_) {
+ GetWidget()->ResetLastMouseMoveFlag();
+
+ if (!HasMouseCapture() && !GetWidget()->is_mouse_button_pressed_) {
MouseEvent mouse_event(TransformEvent(event));
delegate_->OnMouseEvent(mouse_event);
}
@@ -1346,10 +1356,6 @@ void WidgetGtk::HandleGtkGrabBroke() {
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, private:
-RootView* WidgetGtk::CreateRootView() {
- return new RootView(this);
-}
-
gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
DCHECK(window_contents_ && window_contents_->window);
return GDK_WINDOW_XID(window_contents_->window);
@@ -1392,28 +1398,24 @@ void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) {
gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
}
-void WidgetGtk::SetInitParams(const InitParams& params) {
+void WidgetGtk::SetInitParams(const Widget::InitParams& params) {
DCHECK(!GetNativeView());
delete_on_destroy_ = params.delete_on_destroy;
child_ = params.child;
+ // TODO(beng): The secondary checks here actually obviate the need for
+ // params.transient but that's only because WidgetGtk considers
+ // any top-level widget to be a transient widget. We will probably
+ // want to ammend this assumption at some point.
+ if (params.transient || params.parent || params.parent_widget)
+ transient_to_parent_ = true;
if (params.transparent)
MakeTransparent();
if (!params.accept_events && !child_)
ignore_events_ = true;
if (params.double_buffer)
EnableDoubleBuffer(true);
-
- if (params.type == InitParams::TYPE_MENU) {
- GdkEvent* event = gtk_get_current_event();
- if (event) {
- is_mouse_button_pressed_ = event->type == GDK_BUTTON_PRESS ||
- event->type == GDK_2BUTTON_PRESS ||
- event->type == GDK_3BUTTON_PRESS;
- gdk_event_free(event);
- }
- }
}
gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
@@ -1460,13 +1462,13 @@ Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) {
WidgetGtk* widget_gtk = static_cast<WidgetGtk*>(
NativeWidget::GetNativeWidgetForNativeView(parent));
if (widget_gtk && widget_gtk->is_window_)
- return static_cast<WindowGtk*>(widget_gtk);
+ return static_cast<WindowGtk*>(widget_gtk)->GetWindow();
parent = gtk_widget_get_parent(parent);
}
return NULL;
}
-void WidgetGtk::CreateGtkWidget(const InitParams& params) {
+void WidgetGtk::CreateGtkWidget(const Widget::InitParams& params) {
// We turn off double buffering for two reasons:
// 1. We draw to a canvas then composite to the screen, which means we're
// doing our own double buffering already.
@@ -1520,8 +1522,8 @@ void WidgetGtk::CreateGtkWidget(const InitParams& params) {
} else {
// Use our own window class to override GtkWindow's move_focus method.
widget_ = gtk_views_window_new(
- params.type == InitParams::TYPE_WINDOW ? GTK_WINDOW_TOPLEVEL
- : GTK_WINDOW_POPUP);
+ params.type == Widget::InitParams::TYPE_WINDOW ? GTK_WINDOW_TOPLEVEL
+ : GTK_WINDOW_POPUP);
gtk_widget_set_name(widget_, "views-gtkwidget-window");
if (transient_to_parent_) {
gtk_window_set_transient_for(GTK_WINDOW(widget_),
@@ -1560,7 +1562,7 @@ void WidgetGtk::CreateGtkWidget(const InitParams& params) {
gtk_container_add(GTK_CONTAINER(widget_), window_contents_);
gtk_widget_show(window_contents_);
g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey,
- static_cast<Widget*>(this));
+ static_cast<WidgetGtk*>(this));
if (transparent_)
ConfigureWidgetForTransparentBackground(NULL);
@@ -1643,11 +1645,6 @@ void WidgetGtk::DrawTransparentBackground(GtkWidget* widget,
// Widget, public:
// static
-Widget* Widget::CreateWidget() {
- return new WidgetGtk();
-}
-
-// static
void Widget::NotifyLocaleChanged() {
GList *window_list = gtk_window_list_toplevels();
for (GList* element = window_list; element; element = g_list_next(element)) {
@@ -1660,6 +1657,22 @@ void Widget::NotifyLocaleChanged() {
}
// static
+void Widget::CloseAllSecondaryWidgets() {
+ GList* windows = gtk_window_list_toplevels();
+ for (GList* window = windows; window;
+ window = g_list_next(window)) {
+ NativeWidget* native_widget = NativeWidget::GetNativeWidgetForNativeView(
+ GTK_WIDGET(window->data));
+ if (native_widget) {
+ Widget* widget = native_widget->GetWidget();
+ if (widget->is_secondary_widget())
+ widget->Close();
+ }
+ }
+ g_list_free(windows);
+}
+
+// static
bool Widget::ConvertRect(const Widget* source,
const Widget* target,
gfx::Rect* rect) {
@@ -1689,6 +1702,12 @@ bool Widget::ConvertRect(const Widget* source,
// NativeWidget, public:
// static
+NativeWidget* NativeWidget::CreateNativeWidget(
+ internal::NativeWidgetDelegate* delegate) {
+ return new WidgetGtk(delegate);
+}
+
+// static
NativeWidget* NativeWidget::GetNativeWidgetForNativeView(
gfx::NativeView native_view) {
if (!native_view)
@@ -1740,4 +1759,40 @@ void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view,
reinterpret_cast<gpointer>(children));
}
+// static
+void NativeWidget::ReparentNativeView(gfx::NativeView native_view,
+ gfx::NativeView new_parent) {
+ if (!native_view)
+ return;
+
+ gfx::NativeView previous_parent = gtk_widget_get_parent(native_view);
+ if (previous_parent == new_parent)
+ return;
+
+ NativeWidgets widgets;
+ GetAllNativeWidgets(native_view, &widgets);
+
+ // First notify all the widgets that they are being disassociated
+ // from their previous parent.
+ for (NativeWidgets::iterator it = widgets.begin();
+ it != widgets.end(); ++it) {
+ // TODO(beng): Rename this notification to NotifyNativeViewChanging()
+ // and eliminate the bool parameter.
+ (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(false,
+ previous_parent);
+ }
+
+ if (gtk_widget_get_parent(native_view))
+ gtk_widget_reparent(native_view, new_parent);
+ else
+ gtk_container_add(GTK_CONTAINER(new_parent), native_view);
+
+ // And now, notify them that they have a brand new parent.
+ for (NativeWidgets::iterator it = widgets.begin();
+ it != widgets.end(); ++it) {
+ (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(true,
+ new_parent);
+ }
+}
+
} // namespace views