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