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