Home | History | Annotate | Download | only in x11
      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/interface/logging.h"
     16 
     17 namespace webrtc {
     18 
     19 SharedXDisplay::SharedXDisplay(Display* display)
     20   : display_(display) {
     21   assert(display_);
     22 }
     23 
     24 SharedXDisplay::~SharedXDisplay() {
     25   assert(event_handlers_.empty());
     26   XCloseDisplay(display_);
     27 }
     28 
     29 // static
     30 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
     42 scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
     43   return Create(std::string());
     44 }
     45 
     46 void SharedXDisplay::AddEventHandler(int type, XEventHandler* handler) {
     47   event_handlers_[type].push_back(handler);
     48 }
     49 
     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 
     64 void SharedXDisplay::ProcessPendingXEvents() {
     65   // Hold reference to |this| to prevent it from being destroyed while
     66   // processing events.
     67   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