Adds a method to WindowCapturer to bring a window to the front.

BUG=3071
R=sergeyu@chromium.org

Review URL: https://webrtc-codereview.appspot.com/10079004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5718 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
jiayl@webrtc.org 2014-03-18 17:10:36 +00:00
parent e9793ab8b8
commit 886c94f07c
6 changed files with 115 additions and 1 deletions

View File

@ -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",

View File

@ -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

View File

@ -12,6 +12,7 @@
#include <assert.h>
#include <ApplicationServices/ApplicationServices.h>
#include <Cocoa/Cocoa.h>
#include <CoreFoundation/CoreFoundation.h>
#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<const void **>(&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<CFDictionaryRef>(
CFArrayGetValueAtIndex(window_array, 0));
CFNumberRef pid_ref = reinterpret_cast<CFNumberRef>(
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);

View File

@ -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);

View File

@ -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);

View File

@ -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);