summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/base.gypi7
-rw-r--r--base/message_loop.cc10
-rw-r--r--base/message_pump_glib.cc30
-rw-r--r--base/message_pump_glib.h9
-rw-r--r--base/message_pump_glib_x.cc104
-rw-r--r--base/message_pump_glib_x.h63
6 files changed, 209 insertions, 14 deletions
diff --git a/base/base.gypi b/base/base.gypi
index b9fad5e..d0fa20b 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -333,6 +333,7 @@
'sources!': [
'atomicops_internals_x86_gcc.cc',
'message_pump_glib.cc',
+ 'message_pump_glib_x.cc',
],
}],
[ 'OS != "linux"', {
@@ -447,6 +448,8 @@
'md5.h',
'message_pump_glib.cc',
'message_pump_glib.h',
+ 'message_pump_glib_x.cc',
+ 'message_pump_glib_x.h',
'message_pump_libevent.cc',
'message_pump_libevent.h',
'message_pump_mac.h',
@@ -604,10 +607,12 @@
'symbolize',
'../build/util/build_util.gyp:lastchange',
'../build/linux/system.gyp:gtk',
+ '../build/linux/system.gyp:x11',
'xdg_mime',
],
'export_dependent_settings': [
'../build/linux/system.gyp:gtk',
+ '../build/linux/system.gyp:x11',
],
},],
[ 'OS == "freebsd" or OS == "openbsd"', {
@@ -708,10 +713,12 @@
'../build/util/build_util.gyp:lastchange',
'../build/linux/system.gyp:gtk',
'../build/linux/system.gyp:nss',
+ '../build/linux/system.gyp:x11',
'xdg_mime',
],
'export_dependent_settings': [
'../build/linux/system.gyp:gtk',
+ '../build/linux/system.gyp:x11',
],
},],
['OS == "linux"', {
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 8f6c997b..f335ca1 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -23,6 +23,9 @@
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "base/message_pump_glib.h"
#endif
+#if defined(TOUCH_UI)
+#include "base/message_pump_glib_x.h"
+#endif
using base::Time;
using base::TimeDelta;
@@ -134,6 +137,9 @@ MessageLoop::MessageLoop(Type type)
#elif defined(OS_MACOSX)
#define MESSAGE_PUMP_UI base::MessagePumpMac::Create()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
+#elif defined(TOUCH_UI)
+#define MESSAGE_PUMP_UI new base::MessagePumpGlibX()
+#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
#elif defined(OS_POSIX) // POSIX but not MACOSX.
#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
@@ -533,9 +539,9 @@ bool MessageLoop::DoWork() {
return false;
}
-bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
+bool MessageLoop::DoDelayedWork(base::Time* next_delayed_work_time) {
if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
- *next_delayed_work_time = Time();
+ *next_delayed_work_time = base::Time();
return false;
}
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index e85a712..ad6d177 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -207,8 +207,7 @@ void MessagePumpForUI::RunWithDispatcher(Delegate* delegate,
// Don't block if we think we have more work to do.
bool block = !more_work_is_plausible;
- // g_main_context_iteration returns true if events have been dispatched.
- more_work_is_plausible = g_main_context_iteration(context_, block);
+ more_work_is_plausible = RunOnce(context_, block);
if (state_->should_quit)
break;
@@ -232,6 +231,11 @@ void MessagePumpForUI::RunWithDispatcher(Delegate* delegate,
state_ = previous_state;
}
+bool MessagePumpForUI::RunOnce(GMainContext* context, bool block) {
+ // g_main_context_iteration returns true if events have been dispatched.
+ return g_main_context_iteration(context, block);
+}
+
// Return the timeout we want passed to poll.
int MessagePumpForUI::HandlePrepare() {
// We know we have work, but we haven't called HandleDispatch yet. Don't let
@@ -332,19 +336,21 @@ void MessagePumpForUI::ScheduleDelayedWork(const Time& delayed_work_time) {
ScheduleWork();
}
-// static
-void MessagePumpForUI::EventDispatcher(GdkEvent* event, gpointer data) {
- MessagePumpForUI* message_pump = reinterpret_cast<MessagePumpForUI*>(data);
-
- message_pump->WillProcessEvent(event);
- if (message_pump->state_ && // state_ may be null during tests.
- message_pump->state_->dispatcher) {
- if (!message_pump->state_->dispatcher->Dispatch(event))
- message_pump->state_->should_quit = true;
+void MessagePumpForUI::DispatchEvents(GdkEvent* event) {
+ WillProcessEvent(event);
+ if (state_ && state_->dispatcher) { // state_ may be null during tests.
+ if (!state_->dispatcher->Dispatch(event))
+ state_->should_quit = true;
} else {
gtk_main_do_event(event);
}
- message_pump->DidProcessEvent(event);
+ DidProcessEvent(event);
+}
+
+// static
+void MessagePumpForUI::EventDispatcher(GdkEvent* event, gpointer data) {
+ MessagePumpForUI* message_pump = reinterpret_cast<MessagePumpForUI*>(data);
+ message_pump->DispatchEvents(event);
}
} // namespace base
diff --git a/base/message_pump_glib.h b/base/message_pump_glib.h
index f6d022a..31d37c0 100644
--- a/base/message_pump_glib.h
+++ b/base/message_pump_glib.h
@@ -57,6 +57,11 @@ class MessagePumpForUI : public MessagePump {
// Like MessagePump::Run, but GdkEvent objects are routed through dispatcher.
virtual void RunWithDispatcher(Delegate* delegate, Dispatcher* dispatcher);
+ // Run a single iteration of the mainloop. A return value of true indicates
+ // that an event was handled. |block| indicates if it should wait if no event
+ // is ready for processing.
+ virtual bool RunOnce(GMainContext* context, bool block);
+
virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
virtual void Quit();
virtual void ScheduleWork();
@@ -79,6 +84,10 @@ class MessagePumpForUI : public MessagePump {
// receiving a notification callback.
void RemoveObserver(Observer* observer);
+ // Dispatch an available GdkEvent. Essentially this allows a subclass to do
+ // some task before/after calling the default handler (EventDispatcher).
+ virtual void DispatchEvents(GdkEvent* event);
+
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
new file mode 100644
index 0000000..f77f61d
--- /dev/null
+++ b/base/message_pump_glib_x.cc
@@ -0,0 +1,104 @@
+// 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 "base/message_pump_glib_x.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+namespace {
+
+gboolean PlaceholderDispatch(GSource* source,
+ GSourceFunc cb,
+ gpointer data) {
+ return TRUE;
+}
+
+} // namespace
+
+namespace base {
+
+MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(),
+ gdksource_(NULL),
+ dispatching_event_(false),
+ capture_x_events_(0),
+ capture_gdk_events_(0) {
+ gdk_event_handler_set(&EventDispatcherX, this, NULL);
+
+ InitializeEventsToCapture();
+}
+
+MessagePumpGlibX::~MessagePumpGlibX() {
+}
+
+bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
+ GdkDisplay* gdisp = gdk_display_get_default();
+ Display* display = GDK_DISPLAY_XDISPLAY(gdisp);
+ if (XPending(display)) {
+ XEvent xev;
+ XPeekEvent(display, &xev);
+ if (capture_x_events_[xev.type]) {
+ XNextEvent(display, &xev);
+
+ DLOG(INFO) << "nom noming event";
+
+ // 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.
+ } else {
+ // TODO(sad): A couple of extra events can still sneak in during this
+ g_main_context_iteration(context, FALSE);
+ }
+ }
+
+ bool retvalue;
+ if (gdksource_) {
+ // Replace the dispatch callback of the GDK event source temporarily so that
+ // it doesn't read events from X.
+ gboolean (*cb)(GSource*, GSourceFunc, void*) =
+ gdksource_->source_funcs->dispatch;
+ gdksource_->source_funcs->dispatch = PlaceholderDispatch;
+
+ dispatching_event_ = true;
+ retvalue = g_main_context_iteration(context, block);
+ dispatching_event_ = false;
+
+ gdksource_->source_funcs->dispatch = cb;
+ } else {
+ retvalue = g_main_context_iteration(context, block);
+ }
+
+ return retvalue;
+}
+
+void MessagePumpGlibX::InitializeEventsToCapture(void) {
+ // TODO(sad): Decide which events we want to capture and update the tables
+ // accordingly.
+ capture_x_events_[KeyPress] = true;
+ capture_gdk_events_[GDK_KEY_PRESS] = true;
+
+ capture_x_events_[KeyRelease] = true;
+ capture_gdk_events_[GDK_KEY_RELEASE] = true;
+}
+
+void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
+ MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data);
+
+ if (!pump_x->gdksource_) {
+ pump_x->gdksource_ = g_main_current_source();
+ } else if (!pump_x->IsDispatchingEvent()) {
+ if (event->type != GDK_NOTHING &&
+ pump_x->capture_gdk_events_[event->type]) {
+ // 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!!";
+ }
+ }
+
+ pump_x->DispatchEvents(event);
+}
+
+} // namespace base
diff --git a/base/message_pump_glib_x.h b/base/message_pump_glib_x.h
new file mode 100644
index 0000000..2f50731
--- /dev/null
+++ b/base/message_pump_glib_x.h
@@ -0,0 +1,63 @@
+// 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_H
+#define BASE_MESSAGE_PUMP_GLIB_X_H
+
+#include "base/message_pump.h"
+#include "base/message_pump_glib.h"
+
+#include <bitset>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <X11/X.h>
+
+namespace base {
+
+class MessagePumpGlibX : public MessagePumpForUI {
+ public:
+ MessagePumpGlibX();
+ virtual ~MessagePumpGlibX();
+
+ // MessagePumpForUI implementation.
+ virtual bool RunOnce(GMainContext* context, bool block);
+
+ // Indicates whether a GDK event was injected by chrome (when |true|) or if it
+ // was captured and being processed by GDK (when |false|).
+ bool IsDispatchingEvent(void) { return dispatching_event_; }
+
+ private:
+ static void EventDispatcherX(GdkEvent* event, gpointer data);
+
+ // Update the lookup table and flag the events that should be captured and
+ // processed so that GDK doesn't get to them.
+ void InitializeEventsToCapture(void);
+
+ // The event source for GDK events.
+ GSource* gdksource_;
+
+ // Indicates whether a GDK event was injected by chrome (when |true|) or if it
+ // was captured and being processed by GDK (when |false|).
+ bool dispatching_event_;
+
+#if ! GTK_CHECK_VERSION(2,18,0)
+// GDK_EVENT_LAST was introduced in GTK+ 2.18.0. For earlier versions, we pick a
+// large enough value (the value of GDK_EVENT_LAST in 2.18.0) so that it works
+// for all versions.
+#define GDK_EVENT_LAST 37
+#endif
+
+ // We do not want to process all the events ourselves. So we use a lookup
+ // table to quickly check if a particular event should be handled by us or if
+ // it should be passed on to the default GDK handler.
+ std::bitset<LASTEvent> capture_x_events_;
+ std::bitset<GDK_EVENT_LAST> capture_gdk_events_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessagePumpGlibX);
+};
+
+} // namespace base
+
+#endif // BASE_MESSAGE_PUMP_GLIB_X_H