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: ~Observer()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: ~Dispatcher()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 Run(Delegate * delegate)62 virtual void Run(Delegate* delegate) override { 63 RunWithDispatcher(delegate, NULL); 64 } 65 virtual void Quit() override; 66 virtual void ScheduleWork() override; 67 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; 68 69 // Internal methods used for processing the pump callbacks. They are 70 // public for simplicity but should not be used directly. HandlePrepare 71 // is called during the prepare step of glib, and returns a timeout that 72 // will be passed to the poll. HandleCheck is called after the poll 73 // has completed, and returns whether or not HandleDispatch should be called. 74 // HandleDispatch is called if HandleCheck returned true. 75 int HandlePrepare(); 76 bool HandleCheck(); 77 void HandleDispatch(); 78 79 // Adds an Observer, which will start receiving notifications immediately. 80 void AddObserver(Observer* observer); 81 82 // Removes an Observer. It is safe to call this method while an Observer is 83 // receiving a notification callback. 84 void RemoveObserver(Observer* observer); 85 86 private: 87 // We may make recursive calls to Run, so we save state that needs to be 88 // separate between them in this structure type. 89 struct RunState { 90 Delegate* delegate; 91 Dispatcher* dispatcher; 92 93 // Used to flag that the current Run() invocation should return ASAP. 94 bool should_quit; 95 96 // Used to count how many Run() invocations are on the stack. 97 int run_depth; 98 99 // This keeps the state of whether the pump got signaled that there was new 100 // work to be done. Since we eat the message on the wake up pipe as soon as 101 // we get it, we keep that state here to stay consistent. 102 bool has_work; 103 }; 104 105 // Invoked from EventDispatcher. Notifies all observers we're about to 106 // process an event. 107 void WillProcessEvent(GdkEvent* event); 108 109 // Invoked from EventDispatcher. Notifies all observers we processed an 110 // event. 111 void DidProcessEvent(GdkEvent* event); 112 113 // Callback prior to gdk dispatching an event. 114 static void EventDispatcher(GdkEvent* event, void* data); 115 116 RunState* state_; 117 118 // This is a GLib structure that we can add event sources to. We use the 119 // default GLib context, which is the one to which all GTK events are 120 // dispatched. 121 GMainContext* context_; 122 123 // This is the time when we need to do delayed work. 124 TimeTicks delayed_work_time_; 125 126 // The work source. It is shared by all calls to Run and destroyed when 127 // the message pump is destroyed. 128 GSource* work_source_; 129 130 // We use a wakeup pipe to make sure we'll get out of the glib polling phase 131 // when another thread has scheduled us to do some work. There is a glib 132 // mechanism g_main_context_wakeup, but this won't guarantee that our event's 133 // Dispatch() will be called. 134 int wakeup_pipe_read_; 135 int wakeup_pipe_write_; 136 // Use an autoptr to avoid needing the definition of GPollFD in the header. 137 mozilla::UniquePtr<GPollFD> wakeup_gpollfd_; 138 139 mozilla::Atomic<bool> pipe_full_; 140 141 // List of observers. 142 ObserverList<Observer> observers_; 143 144 DISALLOW_COPY_AND_ASSIGN(MessagePumpForUI); 145 }; 146 147 } // namespace base 148 149 #endif // BASE_MESSAGE_PUMP_GLIB_H_ 150