1 // Copyright 2013 Intel Corporation. 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.
5 #include "ozone/wayland/dispatcher.h"
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <wayland-client.h>
14 #include "base/bind.h"
15 #include "ozone/wayland/dispatcher_delegate.h"
16 #include "ozone/wayland/display.h"
18 namespace ozonewayland {
19 WaylandDispatcher* WaylandDispatcher::instance_ = NULL;
23 int osEpollCreateCloExec(void);
25 static int setCloExecOrClose(int fd) {
31 flags = fcntl(fd, F_GETFD);
35 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
45 int osEpollCreateCloExec(void) {
49 fd = epoll_create1(EPOLL_CLOEXEC);
57 return setCloExecOrClose(fd);
61 void WaylandDispatcher::MotionNotify(float x, float y) {
63 delegate_->MotionNotify(x, y);
66 void WaylandDispatcher::ButtonNotify(unsigned handle,
72 delegate_->ButtonNotify(handle, state, flags, x, y);
75 void WaylandDispatcher::AxisNotify(float x,
80 delegate_->AxisNotify(x, y, xoffset, yoffset);
83 void WaylandDispatcher::PointerEnter(unsigned handle, float x, float y) {
85 delegate_->PointerEnter(handle, x, y);
88 void WaylandDispatcher::PointerLeave(unsigned handle, float x, float y) {
90 delegate_->PointerLeave(handle, x, y);
93 void WaylandDispatcher::KeyNotify(unsigned state,
97 delegate_->KeyNotify(state, code, modifiers);
100 void WaylandDispatcher::OutputSizeChanged(unsigned width, unsigned height) {
102 delegate_->OutputSizeChanged(width, height);
105 void WaylandDispatcher::PostTask(Task type) {
106 if (!IsRunning() || !active_)
113 message_loop_proxy()->PostTask(
114 FROM_HERE, base::Bind(&WaylandDispatcher::HandleFlush));
118 message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
119 &WaylandDispatcher::DisplayRun, this));
125 void WaylandDispatcher::SetWindowChangeObserver(
126 WindowChangeObserver* observer) {
128 delegate_->SetWindowChangeObserver(observer);
131 void WaylandDispatcher::SetDelegate(WaylandDispatcherDelegate* delegate) {
132 delegate_ = delegate;
136 void WaylandDispatcher::SetActive(bool active) {
139 delegate_->SetActive(active);
142 WaylandDispatcher::WaylandDispatcher(int fd)
143 : Thread("WaylandDispatcher"),
150 epoll_fd_ = osEpollCreateCloExec();
151 struct epoll_event ep;
152 ep.events = EPOLLIN | EPOLLOUT;
154 epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, display_fd_, &ep);
158 options.message_loop_type = base::MessageLoop::TYPE_IO;
159 StartWithOptions(options);
160 SetPriority(base::kThreadPriority_Background);
163 WaylandDispatcher::~WaylandDispatcher() {
178 void WaylandDispatcher::HandleFlush() {
179 wl_display* waylandDisp = WaylandDisplay::GetInstance()->display();
181 while (wl_display_prepare_read(waylandDisp) != 0)
182 wl_display_dispatch_pending(waylandDisp);
184 wl_display_flush(waylandDisp);
185 wl_display_read_events(waylandDisp);
186 wl_display_dispatch_pending(waylandDisp);
189 void WaylandDispatcher::DisplayRun(WaylandDispatcher* data) {
190 struct epoll_event ep[16];
193 // http://cgit.freedesktop.org/wayland/weston/tree/clients/window.c#n5531.
195 wl_display* waylandDisp = WaylandDisplay::GetInstance()->display();
196 wl_display_dispatch_pending(waylandDisp);
201 ret = wl_display_flush(waylandDisp);
202 if (ret < 0 && errno == EAGAIN) {
203 ep[0].events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;
204 epoll_ctl(data->epoll_fd_, EPOLL_CTL_MOD, data->display_fd_, &ep[0]);
205 } else if (ret < 0) {
209 count = epoll_wait(data->epoll_fd_, ep, 16, -1);
213 for (i = 0; i < count; i++) {
215 uint32_t event = ep[i].events;
217 if (event & EPOLLERR || event & EPOLLHUP)
220 if (event & EPOLLIN) {
221 ret = wl_display_dispatch(waylandDisp);
226 if (event & EPOLLOUT) {
227 ret = wl_display_flush(waylandDisp);
229 struct epoll_event eps;
230 memset(&eps, 0, sizeof(eps));
232 eps.events = EPOLLIN | EPOLLERR | EPOLLHUP;
233 epoll_ctl(data->epoll_fd_, EPOLL_CTL_MOD, data->display_fd_, &eps);
234 } else if (ret == -1 && errno != EAGAIN) {
242 } // namespace ozonewayland