Skip to content

Commit

Permalink
Refactor the glib message-pump, and use it as the base for a gtk mess…
Browse files Browse the repository at this point in the history
…age pump and an X message pump.

The changes:
 * Rename MessagePumpGlibX to MessagePumpX.
 * Rename MessagePumpForUI to MessagePumpGlib.
 * Move some stuff out of MessagePumpGlib, and into MessagePumpGtk and MessagePumpX.
 * Rename MessagePumpForUI::Observer to MessageObserver, moved the platform-specific implementations into MessagePumpGtk and MessagePumpX. Ditto for MessagePumpForUI::Dispatcher.

MessagePumpX is independent of MessagePumpGtk. At the moment, MessagePumpX does process some GDK event, but once we have a complete native_widget_x, we can take out the GDK processing and things should continue to work.

BUG=none
TEST=existing message-pump tests.

Review URL: http://codereview.chromium.org/7250001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90418 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sadrul@chromium.org committed Jun 24, 2011
1 parent 86e1db9 commit 2047ef4
Show file tree
Hide file tree
Showing 26 changed files with 381 additions and 300 deletions.
15 changes: 11 additions & 4 deletions base/base.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,15 @@
'sources!': [
'atomicops_internals_x86_gcc.cc',
'message_pump_glib.cc',
'message_pump_glib_x.cc',
'message_pump_gtk.cc',
'message_pump_x.cc',
],
}],
[ 'touchui==0', {
'sources!' : [ 'message_pump_x.cc', ],
}, {
'sources!' : [ 'message_pump_gtk.cc', ],
}],
[ 'OS != "linux"', {
'sources!': [
# Not automatically excluded by the *linux.cc rules.
Expand Down Expand Up @@ -571,9 +577,10 @@
'md5.h',
'message_pump_glib.cc',
'message_pump_glib.h',
'message_pump_glib_x.cc',
'message_pump_glib_x.h',
'message_pump_glib_x_dispatch.h',
'message_pump_gtk.cc',
'message_pump_gtk.h',
'message_pump_x.cc',
'message_pump_x.h',
'message_pump_libevent.cc',
'message_pump_libevent.h',
'message_pump_mac.h',
Expand Down
14 changes: 8 additions & 6 deletions base/message_loop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
#if defined(OS_POSIX)
#include "base/message_pump_libevent.h"
#endif

#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "base/message_pump_glib.h"
#endif
#if defined(TOUCH_UI)
#include "base/message_pump_glib_x.h"
#endif
#include "base/message_pump_x.h"
#else
#include "base/message_pump_gtk.h"
#endif // defined(TOUCH_UI)
#endif // defined(OS_POSIX) && !defined(OS_MACOSX)

using base::TimeDelta;
using base::TimeTicks;
Expand Down Expand Up @@ -176,15 +178,15 @@ MessageLoop::MessageLoop(Type type)
#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_UI new base::MessagePumpX()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
#elif defined(OS_NACL)
// Currently NaCl doesn't have a UI or an IO MessageLoop.
// TODO(abarth): Figure out if we need these.
#define MESSAGE_PUMP_UI NULL
#define MESSAGE_PUMP_IO NULL
#elif defined(OS_POSIX) // POSIX but not MACOSX.
#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
#define MESSAGE_PUMP_UI new base::MessagePumpGtk()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
#else
#error Not implemented
Expand Down
16 changes: 7 additions & 9 deletions base/message_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@
#elif defined(OS_POSIX)
#include "base/message_pump_libevent.h"
#if !defined(OS_MACOSX)
#include "base/message_pump_glib.h"
typedef struct _XDisplay Display;
#if defined(TOUCH_UI)
#include "base/message_pump_x.h"
#else
#include "base/message_pump_gtk.h"
#endif
typedef struct _XDisplay Display;
#endif
#if defined(TOUCH_UI)
#include "base/message_pump_glib_x_dispatch.h"
#endif

namespace base {
Expand Down Expand Up @@ -80,12 +81,9 @@ class BASE_API MessageLoop : public base::MessagePump::Delegate {
#if defined(OS_WIN)
typedef base::MessagePumpWin::Dispatcher Dispatcher;
typedef base::MessagePumpForUI::Observer Observer;
#elif defined(TOUCH_UI)
typedef base::MessagePumpGlibXDispatcher Dispatcher;
typedef base::MessagePumpXObserver Observer;
#elif !defined(OS_MACOSX)
typedef base::MessagePumpForUI::Dispatcher Dispatcher;
typedef base::MessagePumpForUI::Observer Observer;
typedef base::MessagePumpDispatcher Dispatcher;
typedef base::MessagePumpObserver Observer;
#endif

// A MessageLoop has a particular type, which indicates the set of
Expand Down
76 changes: 21 additions & 55 deletions base/message_pump_glib.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 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.

Expand All @@ -7,7 +7,6 @@
#include <fcntl.h>
#include <math.h>

#include <gtk/gtk.h>
#include <glib.h>

#include "base/eintr_wrapper.h"
Expand Down Expand Up @@ -85,7 +84,7 @@ int GetTimeIntervalMilliseconds(const base::TimeTicks& from) {
// loop, around event handling.

struct WorkSource : public GSource {
base::MessagePumpForUI* pump;
base::MessagePumpGlib* pump;
};

gboolean WorkSourcePrepare(GSource* source,
Expand Down Expand Up @@ -124,9 +123,9 @@ GSourceFuncs WorkSourceFuncs = {

namespace base {

struct MessagePumpForUI::RunState {
struct MessagePumpGlib::RunState {
Delegate* delegate;
Dispatcher* dispatcher;
MessagePumpDispatcher* dispatcher;

// Used to flag that the current Run() invocation should return ASAP.
bool should_quit;
Expand All @@ -140,7 +139,7 @@ struct MessagePumpForUI::RunState {
bool has_work;
};

MessagePumpForUI::MessagePumpForUI()
MessagePumpGlib::MessagePumpGlib()
: state_(NULL),
context_(g_main_context_default()),
wakeup_gpollfd_(new GPollFD) {
Expand All @@ -160,26 +159,23 @@ MessagePumpForUI::MessagePumpForUI()
// This is needed to allow Run calls inside Dispatch.
g_source_set_can_recurse(work_source_, TRUE);
g_source_attach(work_source_, context_);
gdk_event_handler_set(&EventDispatcher, this, NULL);
}

MessagePumpForUI::~MessagePumpForUI() {
gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event),
this, NULL);
MessagePumpGlib::~MessagePumpGlib() {
g_source_destroy(work_source_);
g_source_unref(work_source_);
close(wakeup_pipe_read_);
close(wakeup_pipe_write_);
}

void MessagePumpForUI::RunWithDispatcher(Delegate* delegate,
Dispatcher* dispatcher) {
void MessagePumpGlib::RunWithDispatcher(Delegate* delegate,
MessagePumpDispatcher* dispatcher) {
#ifndef NDEBUG
// Make sure we only run this on one thread. GTK only has one message pump
// Make sure we only run this on one thread. X/GTK only has one message pump
// so we can only have one UI loop per process.
static base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
DCHECK(thread_id == base::PlatformThread::CurrentId()) <<
"Running MessagePumpForUI on two different threads; "
"Running MessagePumpGlib on two different threads; "
"this is unsupported by GLib!";
#endif

Expand Down Expand Up @@ -231,13 +227,8 @@ 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() {
int MessagePumpGlib::HandlePrepare() {
// We know we have work, but we haven't called HandleDispatch yet. Don't let
// the pump block so that we can do some processing.
if (state_ && // state_ may be null during tests.
Expand All @@ -249,7 +240,7 @@ int MessagePumpForUI::HandlePrepare() {
return GetTimeIntervalMilliseconds(delayed_work_time_);
}

bool MessagePumpForUI::HandleCheck() {
bool MessagePumpGlib::HandleCheck() {
if (!state_) // state_ may be null during tests.
return false;

Expand Down Expand Up @@ -279,11 +270,11 @@ bool MessagePumpForUI::HandleCheck() {
return false;
}

void MessagePumpForUI::HandleDispatch() {
void MessagePumpGlib::HandleDispatch() {
state_->has_work = false;
if (state_->delegate->DoWork()) {
// NOTE: on Windows at this point we would call ScheduleWork (see
// MessagePumpForUI::HandleWorkMessage in message_pump_win.cc). But here,
// MessagePumpGlib::HandleWorkMessage in message_pump_win.cc). But here,
// instead of posting a message on the wakeup pipe, we can avoid the
// syscalls and just signal that we have more work.
state_->has_work = true;
Expand All @@ -295,38 +286,27 @@ void MessagePumpForUI::HandleDispatch() {
state_->delegate->DoDelayedWork(&delayed_work_time_);
}

void MessagePumpForUI::AddObserver(Observer* observer) {
void MessagePumpGlib::AddObserver(MessagePumpObserver* observer) {
observers_.AddObserver(observer);
}

void MessagePumpForUI::RemoveObserver(Observer* observer) {
void MessagePumpGlib::RemoveObserver(MessagePumpObserver* observer) {
observers_.RemoveObserver(observer);
}

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);
}
DidProcessEvent(event);
}

void MessagePumpForUI::Run(Delegate* delegate) {
void MessagePumpGlib::Run(Delegate* delegate) {
RunWithDispatcher(delegate, NULL);
}

void MessagePumpForUI::Quit() {
void MessagePumpGlib::Quit() {
if (state_) {
state_->should_quit = true;
} else {
NOTREACHED() << "Quit called outside Run!";
}
}

void MessagePumpForUI::ScheduleWork() {
void MessagePumpGlib::ScheduleWork() {
// This can be called on any thread, so we don't want to touch any state
// variables as we would then need locks all over. This ensures that if
// we are sleeping in a poll that we will wake up.
Expand All @@ -336,29 +316,15 @@ void MessagePumpForUI::ScheduleWork() {
}
}

void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
void MessagePumpGlib::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
// We need to wake up the loop in case the poll timeout needs to be
// adjusted. This will cause us to try to do work, but that's ok.
delayed_work_time_ = delayed_work_time;
ScheduleWork();
}

MessagePumpForUI::Dispatcher* MessagePumpForUI::GetDispatcher() {
MessagePumpDispatcher* MessagePumpGlib::GetDispatcher() {
return state_ ? state_->dispatcher : NULL;
}

void MessagePumpForUI::WillProcessEvent(GdkEvent* event) {
FOR_EACH_OBSERVER(Observer, observers_, WillProcessEvent(event));
}

void MessagePumpForUI::DidProcessEvent(GdkEvent* event) {
FOR_EACH_OBSERVER(Observer, observers_, DidProcessEvent(event));
}

// static
void MessagePumpForUI::EventDispatcher(GdkEvent* event, gpointer data) {
MessagePumpForUI* message_pump = reinterpret_cast<MessagePumpForUI*>(data);
message_pump->DispatchEvents(event);
}

} // namespace base
Loading

0 comments on commit 2047ef4

Please sign in to comment.