Commit e27efcf3 authored by Alexis Menard's avatar Alexis Menard Committed by Commit Bot

Reland "Make Interaction Media Features MQ dynamic on Android"

This is a reland of 1bdb8833 without
changes. 

Original CL was reverted due to a bug in how chromium 
generates JNI bindings with native functions. It is fixed by 
https://codereview.chromium.org/2966163006/.

Original change's description:
> Make Interaction Media Features MQ dynamic on Android
> 
> With detachable form factors such as Asus Transformer
> it is important to make sure the interaction media
> features are updated whenever the keyboard/trackpad combo is
> detached. This will allow content author to react to
> media query changes to adapt the user interface to
> better suit the new interaction method (often touch vs
> trackpad). The patch also handles any input changes e.g.
> USB connected mouse.
> 
> The patch uses the facility landed in previous OSes and
> add a bit of Java code to listen the changes of inputs
> through the InputDeviceListener mechanism.
> 
> BUG=442418
> 
> Change-Id: I5c18ce4df8e6da927eede5a24f40aac10ecf1974
> Reviewed-on: https://chromium-review.googlesource.com/553457
> Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
> Reviewed-by: Andrew Grieve <agrieve@chromium.org>
> Reviewed-by: Bo Liu <boliu@chromium.org>
> Commit-Queue: Alexis Menard <alexis.menard@intel.com>
> Cr-Commit-Position: refs/heads/master@{#484641}


TBR=agrieve@chromium.org, alexis.menard@intel.com, boliu@chromium.org, sadrul@chromium.org

Bug: 442418
Change-Id: I5dca047c566625fa2f976d3311899f9a3a23f44e
Reviewed-on: https://chromium-review.googlesource.com/563478Reviewed-by: default avatarAlexis Menard <alexis.menard@intel.com>
Commit-Queue: Alexis Menard <alexis.menard@intel.com>
Cr-Commit-Position: refs/heads/master@{#484981}
parent 00f9d1de
......@@ -1767,6 +1767,7 @@ if (is_android) {
deps += [
"//device/gamepad",
"//device/sensors",
"//ui/events/devices",
]
}
}
......
......@@ -4,12 +4,15 @@
#include "content/browser/renderer_host/input/input_device_change_observer.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/public/common/web_preferences.h"
#if defined(OS_WIN)
#include "ui/events/devices/input_device_observer_win.h"
#elif defined(OS_LINUX)
#include "ui/events/devices/input_device_manager.h"
#elif defined(OS_ANDROID)
#include "ui/events/devices/input_device_observer_android.h"
#endif
namespace content {
......@@ -20,6 +23,8 @@ InputDeviceChangeObserver::InputDeviceChangeObserver(RenderViewHost* rvh) {
ui::InputDeviceObserverWin::GetInstance()->AddObserver(this);
#elif defined(OS_LINUX)
ui::InputDeviceManager::GetInstance()->AddObserver(this);
#elif defined(OS_ANDROID)
ui::InputDeviceObserverAndroid::GetInstance()->AddObserver(this);
#endif
}
......@@ -28,6 +33,8 @@ InputDeviceChangeObserver::~InputDeviceChangeObserver() {
ui::InputDeviceObserverWin::GetInstance()->RemoveObserver(this);
#elif defined(OS_LINUX)
ui::InputDeviceManager::GetInstance()->RemoveObserver(this);
#elif defined(OS_ANDROID)
ui::InputDeviceObserverAndroid::GetInstance()->RemoveObserver(this);
#endif
render_view_host_ = nullptr;
}
......
......@@ -4,6 +4,7 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
......@@ -25,7 +26,7 @@ class InteractionMediaQueriesDynamicTest : public ContentBrowserTest {
} // namespace
#if defined(OS_WIN) || defined(OS_LINUX)
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(InteractionMediaQueriesDynamicTest,
PointerMediaQueriesDynamic) {
GURL test_url = GetTestUrl("", "interaction-mq-dynamic.html");
......
......@@ -66,6 +66,7 @@ component("android") {
"//ui/base",
"//ui/display",
"//ui/events",
"//ui/events/devices",
"//ui/gfx",
"//ui/gfx/geometry",
"//url",
......@@ -213,6 +214,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/display/DisplaySwitches.java",
"java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java",
"java/src/org/chromium/ui/display/VirtualDisplayAndroid.java",
"java/src/org/chromium/ui/events/devices/InputDeviceObserver.java",
"java/src/org/chromium/ui/gfx/BitmapHelper.java",
"java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java",
"java/src/org/chromium/ui/gl/SurfaceTextureListener.java",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.ui.events.devices;
import android.content.Context;
import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
/**
* A singleton that helps detecting changes in input devices through the interface
* {@link InputDeviceObserver}.
*/
@JNINamespace("ui")
public class InputDeviceObserver implements InputDeviceListener {
private static final InputDeviceObserver INSTANCE = new InputDeviceObserver();
/**
* Notifies the InputDeviceObserver that an observer is attached and it
* should prepare itself for listening input changes.
*/
@CalledByNative
public static void addObserver() {
assert ThreadUtils.runningOnUiThread();
INSTANCE.attachObserver();
}
/**
* Notifies the InputDeviceObserver that an observer has been removed.
*/
@CalledByNative
public static void removeObserver() {
assert ThreadUtils.runningOnUiThread();
INSTANCE.detachObserver();
}
private InputManager mInputManager;
private InputDeviceListener mInputDeviceListener;
private int mObserversCounter;
// Override InputDeviceListener methods
@Override
public void onInputDeviceChanged(int deviceId) {
nativeInputConfigurationChanged();
}
@Override
public void onInputDeviceRemoved(int deviceId) {
nativeInputConfigurationChanged();
}
@Override
public void onInputDeviceAdded(int deviceId) {
nativeInputConfigurationChanged();
}
private void attachObserver() {
if (mObserversCounter++ == 0) {
Context context = ContextUtils.getApplicationContext();
mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
// Register an input device listener.
mInputManager.registerInputDeviceListener(this, null);
}
}
private void detachObserver() {
assert mObserversCounter > 0;
if (--mObserversCounter == 0) {
mInputManager.unregisterInputDeviceListener(this);
mInputManager = null;
}
}
private native void nativeInputConfigurationChanged();
}
\ No newline at end of file
......@@ -367,7 +367,6 @@ component("base") {
sources += [ "touch/touch_device_win.cc" ]
} else if (is_android) {
sources += [ "touch/touch_device_android.cc" ]
sources -= [ "touch/touch_device_util.cc" ]
} else if (is_ios) {
sources += [ "touch/touch_device_ios.cc" ]
} else if (is_linux) {
......
......@@ -20,7 +20,7 @@ int MaxTouchPoints() {
return Java_TouchDevice_maxTouchPoints(AttachCurrentThread());
}
std::pair<int, int> GetAvailablePointerAndHoverTypes() {
std::pair<int, int> AvailablePointerAndHoverTypes() {
JNIEnv* env = AttachCurrentThread();
std::vector<int> pointer_and_hover_types;
base::android::JavaIntArrayToIntVector(
......@@ -30,6 +30,14 @@ std::pair<int, int> GetAvailablePointerAndHoverTypes() {
return std::make_pair(pointer_and_hover_types[0], pointer_and_hover_types[1]);
}
int GetAvailableHoverTypes() {
return AvailablePointerAndHoverTypes().second;
}
int GetAvailablePointerTypes() {
return AvailablePointerAndHoverTypes().first;
}
PointerType GetPrimaryPointerType(int available_pointer_types) {
if (available_pointer_types & POINTER_TYPE_COARSE)
return POINTER_TYPE_COARSE;
......
......@@ -2,6 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
}
component("devices") {
sources = [
"device_data_manager.cc",
......@@ -15,6 +20,8 @@ component("devices") {
"input_device_event_observer.h",
"input_device_manager.cc",
"input_device_manager.h",
"input_device_observer_android.cc",
"input_device_observer_android.h",
"input_device_observer_win.cc",
"input_device_observer_win.h",
"stylus_state.h",
......@@ -35,4 +42,17 @@ component("devices") {
"//ui/display/types",
"//ui/gfx/geometry",
]
if (is_android) {
deps += [ ":ui_events_devices_jni_headers" ]
}
}
if (is_android) {
generate_jni("ui_events_devices_jni_headers") {
sources = [
"../../android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java",
]
jni_package = "events/devices"
}
}
specific_include_rules = {
"input_device_observer_android.cc": [
"+jni",
],
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/devices/input_device_observer_android.h"
#include "base/memory/singleton.h"
#include "jni/InputDeviceObserver_jni.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
// This macro provides the implementation for the observer notification methods.
#define NOTIFY_OBSERVERS(method_decl, observer_call) \
void InputDeviceObserverAndroid::method_decl { \
for (ui::InputDeviceEventObserver & observer : observers_) \
observer.observer_call; \
}
namespace ui {
bool InputDeviceObserverAndroid::RegisterInputDeviceObserver(JNIEnv* env) {
return RegisterNativesImpl(env);
}
InputDeviceObserverAndroid::InputDeviceObserverAndroid() {}
InputDeviceObserverAndroid::~InputDeviceObserverAndroid() {}
InputDeviceObserverAndroid* InputDeviceObserverAndroid::GetInstance() {
return base::Singleton<
InputDeviceObserverAndroid,
base::LeakySingletonTraits<InputDeviceObserverAndroid>>::get();
}
void InputDeviceObserverAndroid::AddObserver(
ui::InputDeviceEventObserver* observer) {
observers_.AddObserver(observer);
JNIEnv* env = AttachCurrentThread();
Java_InputDeviceObserver_addObserver(env);
}
void InputDeviceObserverAndroid::RemoveObserver(
ui::InputDeviceEventObserver* observer) {
observers_.RemoveObserver(observer);
JNIEnv* env = AttachCurrentThread();
Java_InputDeviceObserver_removeObserver(env);
}
static void InputConfigurationChanged(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
InputDeviceObserverAndroid::GetInstance()
->NotifyObserversTouchpadDeviceConfigurationChanged();
InputDeviceObserverAndroid::GetInstance()
->NotifyObserversKeyboardDeviceConfigurationChanged();
InputDeviceObserverAndroid::GetInstance()
->NotifyObserversMouseDeviceConfigurationChanged();
}
NOTIFY_OBSERVERS(NotifyObserversMouseDeviceConfigurationChanged(),
OnMouseDeviceConfigurationChanged());
NOTIFY_OBSERVERS(NotifyObserversTouchpadDeviceConfigurationChanged(),
OnTouchpadDeviceConfigurationChanged());
NOTIFY_OBSERVERS(NotifyObserversKeyboardDeviceConfigurationChanged(),
OnKeyboardDeviceConfigurationChanged());
} // namespace ui
\ No newline at end of file
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_
#define UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_
#include <jni.h>
#include "base/observer_list.h"
#include "ui/events/devices/input_device_event_observer.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
}
namespace ui {
// This class is a singleton responsible to notify the
// InputDeviceChangeObserver whenever an input change
// happened on the Java side.
class EVENTS_DEVICES_EXPORT InputDeviceObserverAndroid {
public:
static InputDeviceObserverAndroid* GetInstance();
~InputDeviceObserverAndroid();
static bool RegisterInputDeviceObserver(JNIEnv* env);
void AddObserver(ui::InputDeviceEventObserver* observer);
void RemoveObserver(ui::InputDeviceEventObserver* observer);
void NotifyObserversTouchpadDeviceConfigurationChanged();
void NotifyObserversKeyboardDeviceConfigurationChanged();
void NotifyObserversMouseDeviceConfigurationChanged();
private:
InputDeviceObserverAndroid();
base::ObserverList<ui::InputDeviceEventObserver> observers_;
friend struct base::DefaultSingletonTraits<InputDeviceObserverAndroid>;
DISALLOW_COPY_AND_ASSIGN(InputDeviceObserverAndroid);
};
} // namespace ui
#endif // UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_
#ifndef UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_
#define UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_
#include "base/observer_list.h"
#include "base/win/registry.h"
......@@ -45,4 +45,4 @@ class EVENTS_DEVICES_EXPORT InputDeviceObserverWin {
} // namespace ui
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_
\ No newline at end of file
#endif // UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment