summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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*);