summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/app_base.gypi6
-rw-r--r--app/keyboard_code_conversion_x.cc163
-rw-r--r--app/keyboard_code_conversion_x.h18
-rw-r--r--base/base.gypi1
-rw-r--r--base/message_loop.h7
-rw-r--r--base/message_pump_glib.cc4
-rw-r--r--base/message_pump_glib.h4
-rw-r--r--base/message_pump_glib_x.cc27
-rw-r--r--base/message_pump_glib_x_dispatch.h28
-rw-r--r--chrome/browser/chromeos/views/native_menu_domui.cc10
-rw-r--r--chrome/browser/chromeos/views/native_menu_domui.h7
-rw-r--r--views/controls/menu/menu_controller.cc13
-rw-r--r--views/controls/menu/menu_controller.h4
-rw-r--r--views/controls/menu/native_menu_gtk.cc10
-rw-r--r--views/controls/menu/native_menu_gtk.h3
-rw-r--r--views/controls/menu/nested_dispatcher_gtk.cc15
-rw-r--r--views/controls/menu/nested_dispatcher_gtk.h10
-rw-r--r--views/event.h13
-rw-r--r--views/event_x.cc117
-rw-r--r--views/focus/accelerator_handler.h9
-rw-r--r--views/focus/accelerator_handler_gtk.cc3
-rw-r--r--views/focus/accelerator_handler_touch.cc91
-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.gyp4
25 files changed, 542 insertions, 286 deletions
diff --git a/app/app_base.gypi b/app/app_base.gypi
index 2866bfd..2c04d38 100644
--- a/app/app_base.gypi
+++ b/app/app_base.gypi
@@ -153,6 +153,8 @@
'keyboard_code_conversion_mac.h',
'keyboard_code_conversion_win.cc',
'keyboard_code_conversion_win.h',
+ 'keyboard_code_conversion_x.cc',
+ 'keyboard_code_conversion_x.h',
'keyboard_codes.h',
'keyboard_codes_win.h',
'keyboard_codes_posix.h',
@@ -364,6 +366,8 @@
'event_synthesis_gtk.h',
'keyboard_code_conversion_gtk.cc',
'keyboard_code_conversion_gtk.h',
+ 'keyboard_code_conversion_x.cc',
+ 'keyboard_code_conversion_x.h',
'keyboard_codes_win.h',
],
}],
@@ -386,6 +390,8 @@
'keyboard_code_conversion_gtk.h',
'keyboard_code_conversion_mac.mm',
'keyboard_code_conversion_mac.h',
+ 'keyboard_code_conversion_x.cc',
+ 'keyboard_code_conversion_x.h',
'keyboard_codes_posix.h',
],
}],
diff --git a/app/keyboard_code_conversion_x.cc b/app/keyboard_code_conversion_x.cc
new file mode 100644
index 0000000..679423b
--- /dev/null
+++ b/app/keyboard_code_conversion_x.cc
@@ -0,0 +1,163 @@
+// 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 "app/keyboard_code_conversion_x.h"
+
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+
+#include "base/logging.h"
+
+namespace app {
+
+// Get an app::KeyboardCode from an X keyevent
+KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev) {
+ KeySym keysym = XLookupKeysym(&xev->xkey, 0);
+
+ // TODO(sad): Have |keysym| go through the X map list?
+
+ switch (keysym) {
+ case XK_BackSpace:
+ return VKEY_BACK;
+ case XK_Tab:
+ return VKEY_TAB;
+ case XK_Linefeed:
+ case XK_Return:
+ return VKEY_RETURN;
+ case XK_Clear:
+ return VKEY_CLEAR;
+ case XK_KP_Space:
+ case XK_space:
+ return VKEY_SPACE;
+ case XK_Home:
+ case XK_KP_Home:
+ return VKEY_HOME;
+ case XK_End:
+ case XK_KP_End:
+ return VKEY_END;
+ case XK_Left:
+ case XK_KP_Left:
+ return VKEY_LEFT;
+ case XK_Right:
+ case XK_KP_Right:
+ return VKEY_RIGHT;
+ case XK_Down:
+ case XK_KP_Down:
+ return VKEY_DOWN;
+ case XK_Up:
+ case XK_KP_Up:
+ return VKEY_UP;
+ case XK_Control_L:
+ return VKEY_LCONTROL;
+ case XK_Control_R:
+ return VKEY_RCONTROL;
+ case XK_Escape:
+ return VKEY_ESCAPE;
+ case XK_A:
+ case XK_a:
+ return VKEY_A;
+ case XK_B:
+ case XK_b:
+ return VKEY_B;
+ case XK_C:
+ case XK_c:
+ return VKEY_C;
+ case XK_D:
+ case XK_d:
+ return VKEY_D;
+ case XK_E:
+ case XK_e:
+ return VKEY_E;
+ case XK_F:
+ case XK_f:
+ return VKEY_F;
+ case XK_G:
+ case XK_g:
+ return VKEY_G;
+ case XK_H:
+ case XK_h:
+ return VKEY_H;
+ case XK_I:
+ case XK_i:
+ return VKEY_I;
+ case XK_J:
+ case XK_j:
+ return VKEY_J;
+ case XK_K:
+ case XK_k:
+ return VKEY_K;
+ case XK_L:
+ case XK_l:
+ return VKEY_L;
+ case XK_M:
+ case XK_m:
+ return VKEY_M;
+ case XK_N:
+ case XK_n:
+ return VKEY_N;
+ case XK_O:
+ case XK_o:
+ return VKEY_O;
+ case XK_P:
+ case XK_p:
+ return VKEY_P;
+ case XK_Q:
+ case XK_q:
+ return VKEY_Q;
+ case XK_R:
+ case XK_r:
+ return VKEY_R;
+ case XK_S:
+ case XK_s:
+ return VKEY_S;
+ case XK_T:
+ case XK_t:
+ return VKEY_T;
+ case XK_U:
+ case XK_u:
+ return VKEY_U;
+ case XK_V:
+ case XK_v:
+ return VKEY_V;
+ case XK_W:
+ case XK_w:
+ return VKEY_W;
+ case XK_X:
+ case XK_x:
+ return VKEY_X;
+ case XK_Y:
+ case XK_y:
+ return VKEY_Y;
+ case XK_Z:
+ case XK_z:
+ return VKEY_Z;
+ case XK_0:
+ return VKEY_0;
+ case XK_1:
+ return VKEY_1;
+ case XK_2:
+ return VKEY_2;
+ case XK_3:
+ return VKEY_3;
+ case XK_4:
+ return VKEY_4;
+ case XK_5:
+ return VKEY_5;
+ case XK_6:
+ return VKEY_6;
+ case XK_7:
+ return VKEY_7;
+ case XK_8:
+ return VKEY_8;
+ case XK_9:
+ return VKEY_9;
+
+ // TODO(sad): A lot of keycodes are still missing.
+ }
+
+ DLOG(WARNING) << "Unknown keycode: " << keysym;
+ return VKEY_UNKNOWN;
+}
+
+} // namespace app
diff --git a/app/keyboard_code_conversion_x.h b/app/keyboard_code_conversion_x.h
new file mode 100644
index 0000000..748ef86
--- /dev/null
+++ b/app/keyboard_code_conversion_x.h
@@ -0,0 +1,18 @@
+// 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.
+
+#ifndef APP_KEYBOARD_CODE_CONVERSION_X_H_
+#define APP_KEYBOARD_CODE_CONVERSION_X_H_
+
+#include "app/keyboard_codes_posix.h"
+
+typedef union _XEvent XEvent;
+
+namespace app {
+
+KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev);
+
+} // namespace app
+
+#endif // APP_KEYBOARD_CODE_CONVERSION_X_H_
diff --git a/base/base.gypi b/base/base.gypi
index 9a32325..690b852 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -456,6 +456,7 @@
'message_pump_glib.h',
'message_pump_glib_x.cc',
'message_pump_glib_x.h',
+ 'message_pump_glib_x_dispatch.h',
'message_pump_libevent.cc',
'message_pump_libevent.h',
'message_pump_mac.h',
diff --git a/base/message_loop.h b/base/message_loop.h
index 37e4b81..f4b1a4d 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -26,6 +26,9 @@
#include "base/message_pump_glib.h"
#endif
#endif
+#if defined(TOUCH_UI)
+#include "base/message_pump_glib_x_dispatch.h"
+#endif
namespace base {
class Histogram;
@@ -290,7 +293,11 @@ class MessageLoop : public base::MessagePump::Delegate {
typedef base::MessagePumpWin::Dispatcher Dispatcher;
typedef base::MessagePumpForUI::Observer Observer;
#elif !defined(OS_MACOSX)
+#if defined(TOUCH_UI)
+ typedef base::MessagePumpGlibXDispatcher Dispatcher;
+#else
typedef base::MessagePumpForUI::Dispatcher Dispatcher;
+#endif
typedef base::MessagePumpForUI::Observer Observer;
#endif
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index ad6d177..616c24c 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -303,6 +303,10 @@ void MessagePumpForUI::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
+MessagePumpForUI::Dispatcher* MessagePumpForUI::GetDispatcher() {
+ return state_ ? state_->dispatcher : NULL;
+}
+
void MessagePumpForUI::WillProcessEvent(GdkEvent* event) {
FOR_EACH_OBSERVER(Observer, observers_, WillProcessEvent(event));
}
diff --git a/base/message_pump_glib.h b/base/message_pump_glib.h
index 31d37c0..d8cbbda 100644
--- a/base/message_pump_glib.h
+++ b/base/message_pump_glib.h
@@ -88,6 +88,10 @@ class MessagePumpForUI : public MessagePump {
// some task before/after calling the default handler (EventDispatcher).
virtual void DispatchEvents(GdkEvent* event);
+ protected:
+ // Returns the dispatcher for the current run state (|state_->dispatcher|).
+ Dispatcher* GetDispatcher();
+
private:
// We may make recursive calls to Run, so we save state that needs to be
// separate between them in this structure type.
diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc
index f77f61d..675774e 100644
--- a/base/message_pump_glib_x.cc
+++ b/base/message_pump_glib_x.cc
@@ -7,6 +7,8 @@
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
+#include "base/message_pump_glib_x_dispatch.h"
+
namespace {
gboolean PlaceholderDispatch(GSource* source,
@@ -41,14 +43,16 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
if (capture_x_events_[xev.type]) {
XNextEvent(display, &xev);
- DLOG(INFO) << "nom noming event";
+ bool processed = static_cast<MessagePumpGlibXDispatcher*>
+ (GetDispatcher())->Dispatch(&xev);
- // TODO(sad): Create a GdkEvent from |xev| and pass it on to
- // EventDispatcherX. The ultimate goal is to create a views::Event from
- // |xev| and send it to a rootview. When done, the preceding DLOG will be
- // removed.
+ if (!processed) {
+ DLOG(WARNING) << "Event (" << xev.type << ") not handled.";
+ }
} else {
- // TODO(sad): A couple of extra events can still sneak in during this
+ // TODO(sad): A couple of extra events can still sneak in during this.
+ // Those should be sent back to the X queue from the dispatcher
+ // EventDispatcherX.
g_main_context_iteration(context, FALSE);
}
}
@@ -81,6 +85,15 @@ void MessagePumpGlibX::InitializeEventsToCapture(void) {
capture_x_events_[KeyRelease] = true;
capture_gdk_events_[GDK_KEY_RELEASE] = true;
+
+ capture_x_events_[ButtonPress] = true;
+ capture_gdk_events_[GDK_BUTTON_PRESS] = true;
+
+ capture_x_events_[ButtonRelease] = true;
+ capture_gdk_events_[GDK_BUTTON_RELEASE] = true;
+
+ capture_x_events_[MotionNotify] = true;
+ capture_gdk_events_[GDK_MOTION_NOTIFY] = true;
}
void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
@@ -94,7 +107,7 @@ void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
// TODO(sad): An X event is caught by the GDK handler. Put it back in the
// X queue so that we catch it in the next iteration. When done, the
// following DLOG statement will be removed.
- DLOG(INFO) << "GDK ruined it!!";
+ DLOG(WARNING) << "GDK received an event it shouldn't have";
}
}
diff --git a/base/message_pump_glib_x_dispatch.h b/base/message_pump_glib_x_dispatch.h
new file mode 100644
index 0000000..95364a2
--- /dev/null
+++ b/base/message_pump_glib_x_dispatch.h
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef BASE_MESSAGE_PUMP_GLIB_X_DISPATCH_H
+#define BASE_MESSAGE_PUMP_GLIB_X_DISPATCH_H
+
+#include "base/message_pump.h"
+#include "base/message_pump_glib.h"
+
+typedef union _XEvent XEvent;
+
+namespace base {
+
+// The message pump used for TOUCH_UI on linux is MessagePumpGlibX, which can
+// dispatch both GdkEvents* and XEvents* captured directly from X.
+// MessagePumpForUI::Dispatcher provides the mechanism for dispatching
+// GdkEvents. This class provides additional mechanism for dispatching XEvents.
+class MessagePumpGlibXDispatcher : public MessagePumpForUI::Dispatcher {
+ public:
+ // Dispatches the event. If true is returned processing continues as
+ // normal. If false is returned, the nested loop exits immediately.
+ virtual bool Dispatch(XEvent* xevent) = 0;
+};
+
+} // namespace base
+
+#endif // BASE_MESSAGE_PUMP_GLIB_X_DISPATCH_H
diff --git a/chrome/browser/chromeos/views/native_menu_domui.cc b/chrome/browser/chromeos/views/native_menu_domui.cc
index d1a0458..5ce238c 100644
--- a/chrome/browser/chromeos/views/native_menu_domui.cc
+++ b/chrome/browser/chromeos/views/native_menu_domui.cc
@@ -22,6 +22,10 @@
#include "views/controls/menu/native_menu_gtk.h"
#include "views/controls/menu/nested_dispatcher_gtk.h"
+#if defined(TOUCH_UI)
+#include "views/focus/accelerator_handler.h"
+#endif
+
namespace {
using chromeos::NativeMenuDOMUI;
@@ -244,6 +248,12 @@ bool NativeMenuDOMUI::Dispatch(GdkEvent* event) {
return true;
}
+#if defined(TOUCH_UI)
+bool NativeMenuDOMUI::Dispatch(XEvent* xevent) {
+ return views::DispatchXEvent(xevent);
+}
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// NativeMenuDOMUI, MenuControl implementation:
diff --git a/chrome/browser/chromeos/views/native_menu_domui.h b/chrome/browser/chromeos/views/native_menu_domui.h
index fb03604e..03a6b92 100644
--- a/chrome/browser/chromeos/views/native_menu_domui.h
+++ b/chrome/browser/chromeos/views/native_menu_domui.h
@@ -27,6 +27,10 @@ namespace views {
class NestedDispatcherGtk;
} // namespace views;
+#if defined(TOUCH_UI)
+typedef union _XEvent XEvent;
+#endif
+
namespace chromeos {
class MenuLocator;
@@ -59,6 +63,9 @@ class NativeMenuDOMUI : public views::MenuWrapper,
// Overriden from MessageLoopForUI::Dispatcher:
virtual bool Dispatch(GdkEvent* event);
+#if defined(TOUCH_UI)
+ virtual bool Dispatch(XEvent* xevent);
+#endif
// Overriden from DOMUIMenuControl;
virtual menus::MenuModel* GetMenuModel() { return model_; }
diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc
index affddeb..e0701a2 100644
--- a/views/controls/menu/menu_controller.cc
+++ b/views/controls/menu/menu_controller.cc
@@ -25,6 +25,10 @@
#include "app/keyboard_code_conversion_gtk.h"
#endif
+#if defined(TOUCH_UI)
+#include "views/focus/accelerator_handler.h"
+#endif
+
using base::Time;
using base::TimeDelta;
@@ -848,12 +852,19 @@ bool MenuController::Dispatch(GdkEvent* event) {
break;
}
- // We don not want Gtk to handle keyboard events, otherwise if they get
+ // We don't want Gtk to handle keyboard events, otherwise if they get
// handled by Gtk, unexpected behavior may occur. For example Tab key
// may cause unexpected focus traversing.
gtk_main_do_event(event);
return exit_type_ == EXIT_NONE;
}
+
+#if defined(TOUCH_UI)
+bool MenuController::Dispatch(XEvent* xev) {
+ return DispatchXEvent(xev);
+}
+#endif
+
#endif
bool MenuController::OnKeyDown(int key_code
diff --git a/views/controls/menu/menu_controller.h b/views/controls/menu/menu_controller.h
index fe379b8..539c2ee 100644
--- a/views/controls/menu/menu_controller.h
+++ b/views/controls/menu/menu_controller.h
@@ -192,6 +192,10 @@ class MenuController : public MessageLoopForUI::Dispatcher {
virtual bool Dispatch(GdkEvent* event);
#endif
+#if defined(TOUCH_UI)
+ virtual bool Dispatch(XEvent* xevent);
+#endif
+
// Key processing. The return value of this is returned from Dispatch.
// In other words, if this returns false (which happens if escape was
// pressed, or a matching mnemonic was found) the message loop returns.
diff --git a/views/controls/menu/native_menu_gtk.cc b/views/controls/menu/native_menu_gtk.cc
index 12f73da..45c64c0 100644
--- a/views/controls/menu/native_menu_gtk.cc
+++ b/views/controls/menu/native_menu_gtk.cc
@@ -23,6 +23,10 @@
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/nested_dispatcher_gtk.h"
+#if defined(TOUCH_UI)
+#include "views/focus/accelerator_handler.h"
+#endif
+
namespace {
const char kPositionString[] = "position";
@@ -220,6 +224,12 @@ void NativeMenuGtk::SetMinimumWidth(int width) {
gtk_widget_set_size_request(menu_, width, -1);
}
+#if defined(TOUCH_UI)
+bool NativeMenuGtk::Dispatch(XEvent* xevent) {
+ return DispatchXEvent(xevent);
+}
+#endif
+
bool NativeMenuGtk::Dispatch(GdkEvent* event) {
if (menu_hidden_) {
// The menu has been closed but the message loop is still nested. Don't
diff --git a/views/controls/menu/native_menu_gtk.h b/views/controls/menu/native_menu_gtk.h
index 6145925..4278d2c 100644
--- a/views/controls/menu/native_menu_gtk.h
+++ b/views/controls/menu/native_menu_gtk.h
@@ -51,6 +51,9 @@ class NativeMenuGtk : public MenuWrapper,
// Overriden from MessageLoopForUI::Dispatcher:
virtual bool Dispatch(GdkEvent* event);
+#if defined(TOUCH_UI)
+ virtual bool Dispatch(XEvent* xevent);
+#endif
private:
CHROMEGTK_CALLBACK_0(NativeMenuGtk, void, OnMenuHidden);
diff --git a/views/controls/menu/nested_dispatcher_gtk.cc b/views/controls/menu/nested_dispatcher_gtk.cc
index 856b0a8..ba7a7b2 100644
--- a/views/controls/menu/nested_dispatcher_gtk.cc
+++ b/views/controls/menu/nested_dispatcher_gtk.cc
@@ -4,6 +4,10 @@
#include "views/controls/menu/nested_dispatcher_gtk.h"
+#if defined(TOUCH_UI)
+#include "views/focus/accelerator_handler.h"
+#endif
+
namespace views {
NestedDispatcherGtk::NestedDispatcherGtk(MessageLoopForUI::Dispatcher* creator,
@@ -30,10 +34,21 @@ void NestedDispatcherGtk::CreatorDestroyed() {
bool NestedDispatcherGtk::Dispatch(GdkEvent* event) {
if (creator_ != NULL) {
+#if defined(TOUCH_UI)
+ return static_cast<base::MessagePumpForUI::Dispatcher*>
+ (creator_)->Dispatch(event);
+#else
return creator_->Dispatch(event);
+#endif
} else {
return false;
}
}
+#if defined(TOUCH_UI)
+bool NestedDispatcherGtk::Dispatch(XEvent* xevent) {
+ return creator_ ? creator_->Dispatch(xevent) : false;
+}
+#endif
+
} // namespace views
diff --git a/views/controls/menu/nested_dispatcher_gtk.h b/views/controls/menu/nested_dispatcher_gtk.h
index 06f54fa..f17e9a4 100644
--- a/views/controls/menu/nested_dispatcher_gtk.h
+++ b/views/controls/menu/nested_dispatcher_gtk.h
@@ -3,11 +3,15 @@
// found in the LICENSE file.
#ifndef VIEWS_CONTROLS_MENU_NESTED_DISPATCHER_GTK_H_
-#define VIEWS_CONTROLS_MENU_NATIVE_DISPATCHER_GTK_H_
+#define VIEWS_CONTROLS_MENU_NESTED_DISPATCHER_GTK_H_
#pragma once
#include "base/message_loop.h"
+#if defined(TOUCH_UI)
+typedef union _XEvent XEvent;
+#endif
+
namespace views {
// A nested dispatcher that can out-live the creator of this
@@ -36,6 +40,10 @@ class NestedDispatcherGtk : public MessageLoopForUI::Dispatcher {
// Overriden from MessageLoopForUI::Dispatcher:
virtual bool Dispatch(GdkEvent* event);
+#if defined(TOUCH_UI)
+ virtual bool Dispatch(XEvent* xevent);
+#endif
+
// Creator of the nested loop.
MessageLoopForUI::Dispatcher* creator_;
diff --git a/views/event.h b/views/event.h
index f02bd1b..9da3945 100644
--- a/views/event.h
+++ b/views/event.h
@@ -13,6 +13,9 @@
#if defined(OS_LINUX)
typedef struct _GdkEventKey GdkEventKey;
#endif
+#if defined(TOUCH_UI)
+typedef union _XEvent XEvent;
+#endif
class OSExchangeData;
@@ -222,6 +225,11 @@ class MouseEvent : public LocatedEvent {
// from 'from' coordinate system to 'to' coordinate system
MouseEvent(const MouseEvent& model, View* from, View* to);
+#if defined(TOUCH_UI)
+ // Create a mouse event from an X mouse event.
+ explicit MouseEvent(XEvent* xevent);
+#endif
+
// Conveniences to quickly test what button is down
bool IsOnlyLeftMouseButton() const {
return (GetFlags() & EF_LEFT_BUTTON_DOWN) &&
@@ -318,6 +326,11 @@ class KeyEvent : public Event {
explicit KeyEvent(GdkEventKey* event);
#endif
+#if defined(TOUCH_UI)
+ // Create a key event from an X key event.
+ explicit KeyEvent(XEvent* xevent);
+#endif
+
// This returns a VKEY_ value as defined in app/keyboard_codes.h which is
// the Windows value.
// On GTK, you can use the methods in keyboard_code_conversion_gtk.cc to
diff --git a/views/event_x.cc b/views/event_x.cc
new file mode 100644
index 0000000..69101bb
--- /dev/null
+++ b/views/event_x.cc
@@ -0,0 +1,117 @@
+// 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 "views/event.h"
+
+#include <gdk/gdkx.h>
+
+#include "app/keyboard_code_conversion_x.h"
+#include "views/widget/root_view.h"
+#include "views/widget/widget_gtk.h"
+
+namespace views {
+
+namespace {
+
+int GetEventFlagsFromXState(unsigned int state) {
+ int flags = 0;
+ if (state & ControlMask)
+ flags |= Event::EF_CONTROL_DOWN;
+ if (state & ShiftMask)
+ flags |= Event::EF_SHIFT_DOWN;
+ if (state & Mod1Mask)
+ flags |= Event::EF_ALT_DOWN;
+ if (state & Button1Mask)
+ flags |= Event::EF_LEFT_BUTTON_DOWN;
+ if (state & Button2Mask)
+ flags |= Event::EF_MIDDLE_BUTTON_DOWN;
+ if (state & Button3Mask)
+ flags |= Event::EF_RIGHT_BUTTON_DOWN;
+
+ return flags;
+}
+
+// Get the event flag for the button in XButtonEvent. During a KeyPress event,
+// |state| in XButtonEvent does not include the button that has just been
+// pressed. Instead |state| contains flags for the buttons (if any) that had
+// already been pressed before the current button, and |button| stores the most
+// current pressed button. So, if you press down left mouse button, and while
+// pressing it down, press down the right mouse button, then for the latter
+// event, |state| would have Button1Mask set but not Button3Mask, and |button|
+// would be 3.
+int GetEventFlagsForButton(int button) {
+ switch (button) {
+ case 1:
+ return Event::EF_LEFT_BUTTON_DOWN;
+ case 2:
+ return Event::EF_MIDDLE_BUTTON_DOWN;
+ case 3:
+ return Event::EF_RIGHT_BUTTON_DOWN;
+ }
+
+ DLOG(WARNING) << "Unexpected button (" << button << ") received.";
+ return 0;
+}
+
+Event::EventType GetMouseEventType(XEvent* xev) {
+ switch (xev->type) {
+ case ButtonPress:
+ return Event::ET_MOUSE_PRESSED;
+ case ButtonRelease:
+ return Event::ET_MOUSE_RELEASED;
+ case MotionNotify:
+ if (xev->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) {
+ return Event::ET_MOUSE_DRAGGED;
+ }
+ return Event::ET_MOUSE_MOVED;
+ }
+
+ return Event::ET_UNKNOWN;
+}
+
+gfx::Point GetMouseEventLocation(XEvent* xev) {
+ switch (xev->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ return gfx::Point(xev->xbutton.x, xev->xbutton.y);
+
+ case MotionNotify:
+ return gfx::Point(xev->xmotion.x, xev->xmotion.y);
+ }
+
+ return gfx::Point();
+}
+
+int GetMouseEventFlags(XEvent* xev) {
+ switch (xev->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ return GetEventFlagsFromXState(xev->xbutton.state) |
+ GetEventFlagsForButton(xev->xbutton.button);
+
+ case MotionNotify:
+ return GetEventFlagsFromXState(xev->xmotion.state);
+ }
+
+ return 0;
+}
+
+} // namespace
+
+KeyEvent::KeyEvent(XEvent* xev)
+ : Event(xev->type == KeyPress ?
+ Event::ET_KEY_PRESSED : Event::ET_KEY_RELEASED,
+ GetEventFlagsFromXState(xev->xkey.state)),
+ key_code_(app::KeyboardCodeFromXKeyEvent(xev)),
+ repeat_count_(0),
+ message_flags_(0) {
+}
+
+MouseEvent::MouseEvent(XEvent* xev)
+ : LocatedEvent(GetMouseEventType(xev),
+ GetMouseEventLocation(xev),
+ GetMouseEventFlags(xev)) {
+}
+
+} // namespace views
diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h
index 3726d96..088f3f1 100644
--- a/views/focus/accelerator_handler.h
+++ b/views/focus/accelerator_handler.h
@@ -18,6 +18,12 @@
namespace views {
+#if defined(TOUCH_UI)
+// Dispatch an XEvent to the RootView. Return true if the event was dispatched
+// and handled, false otherwise.
+bool DispatchXEvent(XEvent* xevent);
+#endif
+
// This class delegates the key messages to the associated FocusManager class
// for the window that is receiving these messages for accelerator processing.
class AcceleratorHandler : public MessageLoopForUI::Dispatcher {
@@ -29,6 +35,9 @@ class AcceleratorHandler : public MessageLoopForUI::Dispatcher {
virtual bool Dispatch(const MSG& msg);
#else
virtual bool Dispatch(GdkEvent* event);
+#if defined(TOUCH_UI)
+ virtual bool Dispatch(XEvent* xev);
+#endif
#endif
private:
diff --git a/views/focus/accelerator_handler_gtk.cc b/views/focus/accelerator_handler_gtk.cc
index a45aa83..f1dc140 100644
--- a/views/focus/accelerator_handler_gtk.cc
+++ b/views/focus/accelerator_handler_gtk.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "views/focus/accelerator_handler.h"
+
#include <gtk/gtk.h>
#include "views/accelerator.h"
-#include "views/focus/accelerator_handler.h"
#include "views/focus/focus_manager.h"
#include "views/widget/widget_gtk.h"
diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc
index ddcdc04..9473600 100644
--- a/views/focus/accelerator_handler_touch.cc
+++ b/views/focus/accelerator_handler_touch.cc
@@ -2,31 +2,96 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "views/focus/accelerator_handler.h"
+
#include <gtk/gtk.h>
+#include <X11/Xlib.h>
#include "views/accelerator.h"
-#include "views/focus/accelerator_handler.h"
+#include "views/event.h"
#include "views/focus/focus_manager.h"
-#include "views/touchui/touch_event_dispatcher_gtk.h"
+#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"
namespace views {
-AcceleratorHandler::AcceleratorHandler() {}
+namespace {
-bool AcceleratorHandler::Dispatch(GdkEvent* event) {
- // The logic for handling keyboard accelerators has been moved into
- // WidgetGtk::OnKeyEvent handler (views/widget/widget_gtk.cc).
+RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) {
+ gpointer data = NULL;
+ gdk_window_get_user_data(gdk_window, &data);
+ GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
+ if (!gtk_widget || !GTK_IS_WIDGET(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();
+}
+
+} // namespace
+
+bool DispatchXEvent(XEvent* xev) {
+ GdkDisplay* gdisp = gdk_display_get_default();
+ GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xev->xany.window);
+
+ if (RootView* root = FindRootViewForGdkWindow(gwind)) {
+ switch (xev->type) {
+ case KeyPress:
+ case KeyRelease: {
+ KeyEvent keyev(xev);
- // 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);
+ // If it's a keypress, check to see if it triggers an accelerator.
+ if (xev->type == KeyPress) {
+ FocusManager* focus_manager = root->GetFocusManager();
+ if (focus_manager && !focus_manager->OnKeyEvent(keyev))
+ return true;
+ }
+ return root->ProcessKeyEvent(keyev);
+ }
+
+ case ButtonPress:
+ case ButtonRelease: {
+ MouseEvent mouseev(xev);
+ if (xev->type == ButtonPress) {
+ return root->OnMousePressed(mouseev);
+ } else {
+ root->OnMouseReleased(mouseev, false);
+ return true; // Assume the event has been processed to make sure we
+ // don't process it twice.
+ }
+ }
+
+ case MotionNotify: {
+ MouseEvent mouseev(xev);
+ if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) {
+ return root->OnMouseDragged(mouseev);
+ } else {
+ root->OnMouseMoved(mouseev);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+AcceleratorHandler::AcceleratorHandler() {}
+
+bool AcceleratorHandler::Dispatch(GdkEvent* event) {
+ gtk_main_do_event(event);
return true;
}
+bool AcceleratorHandler::Dispatch(XEvent* xev) {
+ return DispatchXEvent(xev);
+}
+
} // namespace views
diff --git a/views/touchui/touch_event_dispatcher_gtk.cc b/views/touchui/touch_event_dispatcher_gtk.cc
deleted file mode 100644
index fc4fcd2..0000000
--- a/views/touchui/touch_event_dispatcher_gtk.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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
deleted file mode 100644
index d80cb96..0000000
--- a/views/touchui/touch_event_dispatcher_gtk.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 e011383..c4878fe 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -32,6 +32,7 @@
['include', '/win_[^/]*\\.cc$'],
]}],
['touchui==0', {'sources/': [
+ ['exclude', 'event_x.cc$'],
['exclude', 'touchui/'],
['exclude', '_(touch)\\.cc$'],
]}],
@@ -235,6 +236,7 @@
'event.h',
'event_gtk.cc',
'event_win.cc',
+ 'event_x.cc',
'fill_layout.cc',
'fill_layout.h',
'focus/accelerator_handler.h',
@@ -269,8 +271,6 @@
'standard_layout.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',