x11: Move X event handling out of the message-pump.

This change moves the X11 event handling out of the X11 message-pump, and uses
the X11 event dispatch code from X11EventSource instead. Overview of the changes:

 * Remove all X event handling code from the message-pump. The X11 message-pump
   only opens the connection to the X11 server. This too will be moved out of
   here in subsequent patches.

 * The X11EventSource sends an XEvent it receives from the X11 server back to
   the X11 message-pump, which triggers the MessagePumpObservers, before sending
   the event to the dispatchers. This is a short-term workaround until the
   message-pump observers are converted into PlatformEventObservers.

 * The MessagePumpDispatcher implementations that deal with X11 events are
   converted into PlatformEventDispatchers.

 * Remove support for starting a nested message-loop with a custom dispatcher
   on non-Windows.

Changes in components:

//ash:
 * Split AcceleratorDispatcher into platform-specific AcceleratorDispatcherWin,
   which remains a MessagePumpDispatcher, and AcceleratorDispatcherLinux, which
   is a PlatformEventDispatcher. It may be possible to do some cleanup in this,
   depending on the outcome of http://crbug.com/357777 and http://crbug.com/357733.

//base:
 * Remove support for providing a custom MessagePumpDispatcher when starting a
   nested message-loop on non-Windows platforms.
 * Remove most of the event-dispatch code from MessagePumpX11. The only remaining
   bits are for triggering MessagePumpObservers, which will be replaced by the newer
   PlatformEventObservers in subsequent patches.

//chrome, //content, //mojo, //ui/aura, //ui/base, //ui/wm:
 * Convert MessagePumpDispatchers that deal with X11 events into
   PlatformEventDispatchers.

//ui/events:
 * Allow creating a 'default' PlatformEventSource. On X11, it creates X11EventSource,
   and on other platforms, it doesn't create an event-source.
 * A temporary measure in X11EventSource to send the event to the message-pump so
   that the message-pump observers can be triggered. This will be removed once the
   MessagePumpObservers that deal with X11 events are turned into
   PlatformEventObservers.

//ui/views:
 * Remove the linux implementation of MenuMessagePumpDispatcher, and replace it with
   MenuEventDispatcherLinux.
 * Platform specific implementation for MenuController::RunMessageLoop(): the Windows
   implementation uses the MessagePumpDispatcher, and the non-windows implementation
   uses the PlatformEventDispatcher. This is somewhat unfortunate, and I am going to
   look for something better for this. But the code duplication here is relatively
   small, I don't want to make this patch any larger.

BUG=354062
R=darin@chromium.org, sky@chromium.org

Review URL: https://codereview.chromium.org/219743002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262008 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 9a2e75dde876521fdd1f39c9646902aade1f8c89
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 229eae7..2315fd1 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -388,7 +388,7 @@
 
   StartHistogrammer();
 
-#if defined(USE_AURA)
+#if defined(OS_WIN)
   if (run_loop_->dispatcher_ && type() == TYPE_UI) {
     static_cast<MessagePumpForUI*>(pump_.get())->
         RunWithDispatcher(this, run_loop_->dispatcher_);
diff --git a/base/message_loop/message_pump_x11.cc b/base/message_loop/message_pump_x11.cc
index a86e4fe..6a4db10 100644
--- a/base/message_loop/message_pump_x11.cc
+++ b/base/message_loop/message_pump_x11.cc
@@ -16,33 +16,6 @@
 
 namespace {
 
-gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
-  if (XPending(MessagePumpX11::GetDefaultXDisplay()))
-    *timeout_ms = 0;
-  else
-    *timeout_ms = -1;
-  return FALSE;
-}
-
-gboolean XSourceCheck(GSource* source) {
-  return XPending(MessagePumpX11::GetDefaultXDisplay());
-}
-
-gboolean XSourceDispatch(GSource* source,
-                         GSourceFunc unused_func,
-                         gpointer data) {
-  MessagePumpX11* pump = static_cast<MessagePumpX11*>(data);
-  pump->DispatchXEvents();
-  return TRUE;
-}
-
-GSourceFuncs XSourceFuncs = {
-  XSourcePrepare,
-  XSourceCheck,
-  XSourceDispatch,
-  NULL
-};
-
 // The connection is essentially a global that's accessed through a static
 // method and destroyed whenever ~MessagePumpX11() is called. We do this
 // for historical reasons so user code can call
@@ -52,94 +25,16 @@
 // TODO(erg): This can be changed to something more sane like
 // MessagePumpX11::Current()->display() once MessagePumpGtk goes away.
 Display* g_xdisplay = NULL;
-int g_xinput_opcode = -1;
-
-bool InitializeXInput2() {
-  Display* display = MessagePumpX11::GetDefaultXDisplay();
-  if (!display)
-    return false;
-
-  int event, err;
-
-  int xiopcode;
-  if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
-    DVLOG(1) << "X Input extension not available.";
-    return false;
-  }
-  g_xinput_opcode = xiopcode;
-
-#if defined(USE_XI2_MT)
-  // USE_XI2_MT also defines the required XI2 minor minimum version.
-  int major = 2, minor = USE_XI2_MT;
-#else
-  int major = 2, minor = 0;
-#endif
-  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
-    DVLOG(1) << "XInput2 not supported in the server.";
-    return false;
-  }
-#if defined(USE_XI2_MT)
-  if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
-    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
-            << "But 2." << USE_XI2_MT << " is required.";
-    return false;
-  }
-#endif
-
-  return true;
-}
-
-Window FindEventTarget(const NativeEvent& xev) {
-  Window target = xev->xany.window;
-  if (xev->type == GenericEvent &&
-      static_cast<XIEvent*>(xev->xcookie.data)->extension == g_xinput_opcode) {
-    target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
-  }
-  return target;
-}
-
-bool InitializeXkb() {
-  Display* display = MessagePumpX11::GetDefaultXDisplay();
-  if (!display)
-    return false;
-
-  int opcode, event, error;
-  int major = XkbMajorVersion;
-  int minor = XkbMinorVersion;
-  if (!XkbQueryExtension(display, &opcode, &event, &error, &major, &minor)) {
-    DVLOG(1) << "Xkb extension not available.";
-    return false;
-  }
-
-  // Ask the server not to send KeyRelease event when the user holds down a key.
-  // crbug.com/138092
-  Bool supported_return;
-  if (!XkbSetDetectableAutoRepeat(display, True, &supported_return)) {
-    DVLOG(1) << "XKB not supported in the server.";
-    return false;
-  }
-
-  return true;
-}
 
 }  // namespace
 
-MessagePumpX11::MessagePumpX11() : MessagePumpGlib(),
-    x_source_(NULL) {
-  InitializeXInput2();
-  InitializeXkb();
-  InitXSource();
-
-  // Can't put this in the initializer list because g_xdisplay may not exist
-  // until after InitXSource().
-  x_root_window_ = DefaultRootWindow(g_xdisplay);
-}
+MessagePumpX11::MessagePumpX11() : MessagePumpGlib() {}
 
 MessagePumpX11::~MessagePumpX11() {
-  g_source_destroy(x_source_);
-  g_source_unref(x_source_);
-  XCloseDisplay(g_xdisplay);
-  g_xdisplay = NULL;
+  if (g_xdisplay) {
+    XCloseDisplay(g_xdisplay);
+    g_xdisplay = NULL;
+  }
 }
 
 // static
@@ -163,26 +58,6 @@
 }
 #endif
 
-void MessagePumpX11::AddDispatcherForWindow(
-    MessagePumpDispatcher* dispatcher,
-    unsigned long xid) {
-  dispatchers_.insert(std::make_pair(xid, dispatcher));
-}
-
-void MessagePumpX11::RemoveDispatcherForWindow(unsigned long xid) {
-  dispatchers_.erase(xid);
-}
-
-void MessagePumpX11::AddDispatcherForRootWindow(
-    MessagePumpDispatcher* dispatcher) {
-  root_window_dispatchers_.AddObserver(dispatcher);
-}
-
-void MessagePumpX11::RemoveDispatcherForRootWindow(
-    MessagePumpDispatcher* dispatcher) {
-  root_window_dispatchers_.RemoveObserver(dispatcher);
-}
-
 void MessagePumpX11::AddObserver(MessagePumpObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -191,86 +66,10 @@
   observers_.RemoveObserver(observer);
 }
 
-void MessagePumpX11::DispatchXEvents() {
-  Display* display = GetDefaultXDisplay();
-  DCHECK(display);
-  MessagePumpDispatcher* dispatcher = GetDispatcher();
-  if (!dispatcher)
-    dispatcher = this;
-
-  // In the general case, we want to handle all pending events before running
-  // the tasks. This is what happens in the message_pump_glib case.
-  while (XPending(display)) {
-    XEvent xev;
-    XNextEvent(display, &xev);
-    ProcessXEvent(dispatcher, &xev);
-    if (ShouldQuit())
-      break;
-  }
-}
-
-void MessagePumpX11::BlockUntilWindowMapped(unsigned long xid) {
-  XEvent event;
-
-  Display* display = GetDefaultXDisplay();
-  DCHECK(display);
-
-  MessagePumpDispatcher* dispatcher = GetDispatcher();
-  if (!dispatcher)
-    dispatcher = this;
-
-  do {
-    // Block until there's a message of |event_mask| type on |w|. Then remove
-    // it from the queue and stuff it in |event|.
-    XWindowEvent(display, xid, StructureNotifyMask, &event);
-    ProcessXEvent(dispatcher, &event);
-  } while (event.type != MapNotify);
-}
-
-void MessagePumpX11::InitXSource() {
-  // CHECKs are to help track down crbug.com/113106.
-  CHECK(!x_source_);
-  Display* display = GetDefaultXDisplay();
-  CHECK(display) << "Unable to get connection to X server";
-  x_poll_.reset(new GPollFD());
-  CHECK(x_poll_.get());
-  x_poll_->fd = ConnectionNumber(display);
-  x_poll_->events = G_IO_IN;
-
-  x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource));
-  g_source_add_poll(x_source_, x_poll_.get());
-  g_source_set_can_recurse(x_source_, TRUE);
-  g_source_set_callback(x_source_, NULL, this, NULL);
-  g_source_attach(x_source_, g_main_context_default());
-}
-
-void MessagePumpX11::ProcessXEvent(MessagePumpDispatcher* dispatcher,
-                                   XEvent* xev) {
-  CHECK(dispatcher);
-  bool have_cookie = false;
-  if (xev->type == GenericEvent &&
-      XGetEventData(xev->xgeneric.display, &xev->xcookie)) {
-    have_cookie = true;
-  }
-
-  if (!WillProcessXEvent(xev)) {
-    uint32_t action = dispatcher->Dispatch(xev);
-    bool should_quit = (action & POST_DISPATCH_QUIT_LOOP);
-    if (dispatcher != this && (action & POST_DISPATCH_PERFORM_DEFAULT))
-      action = Dispatch(xev);
-    if ((action & POST_DISPATCH_QUIT_LOOP) || should_quit)
-      Quit();
-    DidProcessXEvent(xev);
-  }
-
-  if (have_cookie)
-    XFreeEventData(xev->xgeneric.display, &xev->xcookie);
-}
-
 bool MessagePumpX11::WillProcessXEvent(XEvent* xevent) {
-  if (!observers().might_have_observers())
+  if (!observers_.might_have_observers())
     return false;
-  ObserverListBase<MessagePumpObserver>::Iterator it(observers());
+  ObserverListBase<MessagePumpObserver>::Iterator it(observers_);
   MessagePumpObserver* obs;
   while ((obs = it.GetNext()) != NULL) {
     if (obs->WillProcessEvent(xevent))
@@ -280,35 +79,7 @@
 }
 
 void MessagePumpX11::DidProcessXEvent(XEvent* xevent) {
-  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent));
-}
-
-MessagePumpDispatcher* MessagePumpX11::GetDispatcherForXEvent(
-    const NativeEvent& xev) const {
-  ::Window x_window = FindEventTarget(xev);
-  DispatchersMap::const_iterator it = dispatchers_.find(x_window);
-  return it != dispatchers_.end() ? it->second : NULL;
-}
-
-uint32_t MessagePumpX11::Dispatch(const NativeEvent& xev) {
-  // MappingNotify events (meaning that the keyboard or pointer buttons have
-  // been remapped) aren't associated with a window; send them to all
-  // dispatchers.
-  if (xev->type == MappingNotify) {
-    for (DispatchersMap::const_iterator it = dispatchers_.begin();
-         it != dispatchers_.end(); ++it) {
-      it->second->Dispatch(xev);
-    }
-    return POST_DISPATCH_NONE;
-  }
-
-  if (FindEventTarget(xev) == x_root_window_) {
-    FOR_EACH_OBSERVER(MessagePumpDispatcher, root_window_dispatchers_,
-                      Dispatch(xev));
-    return POST_DISPATCH_NONE;
-  }
-  MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev);
-  return dispatcher ? dispatcher->Dispatch(xev) : POST_DISPATCH_NONE;
+  FOR_EACH_OBSERVER(MessagePumpObserver, observers_, DidProcessEvent(xevent));
 }
 
 }  // namespace base
diff --git a/base/message_loop/message_pump_x11.h b/base/message_loop/message_pump_x11.h
index ce20d5d..9a61a22 100644
--- a/base/message_loop/message_pump_x11.h
+++ b/base/message_loop/message_pump_x11.h
@@ -31,8 +31,7 @@
 // If there's a current dispatcher given through RunWithDispatcher(), that
 // dispatcher receives events. Otherwise, we route to messages to dispatchers
 // who have subscribed to messages from a specific X11 window.
-class BASE_EXPORT MessagePumpX11 : public MessagePumpGlib,
-                                   public MessagePumpDispatcher {
+class BASE_EXPORT MessagePumpX11 : public MessagePumpGlib {
  public:
   MessagePumpX11();
   virtual ~MessagePumpX11();
@@ -43,18 +42,6 @@
   // Returns the UI or GPU message pump.
   static MessagePumpX11* Current();
 
-  // Adds/Removes |dispatcher| for the |xid|. This will route all messages from
-  // the window |xid| to |dispatcher.
-  void AddDispatcherForWindow(MessagePumpDispatcher* dispatcher,
-                              unsigned long xid);
-  void RemoveDispatcherForWindow(unsigned long xid);
-
-  // Adds/Removes |dispatcher| to receive all events sent to the X root
-  // window. A root window can have multiple dispatchers, and events on root
-  // windows will be dispatched to all.
-  void AddDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
-  void RemoveDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
-
   // Adds an Observer, which will start receiving notifications immediately.
   void AddObserver(MessagePumpObserver* observer);
 
@@ -62,62 +49,16 @@
   // receiving a notification callback.
   void RemoveObserver(MessagePumpObserver* observer);
 
-  // Internal function. Called by the glib source dispatch function. Processes
-  // all available X events.
-  void DispatchXEvents();
-
-  // Blocks on the X11 event queue until we receive notification from the
-  // xserver that |w| has been mapped; StructureNotifyMask events on |w| are
-  // pulled out from the queue and dispatched out of order.
-  //
-  // For those that know X11, this is really a wrapper around XWindowEvent
-  // which still makes sure the preempted event is dispatched instead of
-  // dropped on the floor. This method exists because mapping a window is
-  // asynchronous (and we receive an XEvent when mapped), while there are also
-  // functions which require a mapped window.
-  void BlockUntilWindowMapped(unsigned long xid);
-
- private:
-  typedef std::map<unsigned long, MessagePumpDispatcher*> DispatchersMap;
-
-  // Initializes the glib event source for X.
-  void InitXSource();
-
-  // Dispatches the event to the specified dispatcher.
-  void ProcessXEvent(MessagePumpDispatcher* dispatcher, XEvent* event);
-
   // Sends the event to the observers. If an observer returns true, then it does
   // not send the event to any other observers and returns true. Returns false
   // if no observer returns true.
   bool WillProcessXEvent(XEvent* xevent);
   void DidProcessXEvent(XEvent* xevent);
 
-  // Returns the Dispatcher based on the event's target window.
-  MessagePumpDispatcher* GetDispatcherForXEvent(const NativeEvent& xev) const;
-
-  ObserverList<MessagePumpObserver>& observers() { return observers_; }
-
-  // Overridden from MessagePumpDispatcher:
-  virtual uint32_t Dispatch(const NativeEvent& event) OVERRIDE;
-
-  // The event source for X events.
-  GSource* x_source_;
-
-  // The poll attached to |x_source_|.
-  scoped_ptr<GPollFD> x_poll_;
-
-  DispatchersMap dispatchers_;
-
-  // Dispatch calls can cause addition of new dispatchers as we iterate
-  // through them. Use ObserverList to ensure the iterator remains valid across
-  // additions.
-  ObserverList<MessagePumpDispatcher> root_window_dispatchers_;
-
+ private:
   // List of observers.
   ObserverList<MessagePumpObserver> observers_;
 
-  unsigned long x_root_window_;
-
   DISALLOW_COPY_AND_ASSIGN(MessagePumpX11);
 };