Bug 1036653 - X11-specific support, r=rjesup,gcp
authorMatthew A. Miller <linuxwolf@outer-planes.net>
Wed, 20 Aug 2014 15:49:28 -0600
changeset 223592 7818b389a25bf46c29ee474da29581d4eadee308
parent 223591 2356923247d09f037e44e2d017677aa2cb6a08c3
child 223593 e5f46d90549ce285e2ee46af4b10c806be3164b0
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrjesup, gcp
bugs1036653
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1036653 - X11-specific support, r=rjesup,gcp * * * Bug 1036653 - Interdiff over X11-specific to address review comments from Jesup, GCP * * * Bug 1036653 - Interdiff over X11-specific to address review comments from Jesup
media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture.gypi
media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.h
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.h
old mode 100644
new mode 100755
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc
@@ -4,94 +4,359 @@
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
 #include "webrtc/modules/desktop_capture/window_capturer.h"
 #include "webrtc/modules/desktop_capture/app_capturer.h"
+#include "webrtc/modules/desktop_capture/screen_capturer.h"
+#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
+#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
 
 #include <assert.h>
 #include <string.h>
 #include <X11/Xatom.h>
 #include <X11/extensions/Xcomposite.h>
 #include <X11/extensions/Xrender.h>
 #include <X11/Xutil.h>
+#include <X11/Xregion.h>
 
 #include <algorithm>
 
 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
 #include "webrtc/modules/desktop_capture/desktop_frame.h"
 #include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
 #include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/scoped_refptr.h"
 
 namespace webrtc {
 
 namespace {
 
+class WindowsCapturerProxy : DesktopCapturer::Callback {
+public:
+  WindowsCapturerProxy() : window_capturer_(WindowCapturer::Create()) {
+    window_capturer_->Start(this);
+  }
+  ~WindowsCapturerProxy() {}
+  void SelectWindow(WindowId windowId) { window_capturer_->SelectWindow(windowId); }
+  scoped_ptr<DesktopFrame>& GetFrame() { return frame_; }
+  void Capture(const DesktopRegion& region) { window_capturer_->Capture(region); }
 
-class AppCapturerLinux : public AppCapturer{
+  // Callback interface
+  virtual SharedMemory *CreateSharedMemory(size_t) OVERRIDE { return NULL; }
+  virtual void OnCaptureCompleted(DesktopFrame *frame) OVERRIDE { frame_.reset(frame); }
+
+private:
+  scoped_ptr<WindowCapturer> window_capturer_;
+  scoped_ptr<DesktopFrame> frame_;
+};
+
+class ScreenCapturerProxy : DesktopCapturer::Callback {
+public:
+  ScreenCapturerProxy() : screen_capturer_(ScreenCapturer::Create()) {
+    screen_capturer_->SelectScreen(kFullDesktopScreenId);
+    screen_capturer_->Start(this);
+  }
+  void Capture(const DesktopRegion& region) { screen_capturer_->Capture(region); }
+  scoped_ptr<DesktopFrame>& GetFrame() { return frame_; }
+
+  // Callback interface
+  virtual SharedMemory *CreateSharedMemory(size_t) OVERRIDE { return NULL; }
+  virtual void OnCaptureCompleted(DesktopFrame *frame) OVERRIDE { frame_.reset(frame); }
+protected:
+  scoped_ptr<ScreenCapturer> screen_capturer_;
+  scoped_ptr<DesktopFrame> frame_;
+};
+
+class AppCapturerLinux : public AppCapturer {
 public:
   AppCapturerLinux(const DesktopCaptureOptions& options);
   virtual ~AppCapturerLinux();
 
   // AppCapturer interface.
   virtual bool GetAppList(AppList* apps) OVERRIDE;
-  virtual bool SelectApp(ProcessId id) OVERRIDE;
+  virtual bool SelectApp(ProcessId processId) OVERRIDE;
   virtual bool BringAppToFront() OVERRIDE;
 
   // DesktopCapturer interface.
   virtual void Start(Callback* callback) OVERRIDE;
   virtual void Capture(const DesktopRegion& region) OVERRIDE;
 
+protected:
+  Display* GetDisplay() { return x_display_->display(); }
+  bool UpdateRegions();
 
+  void CaptureWebRTC(const DesktopRegion& region);
+  void CaptureSample(const DesktopRegion& region);
+
+  void FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame,Region rgn, uint32_t color);
 private:
   Callback* callback_;
   ProcessId selected_process_;
 
+  // Sample Mode
+  ScreenCapturerProxy screen_capturer_proxy_;
+  // Mask of foreground (non-app windows in front of selected)
+  Region rgn_mask_;
+  // Region of selected windows
+  Region rgn_visual_;
+  // Mask of background (desktop, non-app windows behind selected)
+  Region rgn_background_;
+
+  // WebRtc Window mode
+  WindowsCapturerProxy window_capturer_proxy_;
+
+  scoped_refptr<SharedXDisplay> x_display_;
   DISALLOW_COPY_AND_ASSIGN(AppCapturerLinux);
 };
 
 AppCapturerLinux::AppCapturerLinux(const DesktopCaptureOptions& options)
-  : callback_(NULL),
-    selected_process_(0) {
+    : callback_(NULL),
+      selected_process_(0),
+      x_display_(options.x_display()) {
+  rgn_mask_ = XCreateRegion();
+  rgn_visual_ = XCreateRegion();
+  rgn_background_ = XCreateRegion();
 }
 
 AppCapturerLinux::~AppCapturerLinux() {
+  if (rgn_mask_) {
+    XDestroyRegion(rgn_mask_);
+  }
+  if (rgn_visual_) {
+    XDestroyRegion(rgn_visual_);
+  }
+  if (rgn_background_) {
+    XDestroyRegion(rgn_background_);
+  }
 }
 
 // AppCapturer interface.
-bool AppCapturerLinux::GetAppList(AppList* apps){
-  // Not implemented yet: See Bug 1036653
+bool AppCapturerLinux::GetAppList(AppList* apps) {
+  // Implemented in DesktopDeviceInfo
   return true;
 }
-bool AppCapturerLinux::SelectApp(ProcessId id){
-  // Not implemented yet: See Bug 1036653
+bool AppCapturerLinux::SelectApp(ProcessId processId) {
+  selected_process_ = processId;
   return true;
 }
-bool AppCapturerLinux::BringAppToFront(){
+bool AppCapturerLinux::BringAppToFront() {
   // Not implemented yet: See Bug 1036653
   return true;
 }
 
 // DesktopCapturer interface.
 void AppCapturerLinux::Start(Callback* callback) {
   assert(!callback_);
   assert(callback);
 
   callback_ = callback;
 }
 
 void AppCapturerLinux::Capture(const DesktopRegion& region) {
-  // Not implemented yet: See Bug 1036653
+  CaptureSample(region);
+}
+
+void AppCapturerLinux::CaptureWebRTC(const DesktopRegion& region) {
+  XErrorTrap error_trap(GetDisplay());
+
+  int nScreenWidth = DisplayWidth(GetDisplay(), DefaultScreen(GetDisplay()));
+  int nScreenHeight = DisplayHeight(GetDisplay(), DefaultScreen(GetDisplay()));
+  scoped_ptr<DesktopFrame> frame(new BasicDesktopFrame(DesktopSize(nScreenWidth, nScreenHeight)));
+
+  WindowUtilX11 window_util_x11(x_display_);
+
+  ::Window root_window = XRootWindow(GetDisplay(), DefaultScreen(GetDisplay()));
+  ::Window parent;
+  ::Window root_return;
+  ::Window *children;
+  unsigned int num_children;
+  int status = XQueryTree(GetDisplay(), root_window, &root_return, &parent,
+      &children, &num_children);
+  if (status == 0) {
+    LOG(LS_ERROR) << "Failed to query for child windows for screen "
+        << DefaultScreen(GetDisplay());
+    return;
+  }
+
+  for (unsigned int i = 0; i < num_children; ++i) {
+    ::Window app_window = window_util_x11.GetApplicationWindow(children[i]);
+    if (!app_window) {
+      continue;
+    }
+
+    unsigned int processId = window_util_x11.GetWindowProcessID(app_window);
+    if(processId != 0 && processId == selected_process_) {
+      // capture
+      window_capturer_proxy_.SelectWindow(app_window);
+      window_capturer_proxy_.Capture(region);
+      DesktopFrame* frameWin = window_capturer_proxy_.GetFrame().get();
+      if (frameWin == NULL) {
+        continue;
+      }
+
+      XRectangle  win_rect;
+      window_util_x11.GetWindowRect(app_window,win_rect, false);
+      if (win_rect.width <= 0 || win_rect.height <= 0) {
+        continue;
+      }
+
+      DesktopSize winFrameSize = frameWin->size();
+      DesktopRect target_rect = DesktopRect::MakeXYWH(win_rect.x,
+                                                      win_rect.y,
+                                                      winFrameSize.width(),
+                                                      winFrameSize.height());
+
+      // bitblt into background frame
+      frame->CopyPixelsFrom(*frameWin, DesktopVector(0, 0), target_rect);
+    }
+  }
+
+  if (children) {
+    XFree(children);
+  }
+
+  // trigger event
+  if (callback_) {
+    callback_->OnCaptureCompleted(error_trap.GetLastErrorAndDisable() != 0 ?
+                                  NULL :
+                                  frame.release());
+  }
+}
+
+void AppCapturerLinux::CaptureSample(const DesktopRegion& region) {
+  XErrorTrap error_trap(GetDisplay());
+
+  //Capture screen >> set root window as capture window
+  screen_capturer_proxy_.Capture(region);
+  DesktopFrame* frame = screen_capturer_proxy_.GetFrame().get();
+  if (frame) {
+    // calculate app visual/foreground region
+    UpdateRegions();
+
+    // TODO: background/foreground mask colors should be configurable; see Bug 1054503
+    // fill background with black
+    FillDesktopFrameRegionWithColor(frame, rgn_background_, 0xFF000000);
+
+    // fill foreground with yellow
+    FillDesktopFrameRegionWithColor(frame, rgn_mask_, 0xFFFFFF00);
+ }
+
+  // trigger event
+  if (callback_) {
+    callback_->OnCaptureCompleted(error_trap.GetLastErrorAndDisable() != 0 ?
+                                  NULL :
+                                  screen_capturer_proxy_.GetFrame().release());
+  }
+}
+
+void AppCapturerLinux::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame, Region rgn, uint32_t color) {
+  XErrorTrap error_trap(GetDisplay());
+
+  if (!pDesktopFrame) {
+    return;
+  }
+  if (XEmptyRegion(rgn)) {
+    return;
+  }
+
+  REGION * st_rgn = (REGION *)rgn;
+  if(st_rgn && st_rgn->numRects > 0) {
+    for (short i = 0; i < st_rgn->numRects; i++) {
+      for (short j = st_rgn->rects[i].y1; j < st_rgn->rects[i].y2; j++) {
+        uint32_t* dst_pos = reinterpret_cast<uint32_t*>(pDesktopFrame->data() + pDesktopFrame->stride() * j);
+        for (short k = st_rgn->rects[i].x1; k < st_rgn->rects[i].x2; k++) {
+          dst_pos[k] = color;
+        }
+      }
+    }
+  }
+}
+
+bool AppCapturerLinux::UpdateRegions() {
+  XErrorTrap error_trap(GetDisplay());
+
+  XSubtractRegion(rgn_visual_, rgn_visual_, rgn_visual_);
+  XSubtractRegion(rgn_mask_, rgn_mask_, rgn_mask_);
+  WindowUtilX11 window_util_x11(x_display_);
+  int num_screens = XScreenCount(GetDisplay());
+  for (int screen = 0; screen < num_screens; ++screen) {
+    int nScreenCX = DisplayWidth(GetDisplay(), screen);
+    int nScreenCY = DisplayHeight(GetDisplay(), screen);
+
+    XRectangle  screen_rect;
+    screen_rect.x = 0;
+    screen_rect.y = 0;
+    screen_rect.width = nScreenCX;
+    screen_rect.height = nScreenCY;
+
+    XUnionRectWithRegion(&screen_rect, rgn_background_, rgn_background_);
+    XXorRegion(rgn_mask_, rgn_mask_, rgn_mask_);
+    XXorRegion(rgn_visual_, rgn_visual_, rgn_visual_);
+
+    ::Window root_window = XRootWindow(GetDisplay(), screen);
+    ::Window parent;
+    ::Window root_return;
+    ::Window *children;
+    unsigned int num_children;
+    int status = XQueryTree(GetDisplay(), root_window, &root_return, &parent, &children, &num_children);
+    if (status == 0) {
+      LOG(LS_ERROR) << "Failed to query for child windows for screen " << screen;
+      continue;
+    }
+    for (unsigned int i = 0; i < num_children; ++i) {
+      ::Window app_window = window_util_x11.GetApplicationWindow(children[i]);
+      if (!app_window) {
+        continue;
+      }
+
+      // Get window region
+      XRectangle  win_rect;
+      window_util_x11.GetWindowRect(app_window, win_rect, true);
+      if (win_rect.width <= 0 || win_rect.height <= 0) {
+        continue;
+      }
+
+      Region win_rgn = XCreateRegion();
+      XUnionRectWithRegion(&win_rect, win_rgn, win_rgn);
+      // update rgn_visual_ , rgn_mask_,
+      unsigned int processId = window_util_x11.GetWindowProcessID(app_window);
+      if (processId != 0 && processId == selected_process_) {
+        XUnionRegion(rgn_visual_, win_rgn, rgn_visual_);
+        XSubtractRegion(rgn_mask_, win_rgn, rgn_mask_);
+      } else {
+        Region win_rgn_intersect = XCreateRegion();
+        XIntersectRegion(rgn_visual_, win_rgn, win_rgn_intersect);
+
+        XSubtractRegion(rgn_visual_, win_rgn_intersect, rgn_visual_);
+        XUnionRegion(win_rgn_intersect, rgn_mask_, rgn_mask_);
+
+        if (win_rgn_intersect) {
+          XDestroyRegion(win_rgn_intersect);
+        }
+      }
+      if (win_rgn) {
+        XDestroyRegion(win_rgn);
+      }
+    }
+
+    if (children) {
+      XFree(children);
+    }
+  }
+
+  XSubtractRegion(rgn_background_, rgn_visual_, rgn_background_);
+
+  return true;
 }
 
 }  // namespace
 
 // static
 AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) {
   return new AppCapturerLinux(options);
 }
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture.gypi
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture.gypi
@@ -76,16 +76,18 @@
         ['use_x11 == 1', {
           'defines':[
             'USE_X11',
           ],
           'sources': [
             "mouse_cursor_monitor_x11.cc",
             "screen_capturer_x11.cc",
             "window_capturer_x11.cc",
+            "x11/shared_x_util.h",
+            "x11/shared_x_util.cc",
             "x11/shared_x_display.h",
             "x11/shared_x_display.cc",
             "x11/x_error_trap.cc",
             "x11/x_error_trap.h",
             "x11/x_server_pixel_buffer.cc",
             "x11/x_server_pixel_buffer.h",
             "x11/desktop_device_info_x11.h",
             "x11/desktop_device_info_x11.cc",
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
@@ -22,74 +22,22 @@
 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
 #include "webrtc/modules/desktop_capture/desktop_frame.h"
 #include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
 #include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/scoped_refptr.h"
+#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
 
 namespace webrtc {
 
 namespace {
 
-// Convenience wrapper for XGetWindowProperty() results.
-template <class PropertyType>
-class XWindowProperty {
- public:
-  XWindowProperty(Display* display, Window window, Atom property)
-      : is_valid_(false),
-        size_(0),
-        data_(NULL) {
-    const int kBitsPerByte = 8;
-    Atom actual_type;
-    int actual_format;
-    unsigned long bytes_after;  // NOLINT: type required by XGetWindowProperty
-    int status = XGetWindowProperty(display, window, property, 0L, ~0L, False,
-                                    AnyPropertyType, &actual_type,
-                                    &actual_format, &size_,
-                                    &bytes_after, &data_);
-    if (status != Success) {
-      data_ = NULL;
-      return;
-    }
-    if (sizeof(PropertyType) * kBitsPerByte != actual_format) {
-      size_ = 0;
-      return;
-    }
-
-    is_valid_ = true;
-  }
-
-  ~XWindowProperty() {
-    if (data_)
-      XFree(data_);
-  }
-
-  // True if we got properly value successfully.
-  bool is_valid() const { return is_valid_; }
-
-  // Size and value of the property.
-  size_t size() const { return size_; }
-  const PropertyType* data() const {
-    return reinterpret_cast<PropertyType*>(data_);
-  }
-  PropertyType* data() {
-    return reinterpret_cast<PropertyType*>(data_);
-  }
-
- private:
-  bool is_valid_;
-  unsigned long size_;  // NOLINT: type required by XGetWindowProperty
-  unsigned char* data_;
-
-  DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
-};
-
 class WindowCapturerLinux : public WindowCapturer,
                             public SharedXDisplay::XEventHandler {
  public:
   WindowCapturerLinux(const DesktopCaptureOptions& options);
   virtual ~WindowCapturerLinux();
 
   // WindowCapturer interface.
   virtual bool GetWindowList(WindowList* windows) OVERRIDE;
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
@@ -1,14 +1,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "webrtc/modules/desktop_capture/x11/desktop_device_info_x11.h"
 #include "webrtc/modules/desktop_capture/window_capturer.h"
+#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
+#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/scoped_refptr.h"
+#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
+#include <unistd.h>
+#include <stdio.h>
 
 namespace webrtc{
 
 DesktopDeviceInfo * DesktopDeviceInfoImpl::Create() {
   DesktopDeviceInfoX11 * pDesktopDeviceInfo = new DesktopDeviceInfoX11();
   if (pDesktopDeviceInfo && pDesktopDeviceInfo->Init() != 0){
     delete pDesktopDeviceInfo;
     pDesktopDeviceInfo = NULL;
@@ -18,50 +26,95 @@ DesktopDeviceInfo * DesktopDeviceInfoImp
 
 DesktopDeviceInfoX11::DesktopDeviceInfoX11() {
 }
 
 DesktopDeviceInfoX11::~DesktopDeviceInfoX11() {
 }
 
 #if !defined(MULTI_MONITOR_SCREENSHARE)
-int32_t DesktopDeviceInfoX11::MultiMonitorScreenshare()
+void DesktopDeviceInfoX11::MultiMonitorScreenshare()
 {
   DesktopDisplayDevice *pDesktopDeviceInfo = new DesktopDisplayDevice;
   if (pDesktopDeviceInfo) {
     pDesktopDeviceInfo->setScreenId(0);
     pDesktopDeviceInfo->setDeviceName("Primary Monitor");
     pDesktopDeviceInfo->setUniqueIdName("\\screen\\monitor#1");
 
     desktop_display_list_[pDesktopDeviceInfo->getScreenId()] = pDesktopDeviceInfo;
   }
-  return 0;
 }
 #endif
 
-int32_t DesktopDeviceInfoX11::Init() {
+void DesktopDeviceInfoX11::InitializeScreenList() {
 #if !defined(MULTI_MONITOR_SCREENSHARE)
   MultiMonitorScreenshare();
 #endif
-
-  initializeWindowList();
+}
+void DesktopDeviceInfoX11::InitializeApplicationList() {
+  //List all running applications exclude background process.
+  scoped_refptr<SharedXDisplay> SharedDisplay = SharedXDisplay::CreateDefault();
+  XErrorTrap error_trap(SharedDisplay->display());
 
-  return 0;
-}
+  WindowUtilX11 window_util_x11(SharedDisplay);
+  int num_screens = XScreenCount(SharedDisplay->display());
+  for (int screen = 0; screen < num_screens; ++screen) {
+    ::Window root_window = XRootWindow(SharedDisplay->display(), screen);
+    ::Window parent;
+    ::Window *children;
+    unsigned int num_children;
+    int status = XQueryTree(SharedDisplay->display(), root_window, &root_window, &parent,
+        &children, &num_children);
+    if (status == 0) {
+      LOG(LS_ERROR) << "Failed to query for child windows for screen " << screen;
+      continue;
+    }
+
+    for (unsigned int i = 0; i < num_children; ++i) {
+      ::Window app_window = window_util_x11.GetApplicationWindow(children[num_children - 1 - i]);
+
+      if (!app_window
+          || window_util_x11.IsDesktopElement(app_window)
+          || window_util_x11.GetWindowStatus(app_window) == WithdrawnState) {
+        continue;
+      }
 
-int32_t DesktopDeviceInfoX11::Refresh() {
-#if !defined(MULTI_MONITOR_SCREENSHARE)
-  std::map<intptr_t,DesktopDisplayDevice*>::iterator iterDevice;
-  for (iterDevice=desktop_display_list_.begin(); iterDevice!=desktop_display_list_.end(); iterDevice++){
-    DesktopDisplayDevice * pDesktopDisplayDevice = iterDevice->second;
-    delete pDesktopDisplayDevice;
-    iterDevice->second = NULL;
+      unsigned int processId = window_util_x11.GetWindowProcessID(app_window);
+      // filter out non-process
+      if (processId == 0) {
+        continue;
+      }
+      // filter out current process
+      if (processId == getpid()) {
+        continue;
+      }
+
+      // Add one application
+      DesktopApplication *pDesktopApplication = new DesktopApplication;
+      if (!pDesktopApplication) {
+        continue;
+      }
+
+      // process id
+      pDesktopApplication->setProcessId(processId);
+
+      // process path name
+      pDesktopApplication->setProcessPathName("");
+
+      // application name
+      std::string strAppName;
+      window_util_x11.GetWindowTitle(app_window, &strAppName);
+      pDesktopApplication->setProcessAppName(strAppName.c_str());
+
+      // unique id name
+      char idStr[64];
+      snprintf(idStr, sizeof(idStr), "%ld", pDesktopApplication->getProcessId());
+      pDesktopApplication->setUniqueIdName(idStr);
+      desktop_application_list_[processId] = pDesktopApplication;
+    }
+
+    if (children) {
+      XFree(children);
+    }
   }
-  desktop_display_list_.clear();
-  MultiMonitorScreenshare();
-#endif
-
-  RefreshWindowList();
-
-  return 0;
 }
 
 } //namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.h
@@ -1,8 +1,12 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_X11_DEVICE_INFO_H_
 #define WEBRTC_MODULES_DESKTOP_CAPTURE_X11_DEVICE_INFO_H_
 
 #include "webrtc/typedefs.h"
@@ -10,20 +14,21 @@
 
 namespace webrtc {
 
 class DesktopDeviceInfoX11 : public DesktopDeviceInfoImpl {
 public:
   DesktopDeviceInfoX11();
   ~DesktopDeviceInfoX11();
 
+protected:
   //DesktopDeviceInfo Interfaces
-  virtual int32_t Init();
-  virtual int32_t Refresh();
+  virtual void InitializeApplicationList() OVERRIDE;
+  virtual void InitializeScreenList() OVERRIDE;
 
 private:
 #if !defined(MULTI_MONITOR_SCREENSHARE)
-  int32_t MultiMonitorScreenshare();
+  void MultiMonitorScreenshare();
 #endif
 };
 
 }// namespace webrtc
 #endif //WEBRTC_MODULES_DESKTOP_CAPTURE_X11_DEVICE_INFO_H_
new file mode 100755
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.cc
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
+
+namespace webrtc {
+
+WindowUtilX11::WindowUtilX11(scoped_refptr<SharedXDisplay> x_display) {
+  x_display_ = x_display;
+  wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
+  window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
+  normal_window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE_NORMAL", True);
+  process_atom_ = XInternAtom(display(), "_NET_WM_PID", True);
+  frame_extends_atom_ = XInternAtom(display(), "_NET_FRAME_EXTENTS", True);
+}
+
+WindowUtilX11::~WindowUtilX11() {
+}
+
+::Window WindowUtilX11::GetApplicationWindow(::Window window) {
+  // Get WM_STATE property of the window.
+  XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_);
+
+  // WM_STATE is considered to be set to WithdrawnState when it missing.
+  int32_t state = window_state.is_valid() ? *window_state.data() : WithdrawnState;
+
+  if (state == NormalState) {
+    // Window has WM_STATE==NormalState. Return it.
+    return window;
+  } else if (state == IconicState) {
+    // Window is in minimized. Skip it.
+    return 0;
+  }
+
+  // If the window is in WithdrawnState then look at all of its children.
+  ::Window root, parent;
+  ::Window *children;
+  unsigned int num_children;
+  if (!XQueryTree(display(), window, &root, &parent, &children, &num_children)) {
+    LOG(LS_ERROR) << "Failed to query for child windows although window"
+                  << "does not have a valid WM_STATE.";
+    return 0;
+  }
+  ::Window app_window = 0;
+  for (unsigned int i = 0; i < num_children; ++i) {
+    app_window = GetApplicationWindow(children[i]);
+    if (app_window) {
+      break;
+    }
+  }
+
+  if (children) {
+    XFree(children);
+  }
+  return app_window;
+}
+
+bool WindowUtilX11::IsDesktopElement(::Window window) {
+  if (window == 0) {
+    return false;
+  }
+
+  // First look for _NET_WM_WINDOW_TYPE. The standard
+  // (http://standards.freedesktop.org/wm-spec/latest/ar01s05.html#id2760306)
+  // says this hint *should* be present on all windows, and we use the existence
+  // of _NET_WM_WINDOW_TYPE_NORMAL in the property to indicate a window is not
+  // a desktop element (that is, only "normal" windows should be shareable).
+  XWindowProperty<uint32_t> window_type(display(), window, window_type_atom_);
+  if (window_type.is_valid() && window_type.size() > 0) {
+    uint32_t* end = window_type.data() + window_type.size();
+    bool is_normal = (end != std::find(window_type.data(), end, normal_window_type_atom_));
+    return !is_normal;
+  }
+
+  // Fall back on using the hint.
+  XClassHint class_hint;
+  Status status = XGetClassHint(display(), window, &class_hint);
+  bool result = false;
+  if (status == 0) {
+    // No hints, assume this is a normal application window.
+    return result;
+  }
+
+  if (strcmp("gnome-panel", class_hint.res_name) == 0 ||
+      strcmp("desktop_window", class_hint.res_name) == 0) {
+    result = true;
+  }
+  XFree(class_hint.res_name);
+  XFree(class_hint.res_class);
+  return result;
+}
+
+bool WindowUtilX11::GetWindowTitle(::Window window, std::string* title) {
+  int status;
+  bool result = false;
+  XTextProperty window_name;
+  window_name.value = NULL;
+  if (window) {
+    char * pWinName = NULL;
+    if(XFetchName(display(), window, &pWinName)){
+      *title = pWinName;
+      XFree(pWinName);
+      result = true;
+    }
+    else{
+      status = XGetWMName(display(), window, &window_name);
+      if (status && window_name.value && window_name.nitems) {
+        int cnt;
+        char **list = NULL;
+        status = Xutf8TextPropertyToTextList(display(), &window_name, &list,
+                                             &cnt);
+        if (status >= Success && cnt && *list) {
+          if (cnt > 1) {
+            LOG(LS_INFO) << "Window has " << cnt << " text properties, only using the first one.";
+          }
+          *title = *list;
+          result = true;
+        }
+        if (list) {
+          XFreeStringList(list);
+        }
+      }
+      if (window_name.value) {
+        XFree(window_name.value);
+      }
+    }
+  }
+  return result;
+}
+
+bool WindowUtilX11::BringWindowToFront(::Window window) {
+  if (!window) {
+    return false;
+  }
+
+  unsigned int num_children;
+  ::Window* children;
+  ::Window parent;
+  ::Window root;
+  // Find the root window to pass event to.
+  int status = XQueryTree(display(), window, &root, &parent, &children, &num_children);
+  if (status == 0) {
+    LOG(LS_ERROR) << "Failed to query for the root window.";
+    return false;
+  }
+
+  if (children) {
+    XFree(children);
+  }
+
+  XRaiseWindow(display(), window);
+
+  // Some window managers (e.g., metacity in GNOME) consider it illegal to
+  // raise a window without also giving it input focus with
+  // _NET_ACTIVE_WINDOW, so XRaiseWindow() on its own isn't enough.
+  Atom atom = XInternAtom(display(), "_NET_ACTIVE_WINDOW", True);
+  if (atom != None) {
+    XEvent xev;
+    xev.xclient.type = ClientMessage;
+    xev.xclient.serial = 0;
+    xev.xclient.send_event = True;
+    xev.xclient.window = window;
+    xev.xclient.message_type = atom;
+
+    // The format member is set to 8, 16, or 32 and specifies whether the
+    // data should be viewed as a list of bytes, shorts, or longs.
+    xev.xclient.format = 32;
+
+    memset(xev.xclient.data.l, 0, sizeof(xev.xclient.data.l));
+
+    XSendEvent(display(),
+               root,
+               False,
+               SubstructureRedirectMask | SubstructureNotifyMask,
+               &xev);
+  }
+  XFlush(display());
+  return true;
+}
+
+int WindowUtilX11::GetWindowProcessID(::Window window) {
+  // Get _NET_WM_PID property of the window.
+  XWindowProperty<uint32_t> process_id(display(), window, process_atom_);
+
+  return process_id.is_valid() ? *process_id.data() : 0;
+}
+
+int32_t WindowUtilX11::GetWindowStatus(::Window window) {
+  // Get WM_STATE property of the window.
+  XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_);
+
+  // WM_STATE is considered to be set to -1 when it missing.
+  int32_t state = window_state.is_valid() ? *window_state.data() : -1;
+  return state;
+}
+
+bool WindowUtilX11::GetWindowFrameExtents(::Window window,
+                                          int32_t &left, int32_t &top,
+                                          int32_t &right, int32_t &bottom) {
+  //reset it first
+  left = top = right = bottom =0;
+
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems;
+  unsigned long bytes_remaining;
+  unsigned char *data;
+  int status;
+
+  status = XGetWindowProperty(display(),
+                              window,
+                              frame_extends_atom_,
+                              0,      // long_offset
+                              4,      // long_length - we expect 4 32-bit values for _NET_FRAME_EXTENTS
+                              False,  // delete
+                              AnyPropertyType,
+                              &actual_type,
+                              &actual_format,
+                              &nitems,
+                              &bytes_remaining,
+                              &data);
+
+  if (status == Success) {
+    if ((nitems == 4) && (bytes_remaining == 0)) {
+      long *data_as_long = (long *)((void *) data);
+      left   = (int) *(data_as_long++);
+      right  = (int) *(data_as_long++);
+      top    = (int) *(data_as_long++);
+      bottom = (int) *(data_as_long++);
+      return true;
+    }
+    XFree (data);
+  }
+  return false;
+}
+
+bool WindowUtilX11::GetWindowRect(::Window window, XRectangle & rcWindow, bool bWithFrame) {
+  // reset
+  rcWindow.x = rcWindow.y = rcWindow.width =  rcWindow.height = 0;
+
+  // get window info
+  XWindowAttributes win_info;
+  if (!XGetWindowAttributes(display(), window, &win_info)) {
+    return false;
+  }
+
+  int absx,absy;
+  ::Window temp_win;
+  ::Window root_win = DefaultRootWindow(display());
+  if (!XTranslateCoordinates(display(), window, root_win, 0, 0, &absx, &absy, &temp_win)) {
+    return false;
+  }
+
+  // Adjust to limit in screen
+  XRectangle  screen_rect;
+  int nScreenCX = DisplayWidth(display(), DefaultScreen(display()));
+  int nScreenCY = DisplayHeight(display(), DefaultScreen(display()));
+  screen_rect.x = 0;
+  screen_rect.y = 0;
+  screen_rect.width = nScreenCX;
+  screen_rect.height = nScreenCY;
+
+  if (absx < 0) {
+    win_info.width += absx;
+    absx = 0;
+  } else if ((absx + win_info.width) > nScreenCX) {
+    win_info.width = nScreenCX - absx;
+  }
+  if (absy < 0) {
+    win_info.height += absy;
+    absy = 0;
+  } else if ((absy + win_info.height) > nScreenCY) {
+    win_info.height = nScreenCY - absy;
+  }
+
+  // data setting
+  rcWindow.x = absx;
+  rcWindow.y = absy;
+  rcWindow.width = win_info.width;
+  rcWindow.height = win_info.height;
+
+  if (bWithFrame) {
+    int left;
+    int right;
+    int top;
+    int bottom;
+    if (GetWindowFrameExtents(window, left, top, right, bottom)) {
+      rcWindow.x -= left;
+      rcWindow.y -= top;
+      rcWindow.width += (left + right);
+      rcWindow.height += (top + bottom);
+    }
+  }
+  return true;
+}
+
+}//namespace webrtc
new file mode 100755
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.h
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_UTIL_H_
+#define WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_UTIL_H_
+
+#include <map>
+#include <vector>
+
+#include <assert.h>
+#include <X11/Xlib.h>
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/Xutil.h>
+#include <string>
+
+#include "webrtc/system_wrappers/interface/atomic32.h"
+#include "webrtc/system_wrappers/interface/scoped_refptr.h"
+
+namespace webrtc {
+
+//===============================================================================
+// Moved common code from window_capture_x11.cc to better reuse throughout module
+
+// Convenience wrapper for XGetWindowProperty() results.
+template <class PropertyType>
+class XWindowProperty {
+public:
+  XWindowProperty(Display* display, Window window, Atom property) :
+      is_valid_(false),
+      size_(0),
+      data_(NULL) {
+    const int kBitsPerByte = 8;
+    Atom actual_type;
+    int actual_format;
+    unsigned long bytes_after;  // NOLINT: type required by XGetWindowProperty
+    int status = XGetWindowProperty(display, window, property, 0L, ~0L, False,
+                                    AnyPropertyType, &actual_type,
+                                    &actual_format, &size_,
+                                    &bytes_after, &data_);
+    if (status != Success) {
+      data_ = NULL;
+      return;
+    }
+    if (sizeof(PropertyType) * kBitsPerByte != actual_format) {
+      size_ = 0;
+      return;
+    }
+
+    is_valid_ = true;
+  }
+
+  ~XWindowProperty() {
+    if (data_) {
+      XFree(data_);
+    }
+  }
+
+  // True if we got properly value successfully.
+  bool is_valid() const { return is_valid_; }
+
+  // Size and value of the property.
+  size_t size() const { return size_; }
+  const PropertyType* data() const {
+    return reinterpret_cast<PropertyType*>(data_);
+  }
+  PropertyType* data() {
+    return reinterpret_cast<PropertyType*>(data_);
+  }
+
+private:
+  bool is_valid_;
+  unsigned long size_;  // NOLINT: type required by XGetWindowProperty
+  unsigned char* data_;
+
+  DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
+};
+
+class WindowUtilX11 {
+public:
+  WindowUtilX11(scoped_refptr<SharedXDisplay> x_display);
+  ~WindowUtilX11();
+  // Iterates through |window| hierarchy to find first visible window, i.e. one
+  // that has WM_STATE property set to NormalState.
+  // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
+  ::Window GetApplicationWindow(::Window window);
+  // Returns true if the |window| is a desktop element.
+  bool IsDesktopElement(::Window window);
+  // Returns window title for the specified X |window|.
+  bool GetWindowTitle(::Window window, std::string* title);
+  bool BringWindowToFront(::Window window);
+  int GetWindowProcessID(::Window window);
+  int32_t GetWindowStatus(::Window window);
+  bool GetWindowRect(::Window window, XRectangle &rcWindow,bool bWithFrame);
+  bool GetWindowFrameExtents(::Window window, int32_t &left, int32_t &top, int32_t &right, int32_t &bottom);
+
+protected:
+  Display* display() { return x_display_->display(); }
+
+  scoped_refptr<SharedXDisplay> x_display_;
+  Atom wm_state_atom_;
+  Atom window_type_atom_;
+  Atom normal_window_type_atom_;
+  Atom process_atom_;
+  Atom frame_extends_atom_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_UTIL_H_