blob: 8221f549090b4ddb09674233ace0da25791c5b05 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chrome_browser_main_extra_parts_exo.h"
#include "base/memory/ptr_util.h"
#if defined(USE_GLIB)
#include <glib.h>
#endif
#include "base/command_line.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/ui/ash/ash_util.h"
#include "chrome/common/chrome_switches.h"
#include "components/exo/display.h"
#include "components/exo/wayland/server.h"
#include "components/exo/wm_helper_ash.h"
#include "components/exo/wm_helper_mus.h"
#include "content/public/browser/browser_thread.h"
#include "ui/arc/notification/arc_notification_surface_manager.h"
#if defined(USE_GLIB)
namespace {
struct GLibWaylandSource : public GSource {
// Note: The GLibWaylandSource is created and destroyed by GLib. So its
// constructor/destructor may or may not get called.
exo::wayland::Server* server;
GPollFD* poll_fd;
};
gboolean WaylandSourcePrepare(GSource* source, gint* timeout_ms) {
*timeout_ms = -1;
return FALSE;
}
gboolean WaylandSourceCheck(GSource* source) {
GLibWaylandSource* wayland_source = static_cast<GLibWaylandSource*>(source);
return (wayland_source->poll_fd->revents & G_IO_IN) ? TRUE : FALSE;
}
gboolean WaylandSourceDispatch(GSource* source,
GSourceFunc unused_func,
gpointer data) {
GLibWaylandSource* wayland_source = static_cast<GLibWaylandSource*>(source);
wayland_source->server->Dispatch(base::TimeDelta());
wayland_source->server->Flush();
return TRUE;
}
GSourceFuncs g_wayland_source_funcs = {WaylandSourcePrepare, WaylandSourceCheck,
WaylandSourceDispatch, nullptr};
} // namespace
class ChromeBrowserMainExtraPartsExo::WaylandWatcher {
public:
explicit WaylandWatcher(exo::wayland::Server* server)
: wayland_poll_(new GPollFD),
wayland_source_(static_cast<GLibWaylandSource*>(
g_source_new(&g_wayland_source_funcs, sizeof(GLibWaylandSource)))) {
wayland_poll_->fd = server->GetFileDescriptor();
wayland_poll_->events = G_IO_IN;
wayland_poll_->revents = 0;
wayland_source_->server = server;
wayland_source_->poll_fd = wayland_poll_.get();
g_source_add_poll(wayland_source_, wayland_poll_.get());
g_source_set_can_recurse(wayland_source_, TRUE);
g_source_set_callback(wayland_source_, nullptr, nullptr, nullptr);
g_source_attach(wayland_source_, g_main_context_default());
}
~WaylandWatcher() {
g_source_destroy(wayland_source_);
g_source_unref(wayland_source_);
}
private:
// The poll attached to |wayland_source_|.
std::unique_ptr<GPollFD> wayland_poll_;
// The GLib event source for wayland events.
GLibWaylandSource* wayland_source_;
DISALLOW_COPY_AND_ASSIGN(WaylandWatcher);
};
#else
class ChromeBrowserMainExtraPartsExo::WaylandWatcher
: public base::MessagePumpLibevent::Watcher {
public:
explicit WaylandWatcher(exo::wayland::Server* server) : server_(server) {
base::MessageLoopForUI::current()->WatchFileDescriptor(
server_->GetFileDescriptor(),
true, // persistent
base::MessagePumpLibevent::WATCH_READ, &controller_, this);
}
// base::MessagePumpLibevent::Watcher:
void OnFileCanReadWithoutBlocking(int fd) override {
server_->Dispatch(base::TimeDelta());
server_->Flush();
}
void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
private:
base::MessagePumpLibevent::FileDescriptorWatcher controller_;
exo::wayland::Server* const server_;
DISALLOW_COPY_AND_ASSIGN(WaylandWatcher);
};
#endif
ChromeBrowserMainExtraPartsExo::ChromeBrowserMainExtraPartsExo() {}
ChromeBrowserMainExtraPartsExo::~ChromeBrowserMainExtraPartsExo() {}
void ChromeBrowserMainExtraPartsExo::PreProfileInit() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWaylandServer))
return;
arc_notification_surface_manager_ =
base::MakeUnique<arc::ArcNotificationSurfaceManager>();
if (chrome::IsRunningInMash())
wm_helper_ = base::MakeUnique<exo::WMHelperMus>();
else
wm_helper_ = base::MakeUnique<exo::WMHelperAsh>();
exo::WMHelper::SetInstance(wm_helper_.get());
display_ =
base::MakeUnique<exo::Display>(arc_notification_surface_manager_.get());
wayland_server_ = exo::wayland::Server::Create(display_.get());
wayland_watcher_ = base::MakeUnique<WaylandWatcher>(wayland_server_.get());
}
void ChromeBrowserMainExtraPartsExo::PostMainMessageLoopRun() {
wayland_watcher_.reset();
wayland_server_.reset();
if (wm_helper_) {
exo::WMHelper::SetInstance(nullptr);
wm_helper_.reset();
}
}