message_pump_glib.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_MESSAGE_PUMP_GLIB_H_
6#define BASE_MESSAGE_PUMP_GLIB_H_
7#pragma once
8
9#include "base/memory/scoped_ptr.h"
10#include "base/message_pump.h"
11#include "base/observer_list.h"
12#include "base/time.h"
13
14typedef union _GdkEvent GdkEvent;
15typedef struct _GMainContext GMainContext;
16typedef struct _GPollFD GPollFD;
17typedef struct _GSource GSource;
18
19namespace base {
20
21// This class implements a MessagePump needed for TYPE_UI MessageLoops on
22// OS_LINUX platforms using GLib.
23class MessagePumpForUI : public MessagePump {
24 public:
25  // Observer is notified prior to a GdkEvent event being dispatched. As
26  // Observers are notified of every change, they have to be FAST!
27  class Observer {
28   public:
29    virtual ~Observer() {}
30
31    // This method is called before processing a message.
32    virtual void WillProcessEvent(GdkEvent* event) = 0;
33
34    // This method is called after processing a message.
35    virtual void DidProcessEvent(GdkEvent* event) = 0;
36  };
37
38  // Dispatcher is used during a nested invocation of Run to dispatch events.
39  // If Run is invoked with a non-NULL Dispatcher, MessageLoop does not
40  // dispatch events (or invoke gtk_main_do_event), rather every event is
41  // passed to Dispatcher's Dispatch method for dispatch. It is up to the
42  // Dispatcher to dispatch, or not, the event.
43  //
44  // The nested loop is exited by either posting a quit, or returning false
45  // from Dispatch.
46  class Dispatcher {
47   public:
48    virtual ~Dispatcher() {}
49    // Dispatches the event. If true is returned processing continues as
50    // normal. If false is returned, the nested loop exits immediately.
51    virtual bool Dispatch(GdkEvent* event) = 0;
52  };
53
54  MessagePumpForUI();
55  virtual ~MessagePumpForUI();
56
57  // Like MessagePump::Run, but GdkEvent objects are routed through dispatcher.
58  virtual void RunWithDispatcher(Delegate* delegate, Dispatcher* dispatcher);
59
60  // Run a single iteration of the mainloop. A return value of true indicates
61  // that an event was handled. |block| indicates if it should wait if no event
62  // is ready for processing.
63  virtual bool RunOnce(GMainContext* context, bool block);
64
65  // Internal methods used for processing the pump callbacks.  They are
66  // public for simplicity but should not be used directly.  HandlePrepare
67  // is called during the prepare step of glib, and returns a timeout that
68  // will be passed to the poll. HandleCheck is called after the poll
69  // has completed, and returns whether or not HandleDispatch should be called.
70  // HandleDispatch is called if HandleCheck returned true.
71  int HandlePrepare();
72  bool HandleCheck();
73  void HandleDispatch();
74
75  // Adds an Observer, which will start receiving notifications immediately.
76  void AddObserver(Observer* observer);
77
78  // Removes an Observer.  It is safe to call this method while an Observer is
79  // receiving a notification callback.
80  void RemoveObserver(Observer* observer);
81
82  // Dispatch an available GdkEvent. Essentially this allows a subclass to do
83  // some task before/after calling the default handler (EventDispatcher).
84  virtual void DispatchEvents(GdkEvent* event);
85
86  // Overridden from MessagePump:
87  virtual void Run(Delegate* delegate);
88  virtual void Quit();
89  virtual void ScheduleWork();
90  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
91
92 protected:
93  // Returns the dispatcher for the current run state (|state_->dispatcher|).
94  Dispatcher* GetDispatcher();
95
96 private:
97  // We may make recursive calls to Run, so we save state that needs to be
98  // separate between them in this structure type.
99  struct RunState;
100
101  // Invoked from EventDispatcher. Notifies all observers we're about to
102  // process an event.
103  void WillProcessEvent(GdkEvent* event);
104
105  // Invoked from EventDispatcher. Notifies all observers we processed an
106  // event.
107  void DidProcessEvent(GdkEvent* event);
108
109  // Callback prior to gdk dispatching an event.
110  static void EventDispatcher(GdkEvent* event, void* data);
111
112  RunState* state_;
113
114  // This is a GLib structure that we can add event sources to.  We use the
115  // default GLib context, which is the one to which all GTK events are
116  // dispatched.
117  GMainContext* context_;
118
119  // This is the time when we need to do delayed work.
120  TimeTicks delayed_work_time_;
121
122  // The work source.  It is shared by all calls to Run and destroyed when
123  // the message pump is destroyed.
124  GSource* work_source_;
125
126  // We use a wakeup pipe to make sure we'll get out of the glib polling phase
127  // when another thread has scheduled us to do some work.  There is a glib
128  // mechanism g_main_context_wakeup, but this won't guarantee that our event's
129  // Dispatch() will be called.
130  int wakeup_pipe_read_;
131  int wakeup_pipe_write_;
132  // Use a scoped_ptr to avoid needing the definition of GPollFD in the header.
133  scoped_ptr<GPollFD> wakeup_gpollfd_;
134
135  // List of observers.
136  ObserverList<Observer> observers_;
137
138  DISALLOW_COPY_AND_ASSIGN(MessagePumpForUI);
139};
140
141}  // namespace base
142
143#endif  // BASE_MESSAGE_PUMP_GLIB_H_
144