summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorbryeung@google.com <bryeung@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 16:40:30 +0000
committerbryeung@google.com <bryeung@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 16:40:30 +0000
commit5fcbeca1c495a7e3ef8e8c6d2d11e275c7430002 (patch)
tree7bd7c6b28d178693b5432c2151ef784930217a5b /views
parent2953b506591d6f4a52e443831d43c0a996b7819a (diff)
downloadchromium_src-5fcbeca1c495a7e3ef8e8c6d2d11e275c7430002.zip
chromium_src-5fcbeca1c495a7e3ef8e8c6d2d11e275c7430002.tar.gz
chromium_src-5fcbeca1c495a7e3ef8e8c6d2d11e275c7430002.tar.bz2
Hijack mouse-related events for TOUCH_UI builds
With this change, which is specifically for TOUCH_UI builds, mouse-related messages are hijacked from the normal Gdk event dispatcher and processed manually in the file touchui/touchui.cc. GdkEvents are converted directly to views events, and dispatched to the RootView. This is preliminary work that will be followed by more elaborate message pump changes, and ultimately is in the spirit of removing Gtk entirely for TOUCH_UI (Chromium-Views-Gtk). Patch from Chad Faragher <wyck@chromium.org> BUG=none TEST=none Review URL: http://codereview.chromium.org/3704005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63368 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/focus/accelerator_handler_touch.cc32
-rw-r--r--views/touchui/touch_event_dispatcher_gtk.cc243
-rw-r--r--views/touchui/touch_event_dispatcher_gtk.h18
-rw-r--r--views/views.gyp9
-rw-r--r--views/widget/widget_gtk.cc6
-rw-r--r--views/widget/widget_gtk.h6
6 files changed, 307 insertions, 7 deletions
diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc
new file mode 100644
index 0000000..ddcdc04
--- /dev/null
+++ b/views/focus/accelerator_handler_touch.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtk/gtk.h>
+
+#include "views/accelerator.h"
+#include "views/focus/accelerator_handler.h"
+#include "views/focus/focus_manager.h"
+#include "views/touchui/touch_event_dispatcher_gtk.h"
+#include "views/widget/widget_gtk.h"
+
+namespace views {
+
+AcceleratorHandler::AcceleratorHandler() {}
+
+bool AcceleratorHandler::Dispatch(GdkEvent* event) {
+ // The logic for handling keyboard accelerators has been moved into
+ // WidgetGtk::OnKeyEvent handler (views/widget/widget_gtk.cc).
+
+ // TODO(wyck): Hijack TouchUI events at other calls to gtk_main_do_event.
+ // There are more places where we call gtk_main_do_event.
+ // In particular: the message pump itself, and the menu controller,
+ // as well as native_menu_gtk.
+ // This function contains the most important one important one, though.
+ if (!DispatchEventForTouchUIGtk(event))
+ gtk_main_do_event(event);
+
+ return true;
+}
+
+} // namespace views
diff --git a/views/touchui/touch_event_dispatcher_gtk.cc b/views/touchui/touch_event_dispatcher_gtk.cc
new file mode 100644
index 0000000..fc4fcd2
--- /dev/null
+++ b/views/touchui/touch_event_dispatcher_gtk.cc
@@ -0,0 +1,243 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains a function that receives a message from the message pump
+// and dispatches that message to the appropriate root view. That function is
+// 'DispatchEventForTouchUIGtk'. (Last function in this file.)
+//
+// The appropriate RootView is determined for each incoming event. The platform
+// specific event is converted to a views event and dispatched directly to the
+// appropriate RootView.
+//
+// This implementation is Gdk specific at the moment, but a future CL will
+// provide a dispatcher that handles events from an X Windows message pump.
+
+// TODO(wyck): Make X Windows versions of all GdkEvent functions.
+// (See individual TODO's below)
+//
+// When we switch the message pump from one that gives us GdkEvents to one that
+// gives us X Windows events, we will need another version of each function.
+// These ones are obviously specific to GdkEvent.
+//
+// Potential names:
+// Maybe DispatchEventForTouchUIGtk will become DispatchEventForTouchUIX11.
+//
+// It may not be necessary to filter events with IsTouchEvent in the X version,
+// because the message pump may pre-filter the message so that we get only
+// touch events and there is nothing to filter out.
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include "views/widget/root_view.h"
+#include "views/widget/widget_gtk.h"
+
+namespace views {
+
+// gets the RootView associated with the GdkEvent.
+//
+// TODO(wyck): Make X Windows version of this function. (see earlier comment)
+static RootView* FindRootViewForGdkEvent(GdkEvent* event) {
+ GdkEventAny* event_any = reinterpret_cast<GdkEventAny*>(event);
+ if (!event_any) {
+ DLOG(WARNING) << "FindRootViewForGdkEvent was passed a null GdkEvent";
+ return NULL;
+ }
+ GdkWindow* gdk_window = event_any->window;
+
+ // and get the parent
+ gpointer data = NULL;
+ gdk_window_get_user_data(gdk_window, &data);
+ GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
+ if (!gtk_widget) {
+ DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
+ return NULL;
+ }
+ WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget);
+
+ if (!widget_gtk) {
+ DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
+ return NULL;
+ }
+ return widget_gtk->GetRootView();
+}
+
+// Specialized dispatch for GDK_BUTTON_PRESS events
+static void DispatchButtonPressGtk(const GdkEventButton& event,
+ RootView* root_view) {
+ // TODO(wyck): may need to remap coordinates:
+ // If so, it's like this:
+ // gdk_window_get_root_origin(dest, &dest_x, &dest_y);
+ // *x = event->x_root - dest_x;
+ // *y = event->y_root - dest_y;
+
+ if (event.type == GDK_2BUTTON_PRESS || event.type == GDK_3BUTTON_PRESS) {
+ // TODO(wyck): decide what to do about 2 button and 3 button press msgs.
+ // You get both a GDK_BUTTON_PRESS and a GDK_2BUTTON_PRESS, so that's
+ // a bit weird.
+ // I'll ignore these events for now.
+ return;
+ }
+
+ MouseEvent mouse_pressed(Event::ET_MOUSE_PRESSED, event.x, event.y,
+ WidgetGtk::GetFlagsForEventButton(event));
+ root_view->OnMousePressed(mouse_pressed);
+}
+
+// Specialized dispatch for GDK_BUTTON_RELEASE events
+static void DispatchButtonReleaseGtk(const GdkEventButton& event,
+ RootView* root_view) {
+ // TODO(wyck): may need to remap coordinates.
+ // If so, it's like this:
+ // gdk_window_get_root_origin(dest, &dest_x, &dest_y);
+ // *x = event->x_root - dest_x;
+ // *y = event->y_root - dest_y;
+
+ MouseEvent mouse_up(Event::ET_MOUSE_RELEASED, event.x, event.y,
+ WidgetGtk::GetFlagsForEventButton(event));
+
+ root_view->OnMouseReleased(mouse_up, false);
+}
+
+// Specialized dispatch for GDK_MOTION_NOTIFY events
+static void DispatchMotionNotifyGtk(const GdkEventMotion& event,
+ RootView* root_view) {
+ // Regarding GDK_POINTER_MOTION_HINT_MASK:
+ // GDK_POINTER_MOTION_HINT_MASK may have been used to reduce the number of
+ // GDK_MOTION_NOTIFY events received. Normally a GDK_MOTION_NOTIFY event is
+ // received each time the mouse moves. But in the hint case, some events are
+ // marked with is_hint TRUE. Without further action after a hint, no more
+ // motion events will be received.
+ // To receive more motion events after a motion hint event, the application
+ // needs to ask for more by calling gdk_event_request_motions().
+ if (event.is_hint) {
+ gdk_event_request_motions(&event);
+ }
+
+ // TODO(wyck): handle dragging
+ // Apparently it's our job to determine the difference between a move and a
+ // drag. We should dispatch OnMouseDragged with ET_MOUSE_DRAGGED instead.
+ // It's unclear what constitutes the dragging state. Which button(s)?
+ int flags = Event::GetFlagsFromGdkState(event.state);
+ MouseEvent mouse_move(Event::ET_MOUSE_MOVED, event.x, event.y, flags);
+ root_view->OnMouseMoved(mouse_move);
+}
+
+// Specialized dispatch for GDK_ENTER_NOTIFY events
+static void DispatchEnterNotifyGtk(const GdkEventCrossing& event,
+ RootView* root_view) {
+ // TODO(wyck): I'm not sure if this is necessary yet
+ int flags = (Event::GetFlagsFromGdkState(event.state) &
+ ~(Event::EF_LEFT_BUTTON_DOWN |
+ Event::EF_MIDDLE_BUTTON_DOWN |
+ Event::EF_RIGHT_BUTTON_DOWN));
+ MouseEvent mouse_move(Event::ET_MOUSE_MOVED, event.x, event.y, flags);
+ root_view->OnMouseMoved(mouse_move);
+}
+
+// Specialized dispatch for GDK_LEAVE_NOTIFY events
+static void DispatchLeaveNotifyGtk(const GdkEventCrossing& event,
+ RootView* root_view) {
+ // TODO(wyck): I'm not sure if this is necessary yet
+ root_view->ProcessOnMouseExited();
+}
+
+// Dispatch an input-related GdkEvent to a RootView
+static void DispatchEventToRootViewGtk(GdkEvent* event, RootView* root_view) {
+ if (!event) {
+ DLOG(WARNING) << "DispatchEventToRootView was passed a null GdkEvent";
+ return;
+ }
+ if (!root_view) {
+ DLOG(WARNING) << "DispatchEventToRootView was passed a null RootView";
+ return;
+ }
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ DispatchButtonPressGtk(*reinterpret_cast<GdkEventButton*>(event),
+ root_view);
+ break;
+ case GDK_BUTTON_RELEASE:
+ DispatchButtonReleaseGtk(*reinterpret_cast<GdkEventButton*>(event),
+ root_view);
+ break;
+ case GDK_MOTION_NOTIFY:
+ DispatchMotionNotifyGtk(*reinterpret_cast<GdkEventMotion*>(event),
+ root_view);
+ break;
+ case GDK_ENTER_NOTIFY:
+ DispatchEnterNotifyGtk(*reinterpret_cast<GdkEventCrossing*>(event),
+ root_view);
+ break;
+ case GDK_LEAVE_NOTIFY:
+ DispatchLeaveNotifyGtk(*reinterpret_cast<GdkEventCrossing*>(event),
+ root_view);
+ break;
+ case GDK_2BUTTON_PRESS:
+ DispatchButtonPressGtk(*reinterpret_cast<GdkEventButton*>(event),
+ root_view);
+ break;
+ case GDK_3BUTTON_PRESS:
+ DispatchButtonPressGtk(*reinterpret_cast<GdkEventButton*>(event),
+ root_view);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+// Called for input-related events only. Dispatches them directly to the
+// associated RootView.
+//
+// TODO(wyck): Make X Windows version of this function. (see earlier comment)
+static void HijackEventForTouchUIGtk(GdkEvent* event) {
+ // TODO(wyck): something like this...
+ RootView* root_view = FindRootViewForGdkEvent(event);
+ if (!root_view) {
+ DLOG(WARNING) << "no RootView found for that GdkEvent";
+ return;
+ }
+ DispatchEventToRootViewGtk(event, root_view);
+}
+
+// returns true if the GdkEvent is a touch-related input event.
+//
+// TODO(wyck): Make X Windows version of this function. (see earlier comment)
+//
+// If the X Windows events are not-prefiltered, then we can provide a filtering
+// function similar to this GdkEvent-specific function. Otherwise this function
+// is not needed at all for the X Windows version.
+static bool IsTouchEventGtk(GdkEvent* event) {
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_MOTION_NOTIFY:
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// This is the public entry point for the touch event dispatcher.
+//
+// Hijacks input-related events and routes them directly to a widget_gtk.
+// Returns false for non-input-related events, in which case the caller is still
+// responsible for dispatching the event.
+//
+// TODO(wyck): Make X Windows version of this function. (see earlier comment)
+bool DispatchEventForTouchUIGtk(GdkEvent* event) {
+ // is this is an input-related event...
+ if (IsTouchEventGtk(event)) {
+ HijackEventForTouchUIGtk(event);
+ return true;
+ } else {
+ return false;
+ }
+}
+} // namespace views
diff --git a/views/touchui/touch_event_dispatcher_gtk.h b/views/touchui/touch_event_dispatcher_gtk.h
new file mode 100644
index 0000000..d80cb96
--- /dev/null
+++ b/views/touchui/touch_event_dispatcher_gtk.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VIEWS_TOUCHUI_TOUCH_EVENT_DISPATCHER_GTK_H_
+#define VIEWS_TOUCHUI_TOUCH_EVENT_DISPATCHER_GTK_H_
+
+namespace views {
+
+// Dispatches a GdkEvent to the appropriate RootView.
+// Returns true if the function dispatched (handled) the event.
+// Returns false if the caller should dispatch the event.
+// FYI: That would typically be done with gtk_main_do_event(event)
+bool DispatchEventForTouchUIGtk(GdkEvent* gdk_event);
+
+} // namespace views
+
+#endif // VIEWS_TOUCHUI_TOUCH_EVENT_DISPATCHER_GTK_H_
diff --git a/views/views.gyp b/views/views.gyp
index af6096d..077d842 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -33,6 +33,7 @@
]}],
['touchui==0', {'sources/': [
['exclude', 'touchui/'],
+ ['exclude', '_(touch)\\.cc$'],
]}],
],
},
@@ -238,6 +239,7 @@
'fill_layout.h',
'focus/accelerator_handler.h',
'focus/accelerator_handler_gtk.cc',
+ 'focus/accelerator_handler_touch.cc',
'focus/accelerator_handler_win.cc',
'focus/external_focus_tracker.cc',
'focus/external_focus_tracker.h',
@@ -265,8 +267,10 @@
'screen_gtk.cc',
'screen_win.cc',
'standard_layout.h',
- 'touchui/gesture_manager.h',
'touchui/gesture_manager.cc',
+ 'touchui/gesture_manager.h',
+ 'touchui/touch_event_dispatcher_gtk.cc',
+ 'touchui/touch_event_dispatcher_gtk.h',
'view.cc',
'view.h',
'view_constants.cc',
@@ -368,6 +372,9 @@
}],
['touchui==1', {
'defines': ['TOUCH_UI=1'],
+ 'sources/': [
+ ['exclude', 'focus/accelerator_handler_gtk.cc'],
+ ],
}],
['OS=="win"', {
'sources!': [
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index 3dfd8cc..badafec 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -908,9 +908,6 @@ bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) {
return handled;
}
-////////////////////////////////////////////////////////////////////////////////
-// WidgetGtk, protected:
-
// static
int WidgetGtk::GetFlagsForEventButton(const GdkEventButton& event) {
int flags = Event::GetFlagsFromGdkState(event.state);
@@ -933,6 +930,9 @@ int WidgetGtk::GetFlagsForEventButton(const GdkEventButton& event) {
return flags;
}
+////////////////////////////////////////////////////////////////////////////////
+// WidgetGtk, protected:
+
void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) {
// Do only return the preferred size for child windows. GtkWindow interprets
// the requisition as a minimum size for top level windows, returning a
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 02d939d..4135c86 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -208,6 +208,9 @@ class WidgetGtk
// Returns true if it's handled by the focus manager.
bool HandleKeyboardEvent(GdkEventKey* event);
+ // Returns the view::Event::flags for a GdkEventButton.
+ static int GetFlagsForEventButton(const GdkEventButton& event);
+
protected:
// If widget containes another widget, translates event coordinates to the
// contained widget's coordinates, else returns original event coordinates.
@@ -229,9 +232,6 @@ class WidgetGtk
return false;
}
- // Returns the view::Event::flags for a GdkEventButton.
- static int GetFlagsForEventButton(const GdkEventButton& event);
-
// Event handlers:
CHROMEGTK_CALLBACK_1(WidgetGtk, gboolean, OnButtonPress, GdkEventButton*);
CHROMEGTK_CALLBACK_1(WidgetGtk, void, OnSizeRequest, GtkRequisition*);