10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// found in the LICENSE file.
40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/events/platform/x11/x11_event_source.h"
60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <glib.h>
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <X11/Xlib.h>
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace ui {
110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace {
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct GLibX11Source : public GSource {
150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Note: The GLibX11Source is created and destroyed by GLib. So its
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // constructor/destructor may or may not get called.
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XDisplay* display;
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GPollFD* poll_fd;
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochgboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (XPending(gxsource->display))
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *timeout_ms = 0;
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *timeout_ms = -1;
270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return FALSE;
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochgboolean XSourceCheck(GSource* source) {
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return XPending(gxsource->display);
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochgboolean XSourceDispatch(GSource* source,
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                         GSourceFunc unused_func,
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                         gpointer data) {
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  X11EventSource* x11_source = static_cast<X11EventSource*>(data);
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  x11_source->DispatchXEvents();
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return TRUE;
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
430529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochGSourceFuncs XSourceFuncs = {
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XSourcePrepare,
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XSourceCheck,
460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XSourceDispatch,
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  NULL
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass X11EventSourceGlib : public X11EventSource {
510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public:
520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  explicit X11EventSourceGlib(XDisplay* display)
530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      : X11EventSource(display),
540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        x_source_(NULL) {
550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    InitXSource(ConnectionNumber(display));
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~X11EventSourceGlib() {
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_destroy(x_source_);
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_unref(x_source_);
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch private:
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void InitXSource(int fd) {
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    CHECK(!x_source_);
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    CHECK(display()) << "Unable to get connection to X server";
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    x_poll_.reset(new GPollFD());
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    x_poll_->fd = fd;
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    x_poll_->events = G_IO_IN;
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    x_poll_->revents = 0;
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    GLibX11Source* glib_x_source = static_cast<GLibX11Source*>
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        (g_source_new(&XSourceFuncs, sizeof(GLibX11Source)));
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    glib_x_source->display = display();
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    glib_x_source->poll_fd = x_poll_.get();
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    x_source_ = glib_x_source;
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_add_poll(x_source_, x_poll_.get());
800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_set_can_recurse(x_source_, TRUE);
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_set_callback(x_source_, NULL, this, NULL);
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    g_source_attach(x_source_, g_main_context_default());
830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // The GLib event source for X events.
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GSource* x_source_;
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // The poll attached to |x_source_|.
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<GPollFD> x_poll_;
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(X11EventSourceGlib);
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() {
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return scoped_ptr<PlatformEventSource>(
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      new X11EventSourceGlib(gfx::GetXDisplay()));
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace ui
102