Fix mouse warp with 2x displays
[chromium-blink-merge.git] / remoting / host / curtain_mode_linux.cc
blob3e917b0c3573f9c3cd594dc2f820a137d7b57f86
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/curtain_mode.h"
7 #include <X11/extensions/XInput.h>
9 #include "base/callback.h"
10 #include "base/single_thread_task_runner.h"
11 #include "remoting/base/logging.h"
12 #include "remoting/host/client_session_control.h"
14 namespace remoting {
16 class CurtainModeLinux : public CurtainMode {
17 public:
18 CurtainModeLinux();
20 // Overriden from CurtainMode.
21 bool Activate() override;
23 private:
24 // Returns true if the host is running under an Xvfb session.
25 bool IsXvfbSession();
27 DISALLOW_COPY_AND_ASSIGN(CurtainModeLinux);
30 CurtainModeLinux::CurtainModeLinux() {
33 bool CurtainModeLinux::Activate() {
34 // We can't curtain the session in run-time in Linux.
35 // Either the session is running on Xvfb (i.e. always curtained), or it is
36 // attached to the physical console (i.e. impossible to curtain).
37 bool activated = IsXvfbSession();
38 if (!activated) {
39 LOG(ERROR) << "Curtain-mode is not supported when running on non-Xvfb "
40 "X server";
43 return activated;
46 bool CurtainModeLinux::IsXvfbSession() {
47 // Try to identify an Xvfb session. There's no way to query what X server we
48 // are running under, so we check for the Xvfb input devices.
49 // TODO(rmsousa): Find a similar way to determine that the *output* is secure.
50 Display* display = XOpenDisplay(nullptr);
51 int opcode, event, error;
52 if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) {
53 // If XInput is not available, assume it is not an Xvfb session.
54 LOG(ERROR) << "X Input extension not available: " << error;
55 XCloseDisplay(display);
56 return false;
58 int num_devices;
59 XDeviceInfo* devices;
60 bool found_xvfb_mouse = false;
61 bool found_xvfb_keyboard = false;
62 bool found_other_devices = false;
63 devices = XListInputDevices(display, &num_devices);
64 for (int i = 0; i < num_devices; i++) {
65 XDeviceInfo* device_info = &devices[i];
66 if (device_info->use == IsXExtensionPointer) {
67 if (strcmp(device_info->name, "Xvfb mouse") == 0) {
68 found_xvfb_mouse = true;
69 } else if (strcmp(device_info->name, "Virtual core XTEST pointer") != 0) {
70 found_other_devices = true;
71 HOST_LOG << "Non Xvfb mouse found: " << device_info->name;
73 } else if (device_info->use == IsXExtensionKeyboard) {
74 if (strcmp(device_info->name, "Xvfb keyboard") == 0) {
75 found_xvfb_keyboard = true;
76 } else if (strcmp(device_info->name,
77 "Virtual core XTEST keyboard") != 0) {
78 found_other_devices = true;
79 HOST_LOG << "Non Xvfb keyboard found: " << device_info->name;
81 } else if (device_info->use == IsXPointer) {
82 if (strcmp(device_info->name, "Virtual core pointer") != 0) {
83 found_other_devices = true;
84 HOST_LOG << "Non Xvfb mouse found: " << device_info->name;
86 } else if (device_info->use == IsXKeyboard) {
87 if (strcmp(device_info->name, "Virtual core keyboard") != 0) {
88 found_other_devices = true;
89 HOST_LOG << "Non Xvfb keyboard found: " << device_info->name;
91 } else {
92 found_other_devices = true;
93 HOST_LOG << "Non Xvfb device found: " << device_info->name;
96 XFreeDeviceList(devices);
97 XCloseDisplay(display);
98 return found_xvfb_mouse && found_xvfb_keyboard && !found_other_devices;
101 // static
102 scoped_ptr<CurtainMode> CurtainMode::Create(
103 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
104 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
105 base::WeakPtr<ClientSessionControl> client_session_control) {
106 return make_scoped_ptr(new CurtainModeLinux());
109 } // namespace remoting