blob: 853d50fb9a998ad29e243b09ccbba4914ab35d95 [file] [log] [blame]
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
12
zijiehee0839092016-11-08 12:47:14 -080013#include <X11/Xlib.h>
14
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000015#include <algorithm>
16
Edward Lemurc20978e2017-07-06 19:44:34 +020017#include "webrtc/rtc_base/checks.h"
18#include "webrtc/rtc_base/logging.h"
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000019
20namespace webrtc {
21
22SharedXDisplay::SharedXDisplay(Display* display)
23 : display_(display) {
zijiehee0839092016-11-08 12:47:14 -080024 RTC_DCHECK(display_);
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000025}
26
27SharedXDisplay::~SharedXDisplay() {
zijiehee0839092016-11-08 12:47:14 -080028 RTC_DCHECK(event_handlers_.empty());
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000029 XCloseDisplay(display_);
30}
31
32// static
Peter Boström26b08602015-06-04 15:18:17 +020033rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::Create(
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000034 const std::string& display_name) {
35 Display* display =
36 XOpenDisplay(display_name.empty() ? NULL : display_name.c_str());
37 if (!display) {
38 LOG(LS_ERROR) << "Unable to open display";
39 return NULL;
40 }
41 return new SharedXDisplay(display);
42}
43
44// static
Peter Boström26b08602015-06-04 15:18:17 +020045rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000046 return Create(std::string());
47}
48
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000049void SharedXDisplay::AddEventHandler(int type, XEventHandler* handler) {
50 event_handlers_[type].push_back(handler);
51}
52
53void SharedXDisplay::RemoveEventHandler(int type, XEventHandler* handler) {
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000054 EventHandlersMap::iterator handlers = event_handlers_.find(type);
55 if (handlers == event_handlers_.end())
56 return;
57
58 std::vector<XEventHandler*>::iterator new_end =
59 std::remove(handlers->second.begin(), handlers->second.end(), handler);
60 handlers->second.erase(new_end, handlers->second.end());
61
62 // Check if no handlers left for this event.
63 if (handlers->second.empty())
64 event_handlers_.erase(handlers);
65}
66
67void SharedXDisplay::ProcessPendingXEvents() {
68 // Hold reference to |this| to prevent it from being destroyed while
69 // processing events.
Peter Boström26b08602015-06-04 15:18:17 +020070 rtc::scoped_refptr<SharedXDisplay> self(this);
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000071
72 // Find the number of events that are outstanding "now." We don't just loop
73 // on XPending because we want to guarantee this terminates.
74 int events_to_process = XPending(display());
75 XEvent e;
76
77 for (int i = 0; i < events_to_process; i++) {
78 XNextEvent(display(), &e);
79 EventHandlersMap::iterator handlers = event_handlers_.find(e.type);
80 if (handlers == event_handlers_.end())
81 continue;
82 for (std::vector<XEventHandler*>::iterator it = handlers->second.begin();
83 it != handlers->second.end(); ++it) {
84 if ((*it)->HandleXEvent(e))
85 break;
86 }
87 }
88}
89
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000090} // namespace webrtc