blob: c475db6e78759b53abbee977f09b60e4056ac055 [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
Tomas Popela318da512018-11-13 06:32:23 +010011#include "modules/desktop_capture/linux/shared_x_display.h"
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000012
zijiehee0839092016-11-08 12:47:14 -080013#include <X11/Xlib.h>
14
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000015#include <algorithm>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
18#include "rtc_base/logging.h"
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000019
20namespace webrtc {
21
Yves Gerey665174f2018-06-19 15:03:05 +020022SharedXDisplay::SharedXDisplay(Display* display) : display_(display) {
zijiehee0839092016-11-08 12:47:14 -080023 RTC_DCHECK(display_);
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000024}
25
26SharedXDisplay::~SharedXDisplay() {
zijiehee0839092016-11-08 12:47:14 -080027 RTC_DCHECK(event_handlers_.empty());
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000028 XCloseDisplay(display_);
29}
30
31// static
Peter Boström26b08602015-06-04 15:18:17 +020032rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::Create(
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000033 const std::string& display_name) {
34 Display* display =
35 XOpenDisplay(display_name.empty() ? NULL : display_name.c_str());
36 if (!display) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010037 RTC_LOG(LS_ERROR) << "Unable to open display";
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000038 return NULL;
39 }
40 return new SharedXDisplay(display);
41}
42
43// static
Peter Boström26b08602015-06-04 15:18:17 +020044rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000045 return Create(std::string());
46}
47
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000048void SharedXDisplay::AddEventHandler(int type, XEventHandler* handler) {
49 event_handlers_[type].push_back(handler);
50}
51
52void SharedXDisplay::RemoveEventHandler(int type, XEventHandler* handler) {
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000053 EventHandlersMap::iterator handlers = event_handlers_.find(type);
54 if (handlers == event_handlers_.end())
55 return;
56
57 std::vector<XEventHandler*>::iterator new_end =
58 std::remove(handlers->second.begin(), handlers->second.end(), handler);
59 handlers->second.erase(new_end, handlers->second.end());
60
61 // Check if no handlers left for this event.
62 if (handlers->second.empty())
63 event_handlers_.erase(handlers);
64}
65
66void SharedXDisplay::ProcessPendingXEvents() {
67 // Hold reference to |this| to prevent it from being destroyed while
68 // processing events.
Peter Boström26b08602015-06-04 15:18:17 +020069 rtc::scoped_refptr<SharedXDisplay> self(this);
sergeyu@chromium.org7419a722013-10-13 00:44:09 +000070
71 // Find the number of events that are outstanding "now." We don't just loop
72 // on XPending because we want to guarantee this terminates.
73 int events_to_process = XPending(display());
74 XEvent e;
75
76 for (int i = 0; i < events_to_process; i++) {
77 XNextEvent(display(), &e);
78 EventHandlersMap::iterator handlers = event_handlers_.find(e.type);
79 if (handlers == event_handlers_.end())
80 continue;
81 for (std::vector<XEventHandler*>::iterator it = handlers->second.begin();
82 it != handlers->second.end(); ++it) {
83 if ((*it)->HandleXEvent(e))
84 break;
85 }
86 }
87}
88
sergeyu@chromium.org894e6fe2013-10-12 22:40:05 +000089} // namespace webrtc