1 /*
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 
13 #include <algorithm>
14 
15 #include "webrtc/system_wrappers/include/logging.h"
16 
17 namespace webrtc {
18 
SharedXDisplay(Display * display)19 SharedXDisplay::SharedXDisplay(Display* display)
20   : display_(display) {
21   assert(display_);
22 }
23 
~SharedXDisplay()24 SharedXDisplay::~SharedXDisplay() {
25   assert(event_handlers_.empty());
26   XCloseDisplay(display_);
27 }
28 
29 // static
Create(const std::string & display_name)30 rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::Create(
31     const std::string& display_name) {
32   Display* display =
33       XOpenDisplay(display_name.empty() ? NULL : display_name.c_str());
34   if (!display) {
35     LOG(LS_ERROR) << "Unable to open display";
36     return NULL;
37   }
38   return new SharedXDisplay(display);
39 }
40 
41 // static
CreateDefault()42 rtc::scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
43   return Create(std::string());
44 }
45 
AddEventHandler(int type,XEventHandler * handler)46 void SharedXDisplay::AddEventHandler(int type, XEventHandler* handler) {
47   event_handlers_[type].push_back(handler);
48 }
49 
RemoveEventHandler(int type,XEventHandler * handler)50 void SharedXDisplay::RemoveEventHandler(int type, XEventHandler* handler) {
51   EventHandlersMap::iterator handlers = event_handlers_.find(type);
52   if (handlers == event_handlers_.end())
53     return;
54 
55   std::vector<XEventHandler*>::iterator new_end =
56       std::remove(handlers->second.begin(), handlers->second.end(), handler);
57   handlers->second.erase(new_end, handlers->second.end());
58 
59   // Check if no handlers left for this event.
60   if (handlers->second.empty())
61     event_handlers_.erase(handlers);
62 }
63 
ProcessPendingXEvents()64 void SharedXDisplay::ProcessPendingXEvents() {
65   // Hold reference to |this| to prevent it from being destroyed while
66   // processing events.
67   rtc::scoped_refptr<SharedXDisplay> self(this);
68 
69   // Find the number of events that are outstanding "now."  We don't just loop
70   // on XPending because we want to guarantee this terminates.
71   int events_to_process = XPending(display());
72   XEvent e;
73 
74   for (int i = 0; i < events_to_process; i++) {
75     XNextEvent(display(), &e);
76     EventHandlersMap::iterator handlers = event_handlers_.find(e.type);
77     if (handlers == event_handlers_.end())
78       continue;
79     for (std::vector<XEventHandler*>::iterator it = handlers->second.begin();
80          it != handlers->second.end(); ++it) {
81       if ((*it)->HandleXEvent(e))
82         break;
83     }
84   }
85 }
86 
87 }  // namespace webrtc
88