mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
Bug 1035774 - Support dynamic input device changes for Android. r=jchen
Though we can't write automation tests for this, I have confirmed that the input device added/removed are properly notified to 'browser.xul'. Unfortunately the notifications don't reach to conent documents because of bug 1478212, but I've also confirmed they did reach to content documents with replacing MediaFeatureValuesChanged with MediaFeatureValuesChangedAllDocuments in nsPresContext::RefreshSystemMetrics(). Differential Revision: https://phabricator.services.mozilla.com/D3303
This commit is contained in:
parent
2b678040eb
commit
b2160ed2cf
@ -32,6 +32,7 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.BitmapUtils;
|
||||
import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.InputDeviceUtils;
|
||||
import org.mozilla.gecko.util.IOUtils;
|
||||
import org.mozilla.gecko.util.ProxySelector;
|
||||
import org.mozilla.gecko.util.StrictModeContext;
|
||||
@ -1879,14 +1880,6 @@ public class GeckoAppShell
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isPointerTypeDevice(InputDevice inputDevice) {
|
||||
int sources = inputDevice.getSources();
|
||||
return (sources & (InputDevice.SOURCE_CLASS_JOYSTICK |
|
||||
InputDevice.SOURCE_CLASS_POINTER |
|
||||
InputDevice.SOURCE_CLASS_POSITION |
|
||||
InputDevice.SOURCE_CLASS_TRACKBALL)) != 0;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
// For any-pointer and any-hover media queries features.
|
||||
private static int getAllPointerCapabilities() {
|
||||
@ -1895,7 +1888,7 @@ public class GeckoAppShell
|
||||
for (int deviceId : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDevice = InputDevice.getDevice(deviceId);
|
||||
if (inputDevice == null ||
|
||||
!isPointerTypeDevice(inputDevice)) {
|
||||
!InputDeviceUtils.isPointerTypeDevice(inputDevice)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1913,7 +1906,7 @@ public class GeckoAppShell
|
||||
for (int deviceId : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDevice = InputDevice.getDevice(deviceId);
|
||||
if (inputDevice == null ||
|
||||
!isPointerTypeDevice(inputDevice)) {
|
||||
!InputDeviceUtils.isPointerTypeDevice(inputDevice)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.InputDeviceUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
public class GeckoInputDeviceListener
|
||||
implements InputManager.InputDeviceListener {
|
||||
private static final String LOGTAG = "GeckoInputDeviceListener";
|
||||
|
||||
private static final GeckoInputDeviceListener listenerInstance = new GeckoInputDeviceListener();
|
||||
|
||||
private boolean initialized;
|
||||
private InputManager mInputManager;
|
||||
|
||||
public static GeckoInputDeviceListener getInstance() {
|
||||
return listenerInstance;
|
||||
}
|
||||
|
||||
private GeckoInputDeviceListener() {
|
||||
}
|
||||
|
||||
public synchronized void initialize(final Context context) {
|
||||
if (initialized) {
|
||||
Log.w(LOGTAG, "Already initialized!");
|
||||
return;
|
||||
}
|
||||
mInputManager = (InputManager)
|
||||
context.getSystemService(Context.INPUT_SERVICE);
|
||||
mInputManager.registerInputDeviceListener(listenerInstance, ThreadUtils.getUiHandler());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public synchronized void shutdown() {
|
||||
if (!initialized) {
|
||||
Log.w(LOGTAG, "Already shut down!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mInputManager != null) {
|
||||
Log.e(LOGTAG, "mInputManager should be valid!");
|
||||
return;
|
||||
}
|
||||
|
||||
mInputManager.unregisterInputDeviceListener(listenerInstance);
|
||||
initialized = false;
|
||||
mInputManager = null;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
|
||||
private static native void onDeviceChanged();
|
||||
|
||||
private void notifyDeviceChanged(int deviceId) {
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
if (device == null ||
|
||||
!InputDeviceUtils.isPointerTypeDevice(device)) {
|
||||
return;
|
||||
}
|
||||
onDeviceChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
notifyDeviceChanged(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
// Call onDeviceChanged directly without checking device source types
|
||||
// since we can no longer get a valid `InputDevice` in the case of
|
||||
// device removal.
|
||||
onDeviceChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
notifyDeviceChanged(deviceId);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import android.view.InputDevice;
|
||||
|
||||
public class InputDeviceUtils {
|
||||
public static boolean isPointerTypeDevice(InputDevice inputDevice) {
|
||||
int sources = inputDevice.getSources();
|
||||
return (sources & (InputDevice.SOURCE_CLASS_JOYSTICK |
|
||||
InputDevice.SOURCE_CLASS_POINTER |
|
||||
InputDevice.SOURCE_CLASS_POSITION |
|
||||
InputDevice.SOURCE_CLASS_TRACKBALL)) != 0;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoInputDeviceListener;
|
||||
import org.mozilla.gecko.GeckoScreenOrientation;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
@ -223,6 +224,8 @@ public final class GeckoRuntime implements Parcelable {
|
||||
|
||||
// Initialize the system ClipboardManager by accessing it on the main thread.
|
||||
GeckoAppShell.getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
||||
GeckoInputDeviceListener.getInstance().initialize(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -278,6 +281,7 @@ public final class GeckoRuntime implements Parcelable {
|
||||
Log.d(LOGTAG, "shutdown");
|
||||
}
|
||||
|
||||
GeckoInputDeviceListener.getInstance().shutdown();
|
||||
GeckoThread.forceQuit();
|
||||
}
|
||||
|
||||
|
61
widget/android/GeckoInputDeviceListener.h
Normal file
61
widget/android/GeckoInputDeviceListener.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 GeckoInputDeviceListener_h
|
||||
#define GeckoInputDeviceListener_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GeckoInputDeviceListener final
|
||||
: public java::GeckoInputDeviceListener::Natives<GeckoInputDeviceListener>
|
||||
{
|
||||
GeckoInputDeviceListener() = delete;
|
||||
|
||||
public:
|
||||
static void
|
||||
OnDeviceChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Iterate all toplevel windows
|
||||
nsCOMPtr<nsIWindowMediator> windowMediator =
|
||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
|
||||
NS_ENSURE_TRUE_VOID(windowMediator);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
|
||||
windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
|
||||
NS_ENSURE_TRUE_VOID(windowEnumerator);
|
||||
|
||||
bool more;
|
||||
while (NS_SUCCEEDED(windowEnumerator->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsISupports> elements;
|
||||
if (NS_FAILED(windowEnumerator->GetNext(getter_AddRefs(elements)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(elements)) {
|
||||
if (window->Closed()) {
|
||||
continue;
|
||||
}
|
||||
if (nsIDocument* doc = window->GetExtantDoc()) {
|
||||
if (nsIPresShell* presShell = doc->GetShell()) {
|
||||
presShell->ThemeChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GeckoInputDeviceListener_h
|
@ -64,6 +64,7 @@
|
||||
#include "GeckoNetworkManager.h"
|
||||
#include "GeckoProcessManager.h"
|
||||
#include "GeckoScreenOrientation.h"
|
||||
#include "GeckoInputDeviceListener.h"
|
||||
#include "GeckoVRManager.h"
|
||||
#include "PrefsHelper.h"
|
||||
#include "fennec/MemoryMonitor.h"
|
||||
@ -427,6 +428,7 @@ nsAppShell::nsAppShell()
|
||||
GeckoAppShellSupport::Init();
|
||||
GeckoThreadSupport::Init();
|
||||
mozilla::GeckoBatteryManager::Init();
|
||||
mozilla::GeckoInputDeviceListener::Init();
|
||||
mozilla::GeckoNetworkManager::Init();
|
||||
mozilla::GeckoProcessManager::Init();
|
||||
mozilla::GeckoScreenOrientation::Init();
|
||||
|
Loading…
Reference in New Issue
Block a user