diff --git a/webrtc/modules/desktop_capture/desktop_capture.gypi b/webrtc/modules/desktop_capture/desktop_capture.gypi index 9463257ce..9a0293512 100644 --- a/webrtc/modules/desktop_capture/desktop_capture.gypi +++ b/webrtc/modules/desktop_capture/desktop_capture.gypi @@ -71,7 +71,7 @@ "win/scoped_thread_desktop.h", "window_capturer.cc", "window_capturer.h", - "window_capturer_mac.cc", + "window_capturer_mac.mm", "window_capturer_win.cc", "window_capturer_x11.cc", "x11/shared_x_display.h", diff --git a/webrtc/modules/desktop_capture/window_capturer.h b/webrtc/modules/desktop_capture/window_capturer.h index 478c8ee99..86b3d19bf 100644 --- a/webrtc/modules/desktop_capture/window_capturer.h +++ b/webrtc/modules/desktop_capture/window_capturer.h @@ -49,6 +49,14 @@ class WindowCapturer : public DesktopCapturer { // Select window to be captured. Returns false in case of a failure (e.g. if // there is no window with the specified id). virtual bool SelectWindow(WindowId id) = 0; + + // Bring the selected window to the front. Returns false in case of a + // failure or no window selected. + // TODO(jiayl): remove the default impl when FakeWindowCapturer is updated in + // Chromium. + virtual bool BringSelectedWindowToFront() { + return true; + } }; } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/window_capturer_mac.cc b/webrtc/modules/desktop_capture/window_capturer_mac.mm old mode 100755 new mode 100644 similarity index 81% rename from webrtc/modules/desktop_capture/window_capturer_mac.cc rename to webrtc/modules/desktop_capture/window_capturer_mac.mm index 6268fc011..8fdbdc8d8 --- a/webrtc/modules/desktop_capture/window_capturer_mac.cc +++ b/webrtc/modules/desktop_capture/window_capturer_mac.mm @@ -12,6 +12,7 @@ #include #include +#include #include #include "webrtc/modules/desktop_capture/desktop_frame.h" @@ -49,6 +50,7 @@ class WindowCapturerMac : public WindowCapturer { // WindowCapturer interface. virtual bool GetWindowList(WindowList* windows) OVERRIDE; virtual bool SelectWindow(WindowId id) OVERRIDE; + virtual bool BringSelectedWindowToFront() OVERRIDE; // DesktopCapturer interface. virtual void Start(Callback* callback) OVERRIDE; @@ -133,6 +135,43 @@ bool WindowCapturerMac::SelectWindow(WindowId id) { return true; } +bool WindowCapturerMac::BringSelectedWindowToFront() { + if (!window_id_) + return false; + + CGWindowID ids[1]; + ids[0] = window_id_; + CFArrayRef window_id_array = + CFArrayCreate(NULL, reinterpret_cast(&ids), 1, NULL); + + CFArrayRef window_array = + CGWindowListCreateDescriptionFromArray(window_id_array); + if (window_array == NULL || 0 == CFArrayGetCount(window_array)) { + // Could not find the window. It might have been closed. + LOG(LS_INFO) << "Window not found"; + CFRelease(window_id_array); + return false; + } + + CFDictionaryRef window = reinterpret_cast( + CFArrayGetValueAtIndex(window_array, 0)); + CFNumberRef pid_ref = reinterpret_cast( + CFDictionaryGetValue(window, kCGWindowOwnerPID)); + + int pid; + CFNumberGetValue(pid_ref, kCFNumberIntType, &pid); + + // TODO(jiayl): this will bring the process main window to the front. We + // should find a way to bring only the window to the front. + bool result = + [[NSRunningApplication runningApplicationWithProcessIdentifier: pid] + activateWithOptions: NSApplicationActivateIgnoringOtherApps]; + + CFRelease(window_id_array); + CFRelease(window_array); + return result; +} + void WindowCapturerMac::Start(Callback* callback) { assert(!callback_); assert(callback); diff --git a/webrtc/modules/desktop_capture/window_capturer_null.cc b/webrtc/modules/desktop_capture/window_capturer_null.cc index 7bb1247ea..5f9010d2f 100755 --- a/webrtc/modules/desktop_capture/window_capturer_null.cc +++ b/webrtc/modules/desktop_capture/window_capturer_null.cc @@ -26,6 +26,7 @@ class WindowCapturerNull : public WindowCapturer { // WindowCapturer interface. virtual bool GetWindowList(WindowList* windows) OVERRIDE; virtual bool SelectWindow(WindowId id) OVERRIDE; + virtual bool BringSelectedWindowToFront() OVERRIDE; // DesktopCapturer interface. virtual void Start(Callback* callback) OVERRIDE; @@ -54,6 +55,11 @@ bool WindowCapturerNull::SelectWindow(WindowId id) { return false; } +bool WindowCapturerNull::BringSelectedWindowToFront() { + // Not implemented yet. + return false; +} + void WindowCapturerNull::Start(Callback* callback) { assert(!callback_); assert(callback); diff --git a/webrtc/modules/desktop_capture/window_capturer_win.cc b/webrtc/modules/desktop_capture/window_capturer_win.cc index 7e2859f69..97a15dd9a 100644 --- a/webrtc/modules/desktop_capture/window_capturer_win.cc +++ b/webrtc/modules/desktop_capture/window_capturer_win.cc @@ -89,6 +89,7 @@ class WindowCapturerWin : public WindowCapturer { // WindowCapturer interface. virtual bool GetWindowList(WindowList* windows) OVERRIDE; virtual bool SelectWindow(WindowId id) OVERRIDE; + virtual bool BringSelectedWindowToFront() OVERRIDE; // DesktopCapturer interface. virtual void Start(Callback* callback) OVERRIDE; @@ -157,6 +158,16 @@ bool WindowCapturerWin::SelectWindow(WindowId id) { return true; } +bool WindowCapturerWin::BringSelectedWindowToFront() { + if (!window_) + return false; + + if (!IsWindow(window_) || !IsWindowVisible(window_) || IsIconic(window_)) + return false; + + return SetForegroundWindow(window_) != 0; +} + void WindowCapturerWin::Start(Callback* callback) { assert(!callback_); assert(callback); diff --git a/webrtc/modules/desktop_capture/window_capturer_x11.cc b/webrtc/modules/desktop_capture/window_capturer_x11.cc index 473231f9c..baeb894b3 100755 --- a/webrtc/modules/desktop_capture/window_capturer_x11.cc +++ b/webrtc/modules/desktop_capture/window_capturer_x11.cc @@ -94,6 +94,7 @@ class WindowCapturerLinux : public WindowCapturer, // WindowCapturer interface. virtual bool GetWindowList(WindowList* windows) OVERRIDE; virtual bool SelectWindow(WindowId id) OVERRIDE; + virtual bool BringSelectedWindowToFront() OVERRIDE; // DesktopCapturer interface. virtual void Start(Callback* callback) OVERRIDE; @@ -220,6 +221,55 @@ bool WindowCapturerLinux::SelectWindow(WindowId id) { return true; } +bool WindowCapturerLinux::BringSelectedWindowToFront() { + if (!selected_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(), selected_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(), selected_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 = selected_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; +} + void WindowCapturerLinux::Start(Callback* callback) { assert(!callback_); assert(callback);