mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and fx-team
This commit is contained in:
commit
95ac4ccc34
@ -4,6 +4,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
requestLongerTimeout(2);
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -60,7 +60,7 @@ AppValidator.prototype._fetchManifest = function (manifestURL) {
|
|||||||
try {
|
try {
|
||||||
manifest = JSON.parse(req.responseText);
|
manifest = JSON.parse(req.responseText);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.error(strings.formatStringFromName("validator.invalidManifestJSON", [manifestURL, e], 2));
|
this.error(strings.formatStringFromName("validator.invalidManifestJSON", [e, manifestURL], 2));
|
||||||
}
|
}
|
||||||
deferred.resolve(manifest);
|
deferred.resolve(manifest);
|
||||||
}).bind(this);
|
}).bind(this);
|
||||||
@ -109,7 +109,7 @@ AppValidator.prototype.validateManifest = function (manifest) {
|
|||||||
if (!manifest.icons || Object.keys(manifest.icons).length == 0) {
|
if (!manifest.icons || Object.keys(manifest.icons).length == 0) {
|
||||||
this.warning(strings.GetStringFromName("validator.missIconsManifestProperty"));
|
this.warning(strings.GetStringFromName("validator.missIconsManifestProperty"));
|
||||||
} else if (!manifest.icons["128"]) {
|
} else if (!manifest.icons["128"]) {
|
||||||
this.warning(strings.GetStringFromName("validator.missIconForMarketplace"));
|
this.warning(strings.GetStringFromName("validator.missIconMarketplace"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,22 +2,32 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (device.deviceSize): %1$S is the device's width, %2$S is
|
||||||
|
# the device's height, %3$S is the device's pixel density.
|
||||||
|
# Example: 800x480 (86 DPI).
|
||||||
device.deviceSize=Device size: %1$Sx%2$S (%3$S DPI)
|
device.deviceSize=Device size: %1$Sx%2$S (%3$S DPI)
|
||||||
|
# LOCALIZATION NOTE (connection.connectedToDevice, connection.connectTo):
|
||||||
|
# %1$S is the host name, %2$S is the port number.
|
||||||
connection.connectedToDevice=Connected to %1$S
|
connection.connectedToDevice=Connected to %1$S
|
||||||
connection.connectTo=Connect to %1$S:%2$S
|
connection.connectTo=Connect to %1$S:%2$S
|
||||||
project.filePickerTitle=Select a webapp folder
|
project.filePickerTitle=Select a webapp folder
|
||||||
|
|
||||||
validator.nonExistingFolder=The project folder doesn't exists
|
validator.nonExistingFolder=The project folder doesn't exists
|
||||||
validator.expectProjectFolder=The project folder ends up being a file
|
validator.expectProjectFolder=The project folder ends up being a file
|
||||||
validator.wrongManifestFileName=Packaged apps require a manifest file that can only be named 'manifest.webapp' at project root folder
|
validator.wrongManifestFileName=Packaged apps require a manifest file that can only be named 'manifest.webapp' at project root folder
|
||||||
validator.invalidManifestURL=Invalid manifest URL '%S'
|
validator.invalidManifestURL=Invalid manifest URL '%S'
|
||||||
|
# LOCALIZATION NOTE (validator.invalidManifestJSON, validator.noAccessManifestURL):
|
||||||
|
# %1$S is the error message, %2$S is the URI of the manifest.
|
||||||
validator.invalidManifestJSON=The webapp manifest isn't a valid JSON file: %1$S at: %2$S
|
validator.invalidManifestJSON=The webapp manifest isn't a valid JSON file: %1$S at: %2$S
|
||||||
validator.noAccessManifestURL=Unable to read manifest file: %1$S at: %2$S
|
validator.noAccessManifestURL=Unable to read manifest file: %1$S at: %2$S
|
||||||
|
# LOCALIZATION NOTE (validator.invalidHostedManifestURL): %1$S is the URI of
|
||||||
|
# the manifest, %2$S is the error message.
|
||||||
validator.invalidHostedManifestURL=Invalid hosted manifest URL '%1$S': %2$S
|
validator.invalidHostedManifestURL=Invalid hosted manifest URL '%1$S': %2$S
|
||||||
validator.invalidProjectType=Unknown project type '%S'
|
validator.invalidProjectType=Unknown project type '%S'
|
||||||
|
# LOCALIZATION NOTE (validator.missNameManifestProperty, validator.missIconsManifestProperty):
|
||||||
|
# don't translate 'icons' and 'name'.
|
||||||
validator.missNameManifestProperty=Missing mandatory 'name' in Manifest.
|
validator.missNameManifestProperty=Missing mandatory 'name' in Manifest.
|
||||||
validator.missIconsManifestProperty=Missing 'icons' in Manifest.
|
validator.missIconsManifestProperty=Missing 'icons' in Manifest.
|
||||||
validator.missIconForMarketplace=app submission to the Marketplace needs at least an 128 icon
|
validator.missIconMarketplace=app submission to the Marketplace needs at least a 128px icon
|
||||||
validator.invalidAppType=Unknown app type: '%S'.
|
validator.invalidAppType=Unknown app type: '%S'.
|
||||||
validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
|
validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
|
||||||
validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
|
validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
|
||||||
|
@ -649,37 +649,41 @@ function test_info() {
|
|||||||
|
|
||||||
let stop = new Date();
|
let stop = new Date();
|
||||||
|
|
||||||
// We round down/up by 1s as file system precision is lower than Date precision
|
// We round down/up by 1s as file system precision is lower than
|
||||||
// (no clear specifications about that, but it seems that this can be a little
|
// Date precision (no clear specifications about that, but it seems
|
||||||
// over 1 second under ext3 and 2 seconds under FAT)
|
// that this can be a little over 1 second under ext3 and 2 seconds
|
||||||
let startMs = start.getTime() - 2500;
|
// under FAT).
|
||||||
let stopMs = stop.getTime() + 2500;
|
let SLOPPY_FILE_SYSTEM_ADJUSTMENT = 3000;
|
||||||
|
let startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT;
|
||||||
|
let stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT;
|
||||||
|
info("Testing stat with bounds [ " + startMs + ", " + stopMs +" ]");
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
let birth;
|
let birth;
|
||||||
if ("winBirthDate" in info) {
|
if ("winBirthDate" in stat) {
|
||||||
birth = info.winBirthDate;
|
birth = stat.winBirthDate;
|
||||||
} else if ("macBirthDate" in info) {
|
} else if ("macBirthDate" in stat) {
|
||||||
birth = info.macBirthDate;
|
birth = stat.macBirthDate;
|
||||||
} else {
|
} else {
|
||||||
ok(true, "Skipping birthdate test");
|
ok(true, "Skipping birthdate test");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ok(birth.getTime() <= stopMs,
|
ok(birth.getTime() <= stopMs,
|
||||||
"test_info: file was created before now - " + stop + ", " + birth);
|
"test_info: platformBirthDate is consistent");
|
||||||
// Note: Previous versions of this test checked whether the file has
|
// Note: Previous versions of this test checked whether the file
|
||||||
// been created after the start of the test. Unfortunately, this sometimes
|
// has been created after the start of the test. Unfortunately,
|
||||||
// failed under Windows, in specific circumstances: if the file has been
|
// this sometimes failed under Windows, in specific circumstances:
|
||||||
// removed at the start of the test and recreated immediately, the Windows
|
// if the file has been removed at the start of the test and
|
||||||
// file system detects this and decides that the file was actually truncated
|
// recreated immediately, the Windows file system detects this and
|
||||||
// rather than recreated, hence that it should keep its previous creation date.
|
// decides that the file was actually truncated rather than
|
||||||
// Debugging hilarity ensues.
|
// recreated, hence that it should keep its previous creation
|
||||||
|
// date. Debugging hilarity ensues.
|
||||||
});
|
});
|
||||||
|
|
||||||
let change = stat.lastModificationDate;
|
let change = stat.lastModificationDate;
|
||||||
ok(change.getTime() >= startMs
|
info("Testing lastModificationDate: " + change);
|
||||||
&& change.getTime() <= stopMs,
|
ok(change.getTime() >= startMs && change.getTime() <= stopMs,
|
||||||
"test_info: file has changed between the start of the test and now - " + start + ", " + stop + ", " + change);
|
"test_info: lastModificationDate is consistent");
|
||||||
|
|
||||||
// Test OS.File.prototype.stat on new file
|
// Test OS.File.prototype.stat on new file
|
||||||
file = OS.File.open(filename);
|
file = OS.File.open(filename);
|
||||||
@ -696,23 +700,20 @@ function test_info() {
|
|||||||
|
|
||||||
stop = new Date();
|
stop = new Date();
|
||||||
|
|
||||||
// We round down/up by 1s as file system precision is lower than Date precision
|
// Round up/down as above
|
||||||
startMs = start.getTime() - 1000;
|
startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT;
|
||||||
stopMs = stop.getTime() + 1000;
|
stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT;
|
||||||
|
info("Testing stat 2 with bounds [ " + startMs + ", " + stopMs +" ]");
|
||||||
let birth = stat.creationDate;
|
|
||||||
ok(birth.getTime() <= stopMs,
|
|
||||||
"test_info: file 2 was created between the start of the test and now - " + start + ", " + stop + ", " + birth);
|
|
||||||
|
|
||||||
let access = stat.lastAccessDate;
|
let access = stat.lastAccessDate;
|
||||||
ok(access.getTime() >= startMs
|
info("Testing lastAccessDate: " + access);
|
||||||
&& access.getTime() <= stopMs,
|
ok(access.getTime() >= startMs && access.getTime() <= stopMs,
|
||||||
"test_info: file 2 was accessed between the start of the test and now - " + start + ", " + stop + ", " + access);
|
"test_info: lastAccessDate is consistent");
|
||||||
|
|
||||||
change = stat.lastModificationDate;
|
change = stat.lastModificationDate;
|
||||||
ok(change.getTime() >= startMs
|
info("Testing lastModificationDate 2: " + change);
|
||||||
&& change.getTime() <= stopMs,
|
ok(change.getTime() >= startMs && change.getTime() <= stopMs,
|
||||||
"test_info: file 2 has changed between the start of the test and now - " + start + ", " + stop + ", " + change);
|
"test_info: lastModificationDate 2 is consistent");
|
||||||
|
|
||||||
// Test OS.File.stat on directory
|
// Test OS.File.stat on directory
|
||||||
stat = OS.File.stat(OS.File.getCurrentDirectory());
|
stat = OS.File.stat(OS.File.getCurrentDirectory());
|
||||||
|
@ -114,6 +114,10 @@ const N_STATUS = Name("status");
|
|||||||
const N_VALUE = Name("value");
|
const N_VALUE = Name("value");
|
||||||
const N_HANDLERS = Name("handlers");
|
const N_HANDLERS = Name("handlers");
|
||||||
|
|
||||||
|
// The following error types are considered programmer errors, which should be
|
||||||
|
// reported (possibly redundantly) so as to let programmers fix their code.
|
||||||
|
const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//// Promise
|
//// Promise
|
||||||
|
|
||||||
@ -572,7 +576,27 @@ Handler.prototype = {
|
|||||||
nextStatus = STATUS_RESOLVED;
|
nextStatus = STATUS_RESOLVED;
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// If an exception occurred in the handler, reject the next promise.
|
|
||||||
|
// An exception has occurred in the handler.
|
||||||
|
|
||||||
|
if (ex && typeof ex == "object" && "name" in ex &&
|
||||||
|
ERRORS_TO_REPORT.indexOf(ex.name) != -1) {
|
||||||
|
|
||||||
|
// We suspect that the exception is a programmer error, so we now
|
||||||
|
// display it using dump(). Note that we do not use Cu.reportError as
|
||||||
|
// we assume that this is a programming error, so we do not want end
|
||||||
|
// users to see it. Also, if the programmer handles errors correctly,
|
||||||
|
// they will either treat the error or log them somewhere.
|
||||||
|
|
||||||
|
dump("A coding exception was thrown in a Promise " +
|
||||||
|
((nextStatus == STATUS_RESOLVED) ? "resolution":"rejection") +
|
||||||
|
" callback.\n");
|
||||||
|
dump("Full message: " + ex + "\n");
|
||||||
|
dump("See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise\n");
|
||||||
|
dump("Full stack: " + (("stack" in ex)?ex.stack:"not available") + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additionally, reject the next promise.
|
||||||
nextStatus = STATUS_REJECTED;
|
nextStatus = STATUS_REJECTED;
|
||||||
nextValue = ex;
|
nextValue = ex;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,10 @@ const Cr = Components.results;
|
|||||||
|
|
||||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||||
|
|
||||||
|
// The following error types are considered programmer errors, which should be
|
||||||
|
// reported (possibly redundantly) so as to let programmers fix their code.
|
||||||
|
const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//// Task
|
//// Task
|
||||||
|
|
||||||
@ -226,6 +230,21 @@ TaskImpl.prototype = {
|
|||||||
this.deferred.resolve();
|
this.deferred.resolve();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// The generator function failed with an uncaught exception.
|
// The generator function failed with an uncaught exception.
|
||||||
|
|
||||||
|
if (ex && typeof ex == "object" && "name" in ex &&
|
||||||
|
ERRORS_TO_REPORT.indexOf(ex.name) != -1) {
|
||||||
|
|
||||||
|
// We suspect that the exception is a programmer error, so we now
|
||||||
|
// display it using dump(). Note that we do not use Cu.reportError as
|
||||||
|
// we assume that this is a programming error, so we do not want end
|
||||||
|
// users to see it. Also, if the programmer handles errors correctly,
|
||||||
|
// they will either treat the error or log them somewhere.
|
||||||
|
|
||||||
|
dump("A coding exception was thrown and uncaught in a Task.\n");
|
||||||
|
dump("Full message: " + ex + "\n");
|
||||||
|
dump("Full stack: " + (("stack" in ex)?ex.stack:"not available") + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
this.deferred.reject(ex);
|
this.deferred.reject(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1152,7 +1152,8 @@ public:
|
|||||||
keyCode(0), charCode(0),
|
keyCode(0), charCode(0),
|
||||||
location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), isChar(0),
|
location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), isChar(0),
|
||||||
mKeyNameIndex(mozilla::widget::KEY_NAME_INDEX_Unidentified),
|
mKeyNameIndex(mozilla::widget::KEY_NAME_INDEX_Unidentified),
|
||||||
mNativeKeyEvent(nullptr)
|
mNativeKeyEvent(nullptr),
|
||||||
|
mUniqueId(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,6 +1172,11 @@ public:
|
|||||||
mozilla::widget::KeyNameIndex mKeyNameIndex;
|
mozilla::widget::KeyNameIndex mKeyNameIndex;
|
||||||
// OS-specific native event can optionally be preserved
|
// OS-specific native event can optionally be preserved
|
||||||
void* mNativeKeyEvent;
|
void* mNativeKeyEvent;
|
||||||
|
// Unique id associated with a keydown / keypress event. Used in identifing
|
||||||
|
// keypress events for removal from async event dispatch queue in metrofx
|
||||||
|
// after preventDefault is called on keydown events. It's ok if this wraps
|
||||||
|
// over long periods.
|
||||||
|
uint32_t mUniqueId;
|
||||||
|
|
||||||
void GetDOMKeyName(nsAString& aKeyName)
|
void GetDOMKeyName(nsAString& aKeyName)
|
||||||
{
|
{
|
||||||
@ -1205,6 +1211,7 @@ public:
|
|||||||
// Don't copy mNativeKeyEvent because it may be referred after its instance
|
// Don't copy mNativeKeyEvent because it may be referred after its instance
|
||||||
// is destroyed.
|
// is destroyed.
|
||||||
mNativeKeyEvent = nullptr;
|
mNativeKeyEvent = nullptr;
|
||||||
|
mUniqueId = aEvent.mUniqueId;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ struct ParamTraits<nsKeyEvent>
|
|||||||
WriteParam(aMsg, aParam.charCode);
|
WriteParam(aMsg, aParam.charCode);
|
||||||
WriteParam(aMsg, aParam.isChar);
|
WriteParam(aMsg, aParam.isChar);
|
||||||
WriteParam(aMsg, aParam.location);
|
WriteParam(aMsg, aParam.location);
|
||||||
|
WriteParam(aMsg, aParam.mUniqueId);
|
||||||
// An OS-specific native event might be attached in |mNativeKeyEvent|, but
|
// An OS-specific native event might be attached in |mNativeKeyEvent|, but
|
||||||
// that cannot be copied across process boundaries.
|
// that cannot be copied across process boundaries.
|
||||||
}
|
}
|
||||||
@ -273,7 +274,8 @@ struct ParamTraits<nsKeyEvent>
|
|||||||
ReadParam(aMsg, aIter, &aResult->keyCode) &&
|
ReadParam(aMsg, aIter, &aResult->keyCode) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->charCode) &&
|
ReadParam(aMsg, aIter, &aResult->charCode) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->isChar) &&
|
ReadParam(aMsg, aIter, &aResult->isChar) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->location))
|
ReadParam(aMsg, aIter, &aResult->location) &&
|
||||||
|
ReadParam(aMsg, aIter, &aResult->mUniqueId))
|
||||||
{
|
{
|
||||||
aResult->mKeyNameIndex = static_cast<mozilla::widget::KeyNameIndex>(keyNameIndex);
|
aResult->mKeyNameIndex = static_cast<mozilla::widget::KeyNameIndex>(keyNameIndex);
|
||||||
aResult->mNativeKeyEvent = NULL;
|
aResult->mNativeKeyEvent = NULL;
|
||||||
|
@ -41,6 +41,11 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace widget {
|
namespace widget {
|
||||||
|
|
||||||
|
// Unique id counter associated with a keydown / keypress events. Used in
|
||||||
|
// identifing keypress events for removal from async event dispatch queue
|
||||||
|
// in metrofx after preventDefault is called on keydown events.
|
||||||
|
static uint32_t sUniqueKeyEventId = 0;
|
||||||
|
|
||||||
struct DeadKeyEntry
|
struct DeadKeyEntry
|
||||||
{
|
{
|
||||||
PRUnichar BaseChar;
|
PRUnichar BaseChar;
|
||||||
@ -756,6 +761,9 @@ NativeKey::InitKeyEvent(nsKeyEvent& aKeyEvent,
|
|||||||
switch (aKeyEvent.message) {
|
switch (aKeyEvent.message) {
|
||||||
case NS_KEY_DOWN:
|
case NS_KEY_DOWN:
|
||||||
aKeyEvent.keyCode = mDOMKeyCode;
|
aKeyEvent.keyCode = mDOMKeyCode;
|
||||||
|
// Unique id for this keydown event and its associated keypress.
|
||||||
|
sUniqueKeyEventId++;
|
||||||
|
aKeyEvent.mUniqueId = sUniqueKeyEventId;
|
||||||
break;
|
break;
|
||||||
case NS_KEY_UP:
|
case NS_KEY_UP:
|
||||||
aKeyEvent.keyCode = mDOMKeyCode;
|
aKeyEvent.keyCode = mDOMKeyCode;
|
||||||
@ -768,6 +776,7 @@ NativeKey::InitKeyEvent(nsKeyEvent& aKeyEvent,
|
|||||||
(mOriginalVirtualKeyCode == VK_MENU && mMsg.message != WM_SYSKEYUP);
|
(mOriginalVirtualKeyCode == VK_MENU && mMsg.message != WM_SYSKEYUP);
|
||||||
break;
|
break;
|
||||||
case NS_KEY_PRESS:
|
case NS_KEY_PRESS:
|
||||||
|
aKeyEvent.mUniqueId = sUniqueKeyEventId;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Invalid event message");
|
MOZ_CRASH("Invalid event message");
|
||||||
@ -797,7 +806,7 @@ NativeKey::DispatchKeyEvent(nsKeyEvent& aKeyEvent,
|
|||||||
aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent);
|
aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (mWidget->DispatchWindowEvent(&aKeyEvent) || mWidget->Destroyed());
|
return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -147,6 +147,27 @@ MouseScrollHandler::~MouseScrollHandler()
|
|||||||
delete mSynthesizingEvent;
|
delete mSynthesizingEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
MouseScrollHandler::NeedsMessage(UINT aMsg)
|
||||||
|
{
|
||||||
|
switch (aMsg) {
|
||||||
|
case WM_SETTINGCHANGE:
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
case WM_HSCROLL:
|
||||||
|
case WM_VSCROLL:
|
||||||
|
case MOZ_WM_MOUSEVWHEEL:
|
||||||
|
case MOZ_WM_MOUSEHWHEEL:
|
||||||
|
case MOZ_WM_HSCROLL:
|
||||||
|
case MOZ_WM_VSCROLL:
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool
|
bool
|
||||||
MouseScrollHandler::ProcessMessage(nsWindowBase* aWidget, UINT msg,
|
MouseScrollHandler::ProcessMessage(nsWindowBase* aWidget, UINT msg,
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
static void Initialize();
|
static void Initialize();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
|
static bool NeedsMessage(UINT aMsg);
|
||||||
static bool ProcessMessage(nsWindowBase* aWidget,
|
static bool ProcessMessage(nsWindowBase* aWidget,
|
||||||
UINT msg,
|
UINT msg,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
|
@ -34,6 +34,24 @@ struct KeyPair;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace widget {
|
namespace widget {
|
||||||
|
|
||||||
|
// More complete QS definitions for MsgWaitForMultipleObjects() and
|
||||||
|
// GetQueueStatus() that include newer win8 specific defines.
|
||||||
|
|
||||||
|
#ifndef QS_RAWINPUT
|
||||||
|
#define QS_RAWINPUT 0x0400
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef QS_TOUCH
|
||||||
|
#define QS_TOUCH 0x0800
|
||||||
|
#define QS_POINTER 0x1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MOZ_QS_ALLEVENT (QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON | \
|
||||||
|
QS_POSTMESSAGE | QS_TIMER | QS_PAINT | \
|
||||||
|
QS_SENDMESSAGE | QS_HOTKEY | \
|
||||||
|
QS_ALLPOSTMESSAGE | QS_RAWINPUT | \
|
||||||
|
QS_TOUCH | QS_POINTER)
|
||||||
|
|
||||||
class myDownloadObserver MOZ_FINAL : public nsIDownloadObserver
|
class myDownloadObserver MOZ_FINAL : public nsIDownloadObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -3662,6 +3662,13 @@ bool nsWindow::DispatchStandardEvent(uint32_t aMsg)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsWindow::DispatchKeyboardEvent(nsGUIEvent* event)
|
||||||
|
{
|
||||||
|
nsEventStatus status;
|
||||||
|
DispatchEvent(event, status);
|
||||||
|
return ConvertStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
bool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
|
bool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
|
||||||
{
|
{
|
||||||
nsEventStatus status;
|
nsEventStatus status;
|
||||||
|
@ -87,6 +87,7 @@ public:
|
|||||||
// nsWindowBase
|
// nsWindowBase
|
||||||
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE;
|
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE;
|
||||||
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||||
|
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||||
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE;
|
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE;
|
||||||
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return mIsTopWidgetWindow; }
|
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return mIsTopWidgetWindow; }
|
||||||
|
|
||||||
|
@ -49,9 +49,16 @@ public:
|
|||||||
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) = 0;
|
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispatch a plugin event with the message.
|
* Dispatch a gecko keyboard event for this widget. This
|
||||||
|
* is called by KeyboardLayout to dispatch gecko events.
|
||||||
|
* Returns true if it's consumed. Otherwise, false.
|
||||||
*/
|
*/
|
||||||
virtual bool DispatchPluginEvent(const MSG &aMsg) MOZ_FINAL
|
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default dispatch of a plugin event.
|
||||||
|
*/
|
||||||
|
virtual bool DispatchPluginEvent(const MSG &aMsg)
|
||||||
{
|
{
|
||||||
if (!PluginHasFocus()) {
|
if (!PluginHasFocus()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -32,12 +32,6 @@ using namespace ABI::Windows::Foundation;
|
|||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
using namespace Microsoft::WRL::Wrappers;
|
using namespace Microsoft::WRL::Wrappers;
|
||||||
|
|
||||||
/*
|
|
||||||
* Due to issues on older platforms with linking the winrt runtime lib we
|
|
||||||
* can't have ref new winrt variables in the global scope. Everything should
|
|
||||||
* be encapsulated in a class. See toolkit/library/nsDllMain for the details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace widget {
|
namespace widget {
|
||||||
namespace winrt {
|
namespace winrt {
|
||||||
@ -57,7 +51,6 @@ FrameworkView::FrameworkView(MetroApp* aMetroApp) :
|
|||||||
mWinVisible(false),
|
mWinVisible(false),
|
||||||
mWinActiveState(false)
|
mWinActiveState(false)
|
||||||
{
|
{
|
||||||
mPainting = false;
|
|
||||||
memset(&sKeyboardRect, 0, sizeof(Rect));
|
memset(&sKeyboardRect, 0, sizeof(Rect));
|
||||||
sSettingsArray = new nsTArray<nsString>();
|
sSettingsArray = new nsTArray<nsString>();
|
||||||
LogFunction();
|
LogFunction();
|
||||||
@ -84,27 +77,6 @@ FrameworkView::Initialize(ICoreApplicationView* aAppView)
|
|||||||
HRESULT
|
HRESULT
|
||||||
FrameworkView::Uninitialize()
|
FrameworkView::Uninitialize()
|
||||||
{
|
{
|
||||||
LogFunction();
|
|
||||||
mShuttingDown = true;
|
|
||||||
|
|
||||||
if (mAutomationProvider) {
|
|
||||||
ComPtr<IUIABridge> provider;
|
|
||||||
mAutomationProvider.As(&provider);
|
|
||||||
if (provider) {
|
|
||||||
provider->Disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mAutomationProvider = nullptr;
|
|
||||||
|
|
||||||
mMetroInput = nullptr;
|
|
||||||
mD2DWindowSurface = nullptr;
|
|
||||||
delete sSettingsArray;
|
|
||||||
sSettingsArray = nullptr;
|
|
||||||
mWidget = nullptr;
|
|
||||||
mMetroApp = nullptr;
|
|
||||||
mDispatcher = nullptr;
|
|
||||||
mWindow = nullptr;
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,34 +86,41 @@ FrameworkView::Load(HSTRING aEntryPoint)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called by winrt on startup
|
||||||
HRESULT
|
HRESULT
|
||||||
FrameworkView::Run()
|
FrameworkView::Run()
|
||||||
{
|
{
|
||||||
LogFunction();
|
LogFunction();
|
||||||
|
|
||||||
// XPCOM is initialized here. mWidget is also created.
|
// Initialize XPCOM, create mWidget and go! We get a
|
||||||
mMetroApp->Initialize();
|
// callback in MetroAppShell::Run, in which we kick
|
||||||
|
// off normal browser execution / event dispatching.
|
||||||
|
mMetroApp->Run();
|
||||||
|
|
||||||
ProcessLaunchArguments();
|
// Gecko is completely shut down at this point.
|
||||||
|
Log("Exiting FrameworkView::Run()");
|
||||||
|
|
||||||
// Activate the window
|
return S_OK;
|
||||||
mWindow->Activate();
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
FrameworkView::ActivateView()
|
||||||
|
{
|
||||||
|
LogFunction();
|
||||||
|
|
||||||
UpdateWidgetSizeAndPosition();
|
UpdateWidgetSizeAndPosition();
|
||||||
|
|
||||||
MetroUtils::GetViewState(mViewState);
|
MetroUtils::GetViewState(mViewState);
|
||||||
|
|
||||||
// Get the metro event dispatcher
|
nsIntRegion region(nsIntRect(0, 0, mWindowBounds.width, mWindowBounds.height));
|
||||||
HRESULT hr = mWindow->get_Dispatcher(&mDispatcher);
|
mWidget->Paint(region);
|
||||||
AssertRetHRESULT(hr, hr);
|
|
||||||
|
|
||||||
// Needs mDispatcher
|
// Activate the window, this kills the splash screen
|
||||||
|
mWindow->Activate();
|
||||||
|
|
||||||
|
ProcessLaunchArguments();
|
||||||
AddEventHandlers();
|
AddEventHandlers();
|
||||||
|
SetupContracts();
|
||||||
|
|
||||||
// Drop into the main metro event loop
|
|
||||||
mDispatcher->ProcessEvents(ABI::Windows::UI::Core::CoreProcessEventsOption::CoreProcessEventsOption_ProcessUntilQuit);
|
|
||||||
|
|
||||||
Log("Exiting FrameworkView::Run()");
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,12 +144,9 @@ void
|
|||||||
FrameworkView::AddEventHandlers() {
|
FrameworkView::AddEventHandlers() {
|
||||||
NS_ASSERTION(mWindow, "SetWindow must be called before AddEventHandlers!");
|
NS_ASSERTION(mWindow, "SetWindow must be called before AddEventHandlers!");
|
||||||
NS_ASSERTION(mWidget, "SetWidget must be called before AddEventHAndlers!");
|
NS_ASSERTION(mWidget, "SetWidget must be called before AddEventHAndlers!");
|
||||||
NS_ASSERTION(mDispatcher, "Must have a valid CoreDispatcher before "
|
|
||||||
"calling AddEventHAndlers!");
|
|
||||||
|
|
||||||
mMetroInput = Make<MetroInput>(mWidget.Get(),
|
mMetroInput = Make<MetroInput>(mWidget.Get(),
|
||||||
mWindow.Get(),
|
mWindow.Get());
|
||||||
mDispatcher.Get());
|
|
||||||
|
|
||||||
mWindow->add_VisibilityChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs>(
|
mWindow->add_VisibilityChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs>(
|
||||||
this, &FrameworkView::OnWindowVisibilityChanged).Get(), &mWindowVisibilityChanged);
|
this, &FrameworkView::OnWindowVisibilityChanged).Get(), &mWindowVisibilityChanged);
|
||||||
@ -208,7 +184,25 @@ FrameworkView::AddEventHandlers() {
|
|||||||
void
|
void
|
||||||
FrameworkView::ShutdownXPCOM()
|
FrameworkView::ShutdownXPCOM()
|
||||||
{
|
{
|
||||||
Uninitialize();
|
LogFunction();
|
||||||
|
mShuttingDown = true;
|
||||||
|
|
||||||
|
if (mAutomationProvider) {
|
||||||
|
ComPtr<IUIABridge> provider;
|
||||||
|
mAutomationProvider.As(&provider);
|
||||||
|
if (provider) {
|
||||||
|
provider->Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAutomationProvider = nullptr;
|
||||||
|
|
||||||
|
mMetroInput = nullptr;
|
||||||
|
mD2DWindowSurface = nullptr;
|
||||||
|
delete sSettingsArray;
|
||||||
|
sSettingsArray = nullptr;
|
||||||
|
mWidget = nullptr;
|
||||||
|
mMetroApp = nullptr;
|
||||||
|
mWindow = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -289,6 +283,8 @@ FrameworkView::IsVisible() const
|
|||||||
void FrameworkView::SetDpi(float aDpi)
|
void FrameworkView::SetDpi(float aDpi)
|
||||||
{
|
{
|
||||||
if (aDpi != mDPI) {
|
if (aDpi != mDPI) {
|
||||||
|
LogFunction();
|
||||||
|
|
||||||
mDPI = aDpi;
|
mDPI = aDpi;
|
||||||
// Often a DPI change implies a window size change.
|
// Often a DPI change implies a window size change.
|
||||||
NS_ASSERTION(mWindow, "SetWindow must be called before SetDpi!");
|
NS_ASSERTION(mWindow, "SetWindow must be called before SetDpi!");
|
||||||
@ -346,8 +342,6 @@ FrameworkView::OnActivated(ICoreApplicationView* aApplicationView,
|
|||||||
IActivatedEventArgs* aArgs)
|
IActivatedEventArgs* aArgs)
|
||||||
{
|
{
|
||||||
LogFunction();
|
LogFunction();
|
||||||
// If we're on startup, we want to wait for FrameworkView::Run to run because
|
|
||||||
// XPCOM is not initialized yet and and we can't use nsICommandLineRunner
|
|
||||||
|
|
||||||
ApplicationExecutionState state;
|
ApplicationExecutionState state;
|
||||||
aArgs->get_PreviousExecutionState(&state);
|
aArgs->get_PreviousExecutionState(&state);
|
||||||
@ -452,11 +446,6 @@ FrameworkView::OnWindowActivated(ICoreWindow* aSender, IWindowActivatedEventArgs
|
|||||||
aArgs->get_WindowActivationState(&state);
|
aArgs->get_WindowActivationState(&state);
|
||||||
mWinActiveState = !(state == CoreWindowActivationState::CoreWindowActivationState_Deactivated);
|
mWinActiveState = !(state == CoreWindowActivationState::CoreWindowActivationState_Deactivated);
|
||||||
SendActivationEvent();
|
SendActivationEvent();
|
||||||
|
|
||||||
// Flush out all remaining events so base widget doesn't process other stuff
|
|
||||||
// earlier which would lead to a white flash of a second at startup.
|
|
||||||
MetroAppShell::ProcessAllNativeEventsPresent();
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +454,9 @@ FrameworkView::OnLogicalDpiChanged(IInspectable* aSender)
|
|||||||
{
|
{
|
||||||
LogFunction();
|
LogFunction();
|
||||||
UpdateLogicalDPI();
|
UpdateLogicalDPI();
|
||||||
Render();
|
if (mWidget) {
|
||||||
|
mWidget->Invalidate();
|
||||||
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +78,10 @@ public:
|
|||||||
STDMETHODIMP Run();
|
STDMETHODIMP Run();
|
||||||
STDMETHODIMP Uninitialize();
|
STDMETHODIMP Uninitialize();
|
||||||
|
|
||||||
|
HRESULT ActivateView();
|
||||||
|
|
||||||
// Public apis for MetroWidget
|
// Public apis for MetroWidget
|
||||||
void ShutdownXPCOM();
|
void ShutdownXPCOM();
|
||||||
bool Render();
|
|
||||||
bool Render(const nsIntRegion& aInvalidRegion);
|
|
||||||
float GetDPI() { return mDPI; }
|
float GetDPI() { return mDPI; }
|
||||||
ICoreWindow* GetCoreWindow() { return mWindow.Get(); }
|
ICoreWindow* GetCoreWindow() { return mWindow.Get(); }
|
||||||
void SetWidget(MetroWidget* aWidget);
|
void SetWidget(MetroWidget* aWidget);
|
||||||
@ -180,7 +180,6 @@ private:
|
|||||||
nsIntRect mWindowBounds; // in device-pixel coordinates
|
nsIntRect mWindowBounds; // in device-pixel coordinates
|
||||||
float mDPI;
|
float mDPI;
|
||||||
bool mShuttingDown;
|
bool mShuttingDown;
|
||||||
bool mPainting;
|
|
||||||
nsAutoString mActivationURI;
|
nsAutoString mActivationURI;
|
||||||
nsAutoString mActivationCommandLine;
|
nsAutoString mActivationCommandLine;
|
||||||
Microsoft::WRL::ComPtr<IInspectable> mAutomationProvider;
|
Microsoft::WRL::ComPtr<IInspectable> mAutomationProvider;
|
||||||
@ -190,7 +189,6 @@ private:
|
|||||||
//Microsoft::WRL::ComPtr<IWICImagingFactory2> mWicFactory;
|
//Microsoft::WRL::ComPtr<IWICImagingFactory2> mWicFactory;
|
||||||
Microsoft::WRL::ComPtr<MetroApp> mMetroApp;
|
Microsoft::WRL::ComPtr<MetroApp> mMetroApp;
|
||||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||||
Microsoft::WRL::ComPtr<ICoreDispatcher> mDispatcher;
|
|
||||||
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
||||||
Microsoft::WRL::ComPtr<MetroInput> mMetroInput;
|
Microsoft::WRL::ComPtr<MetroInput> mMetroInput;
|
||||||
static bool sKeyboardIsVisible;
|
static bool sKeyboardIsVisible;
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
|
||||||
#include "FrameworkView.h"
|
|
||||||
#include "MetroWidget.h"
|
|
||||||
#include "mozilla/AutoRestore.h"
|
|
||||||
#include "MetroUtils.h"
|
|
||||||
#include "nsIWidgetListener.h"
|
|
||||||
|
|
||||||
#include <windows.ui.xaml.media.dxinterop.h>
|
|
||||||
|
|
||||||
using namespace mozilla::gfx;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace widget {
|
|
||||||
namespace winrt {
|
|
||||||
|
|
||||||
static bool
|
|
||||||
IsRenderMode(gfxWindowsPlatform::RenderMode aRMode)
|
|
||||||
{
|
|
||||||
return gfxWindowsPlatform::GetPlatform()->GetRenderMode() == aRMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
FrameworkView::Render()
|
|
||||||
{
|
|
||||||
Rect msrect;
|
|
||||||
mWindow->get_Bounds(&msrect);
|
|
||||||
nsIntRegion region(nsIntRect(0, 0, (uint32_t)ceil(msrect.Width),
|
|
||||||
(uint32_t)ceil(msrect.Height)));
|
|
||||||
return Render(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
FrameworkView::Render(const nsIntRegion& aInvalidRegion)
|
|
||||||
{
|
|
||||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
|
|
||||||
|
|
||||||
if (mShuttingDown || mPainting || !mWidget) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we haven't created the layer manager, then create it now.
|
|
||||||
// The swap buffer will be resized automatically by the layer manager.
|
|
||||||
if (!mWidget->mLayerManager) {
|
|
||||||
(void)mWidget->GetLayerManager();
|
|
||||||
if (!mWidget->mLayerManager) {
|
|
||||||
NS_WARNING("mWidget->GetLayerManager() failed!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If OMTC is not in use, then we only support D2D rendering
|
|
||||||
if (!mWidget->ShouldUseOffMainThreadCompositing()) {
|
|
||||||
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) ||
|
|
||||||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) ||
|
|
||||||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)) {
|
|
||||||
NS_WARNING("Unsupported render mode, can't draw. Needs to be D2D.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mWidget->GetTransparencyMode() != eTransparencyOpaque) {
|
|
||||||
NS_WARNING("transparency modes other than eTransparencyOpaque unsupported, can't draw.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoRestore<bool> painting(mPainting);
|
|
||||||
mPainting = true;
|
|
||||||
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
|
|
||||||
mWidget->Paint(aInvalidRegion);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} } }
|
|
@ -60,28 +60,12 @@ MetroApp::CreateView(ABI::Windows::ApplicationModel::Core::IFrameworkView **aVie
|
|||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// MetroApp impl.
|
// MetroApp impl.
|
||||||
|
|
||||||
// called after FrameworkView::Run() drops into the event dispatch loop
|
|
||||||
void
|
void
|
||||||
MetroApp::Initialize()
|
MetroApp::Run()
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
|
||||||
LogThread();
|
LogThread();
|
||||||
|
|
||||||
static bool xpcomInit;
|
HRESULT hr;
|
||||||
if (!xpcomInit) {
|
|
||||||
xpcomInit = true;
|
|
||||||
Log("XPCOM startup initialization began");
|
|
||||||
nsresult rv = XRE_metroStartup(true);
|
|
||||||
Log("XPCOM startup initialization complete");
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
Log("XPCOM startup initialization failed, bailing. rv=%X", rv);
|
|
||||||
CoreExit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sFrameworkView->SetupContracts();
|
|
||||||
|
|
||||||
hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>(
|
hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>(
|
||||||
this, &MetroApp::OnSuspending).Get(), &mSuspendEvent);
|
this, &MetroApp::OnSuspending).Get(), &mSuspendEvent);
|
||||||
AssertHRESULT(hr);
|
AssertHRESULT(hr);
|
||||||
@ -90,7 +74,13 @@ MetroApp::Initialize()
|
|||||||
this, &MetroApp::OnResuming).Get(), &mResumeEvent);
|
this, &MetroApp::OnResuming).Get(), &mResumeEvent);
|
||||||
AssertHRESULT(hr);
|
AssertHRESULT(hr);
|
||||||
|
|
||||||
mozilla::widget::StartAudioSession();
|
Log("XPCOM startup initialization began");
|
||||||
|
nsresult rv = XRE_metroStartup(true);
|
||||||
|
Log("XPCOM startup initialization complete");
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
Log("XPCOM startup initialization failed, bailing. rv=%X", rv);
|
||||||
|
CoreExit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free all xpcom related resources before calling the xre shutdown call.
|
// Free all xpcom related resources before calling the xre shutdown call.
|
||||||
@ -100,8 +90,6 @@ MetroApp::ShutdownXPCOM()
|
|||||||
{
|
{
|
||||||
LogThread();
|
LogThread();
|
||||||
|
|
||||||
mozilla::widget::StopAudioSession();
|
|
||||||
|
|
||||||
if (sCoreApp) {
|
if (sCoreApp) {
|
||||||
sCoreApp->remove_Suspending(mSuspendEvent);
|
sCoreApp->remove_Suspending(mSuspendEvent);
|
||||||
sCoreApp->remove_Resuming(mResumeEvent);
|
sCoreApp->remove_Resuming(mResumeEvent);
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
// nsIWinMetroUtils tile related async callbacks
|
// nsIWinMetroUtils tile related async callbacks
|
||||||
HRESULT OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation, AsyncStatus aStatus);
|
HRESULT OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation, AsyncStatus aStatus);
|
||||||
|
|
||||||
void Initialize();
|
void Run();
|
||||||
void CoreExit();
|
void CoreExit();
|
||||||
|
|
||||||
void ShutdownXPCOM();
|
void ShutdownXPCOM();
|
||||||
|
@ -8,10 +8,13 @@
|
|||||||
#include "mozilla/widget/AudioSession.h"
|
#include "mozilla/widget/AudioSession.h"
|
||||||
#include "MetroUtils.h"
|
#include "MetroUtils.h"
|
||||||
#include "MetroApp.h"
|
#include "MetroApp.h"
|
||||||
|
#include "FrameworkView.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "WinUtils.h"
|
#include "WinUtils.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
using namespace mozilla::widget;
|
using namespace mozilla::widget;
|
||||||
using namespace mozilla::widget::winrt;
|
using namespace mozilla::widget::winrt;
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
@ -19,10 +22,14 @@ using namespace Microsoft::WRL::Wrappers;
|
|||||||
using namespace ABI::Windows::UI::Core;
|
using namespace ABI::Windows::UI::Core;
|
||||||
using namespace ABI::Windows::Foundation;
|
using namespace ABI::Windows::Foundation;
|
||||||
|
|
||||||
|
// ProcessNextNativeEvent message wait timeout, see bug 907410.
|
||||||
|
#define MSG_WAIT_TIMEOUT 250
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace widget {
|
namespace widget {
|
||||||
namespace winrt {
|
namespace winrt {
|
||||||
extern ComPtr<MetroApp> sMetroApp;
|
extern ComPtr<MetroApp> sMetroApp;
|
||||||
|
extern ComPtr<FrameworkView> sFrameworkView;
|
||||||
} } }
|
} } }
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -32,6 +39,7 @@ extern UINT sAppShellGeckoMsgId;
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
static ComPtr<ICoreWindowStatic> sCoreStatic;
|
static ComPtr<ICoreWindowStatic> sCoreStatic;
|
||||||
|
static bool sIsDispatching = false;
|
||||||
|
|
||||||
MetroAppShell::~MetroAppShell()
|
MetroAppShell::~MetroAppShell()
|
||||||
{
|
{
|
||||||
@ -101,7 +109,16 @@ MetroAppShell::Run(void)
|
|||||||
rv = NS_ERROR_NOT_IMPLEMENTED;
|
rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
case GeckoProcessType_Default:
|
case GeckoProcessType_Default:
|
||||||
// Nothing to do, just return.
|
mozilla::widget::StartAudioSession();
|
||||||
|
sFrameworkView->ActivateView();
|
||||||
|
rv = nsBaseAppShell::Run();
|
||||||
|
mozilla::widget::StopAudioSession();
|
||||||
|
// This calls XRE_metroShutdown() in xre. This will also destroy
|
||||||
|
// MessagePump.
|
||||||
|
sMetroApp->ShutdownXPCOM();
|
||||||
|
// This will free the real main thread in CoreApplication::Run()
|
||||||
|
// once winrt cleans up this thread.
|
||||||
|
sMetroApp->CoreExit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,50 +145,29 @@ ProcessNativeEvents(CoreProcessEventsOption eventOption)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
bool
|
||||||
MetroAppShell::ProcessOneNativeEventIfPresent()
|
MetroAppShell::ProcessOneNativeEventIfPresent()
|
||||||
{
|
{
|
||||||
|
if (sIsDispatching) {
|
||||||
|
NS_RUNTIMEABORT("Reentrant call into process events, this is not allowed in Winrt land. Goodbye!");
|
||||||
|
}
|
||||||
|
AutoRestore<bool> dispatching(sIsDispatching);
|
||||||
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent);
|
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent);
|
||||||
}
|
return !!HIWORD(::GetQueueStatus(MOZ_QS_ALLEVENT));
|
||||||
|
|
||||||
// static
|
|
||||||
void
|
|
||||||
MetroAppShell::ProcessAllNativeEventsPresent()
|
|
||||||
{
|
|
||||||
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessAllIfPresent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MetroAppShell::ProcessNextNativeEvent(bool mayWait)
|
MetroAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||||
{
|
{
|
||||||
MSG msg;
|
if (ProcessOneNativeEventIfPresent()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (mayWait) {
|
if (mayWait) {
|
||||||
if (!WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, MSG_WAIT_TIMEOUT, MOZ_QS_ALLEVENT,
|
||||||
WinUtils::WaitForMessage();
|
MWMO_INPUTAVAILABLE|MWMO_ALERTABLE);
|
||||||
}
|
NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed");
|
||||||
ProcessOneNativeEventIfPresent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return ProcessOneNativeEventIfPresent();
|
||||||
if (WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
|
||||||
ProcessOneNativeEventIfPresent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Results from a call to appstartup->quit, which fires a final nsAppExitEvent
|
|
||||||
// event which calls us here. This is on the metro main thread. We want to
|
|
||||||
// call xpcom shutdown here, but we need to wait until the runnable that fires
|
|
||||||
// this is off the stack. See NativeEventCallback below.
|
|
||||||
NS_IMETHODIMP
|
|
||||||
MetroAppShell::Exit(void)
|
|
||||||
{
|
|
||||||
LogFunction();
|
|
||||||
mExiting = true;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -179,22 +175,6 @@ MetroAppShell::NativeCallback()
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Native callbacks must be on the metro main thread");
|
NS_ASSERTION(NS_IsMainThread(), "Native callbacks must be on the metro main thread");
|
||||||
NativeEventCallback();
|
NativeEventCallback();
|
||||||
|
|
||||||
// Handle shutdown after Exit() is called and unwinds.
|
|
||||||
if (mExiting) {
|
|
||||||
// shutdown fires events, don't recurse
|
|
||||||
static bool sShutdown = false;
|
|
||||||
if (sShutdown)
|
|
||||||
return;
|
|
||||||
sShutdown = true;
|
|
||||||
if (sMetroApp) {
|
|
||||||
// This calls XRE_metroShutdown() in xre
|
|
||||||
sMetroApp->ShutdownXPCOM();
|
|
||||||
// This will free the real main thread in CoreApplication::Run()
|
|
||||||
// once winrt cleans up this thread.
|
|
||||||
sMetroApp->CoreExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -15,26 +15,27 @@ class MetroAppShell : public nsBaseAppShell
|
|||||||
public:
|
public:
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
MetroAppShell() : mEventWnd(NULL), mExiting(false), mPowerRequestCount(0)
|
MetroAppShell() :
|
||||||
{}
|
mEventWnd(NULL),
|
||||||
|
mPowerRequestCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
void DoProcessMoreGeckoEvents();
|
void DoProcessMoreGeckoEvents();
|
||||||
void NativeCallback();
|
void NativeCallback();
|
||||||
|
|
||||||
static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
|
static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
static void ProcessAllNativeEventsPresent();
|
static bool ProcessOneNativeEventIfPresent();
|
||||||
static void ProcessOneNativeEventIfPresent();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HWND mEventWnd;
|
|
||||||
bool mExiting;
|
|
||||||
nsAutoHandle mPowerRequest;
|
|
||||||
ULONG mPowerRequestCount;
|
|
||||||
|
|
||||||
NS_IMETHOD Run();
|
NS_IMETHOD Run();
|
||||||
NS_IMETHOD Exit();
|
|
||||||
virtual void ScheduleNativeEventCallback();
|
virtual void ScheduleNativeEventCallback();
|
||||||
virtual bool ProcessNextNativeEvent(bool mayWait);
|
virtual bool ProcessNextNativeEvent(bool mayWait);
|
||||||
virtual ~MetroAppShell();
|
virtual ~MetroAppShell();
|
||||||
|
|
||||||
|
HWND mEventWnd;
|
||||||
|
nsAutoHandle mPowerRequest;
|
||||||
|
ULONG mPowerRequestCount;
|
||||||
};
|
};
|
||||||
|
@ -153,12 +153,9 @@ namespace widget {
|
|||||||
namespace winrt {
|
namespace winrt {
|
||||||
|
|
||||||
MetroInput::MetroInput(MetroWidget* aWidget,
|
MetroInput::MetroInput(MetroWidget* aWidget,
|
||||||
UI::Core::ICoreWindow* aWindow,
|
UI::Core::ICoreWindow* aWindow)
|
||||||
UI::Core::ICoreDispatcher* aDispatcher)
|
|
||||||
: mWidget(aWidget),
|
: mWidget(aWidget),
|
||||||
mWindow(aWindow),
|
mWindow(aWindow)
|
||||||
mDispatcher(aDispatcher),
|
|
||||||
mTouchEvent(true, NS_TOUCH_MOVE, aWidget)
|
|
||||||
{
|
{
|
||||||
LogFunction();
|
LogFunction();
|
||||||
NS_ASSERTION(aWidget, "Attempted to create MetroInput for null widget!");
|
NS_ASSERTION(aWidget, "Attempted to create MetroInput for null widget!");
|
||||||
@ -220,6 +217,7 @@ MetroInput::OnEdgeGestureStarted(UI::Input::IEdgeGesture* sender,
|
|||||||
|
|
||||||
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
|
|
||||||
|
// Safe
|
||||||
DispatchEventIgnoreStatus(&geckoEvent);
|
DispatchEventIgnoreStatus(&geckoEvent);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -251,6 +249,7 @@ MetroInput::OnEdgeGestureCanceled(UI::Input::IEdgeGesture* sender,
|
|||||||
|
|
||||||
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
|
|
||||||
|
// Safe
|
||||||
DispatchEventIgnoreStatus(&geckoEvent);
|
DispatchEventIgnoreStatus(&geckoEvent);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -288,6 +287,7 @@ MetroInput::OnEdgeGestureCompleted(UI::Input::IEdgeGesture* sender,
|
|||||||
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safe
|
||||||
DispatchEventIgnoreStatus(&geckoEvent);
|
DispatchEventIgnoreStatus(&geckoEvent);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -309,43 +309,51 @@ MetroInput::OnPointerNonTouch(UI::Input::IPointerPoint* aPoint) {
|
|||||||
aPoint->get_Properties(props.GetAddressOf());
|
aPoint->get_Properties(props.GetAddressOf());
|
||||||
props->get_PointerUpdateKind(&pointerUpdateKind);
|
props->get_PointerUpdateKind(&pointerUpdateKind);
|
||||||
|
|
||||||
nsMouseEvent mouseEvent(true,
|
nsMouseEvent* event =
|
||||||
NS_MOUSE_MOVE,
|
new nsMouseEvent(true,
|
||||||
mWidget.Get(),
|
NS_MOUSE_MOVE,
|
||||||
nsMouseEvent::eReal,
|
mWidget.Get(),
|
||||||
nsMouseEvent::eNormal);
|
nsMouseEvent::eReal,
|
||||||
|
nsMouseEvent::eNormal);
|
||||||
|
|
||||||
switch (pointerUpdateKind) {
|
switch (pointerUpdateKind) {
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_LeftButtonPressed:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_LeftButtonPressed:
|
||||||
// We don't bother setting mouseEvent.button because it is already
|
// We don't bother setting mouseEvent.button because it is already
|
||||||
// set to nsMouseEvent::buttonType::eLeftButton whose value is 0.
|
// set to nsMouseEvent::buttonType::eLeftButton whose value is 0.
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_DOWN;
|
event->message = NS_MOUSE_BUTTON_DOWN;
|
||||||
break;
|
break;
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_MiddleButtonPressed:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_MiddleButtonPressed:
|
||||||
mouseEvent.button = nsMouseEvent::buttonType::eMiddleButton;
|
event->button = nsMouseEvent::buttonType::eMiddleButton;
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_DOWN;
|
event->message = NS_MOUSE_BUTTON_DOWN;
|
||||||
break;
|
break;
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_RightButtonPressed:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_RightButtonPressed:
|
||||||
mouseEvent.button = nsMouseEvent::buttonType::eRightButton;
|
event->button = nsMouseEvent::buttonType::eRightButton;
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_DOWN;
|
event->message = NS_MOUSE_BUTTON_DOWN;
|
||||||
break;
|
break;
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_LeftButtonReleased:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_LeftButtonReleased:
|
||||||
// We don't bother setting mouseEvent.button because it is already
|
// We don't bother setting mouseEvent.button because it is already
|
||||||
// set to nsMouseEvent::buttonType::eLeftButton whose value is 0.
|
// set to nsMouseEvent::buttonType::eLeftButton whose value is 0.
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_UP;
|
event->message = NS_MOUSE_BUTTON_UP;
|
||||||
break;
|
break;
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_MiddleButtonReleased:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_MiddleButtonReleased:
|
||||||
mouseEvent.button = nsMouseEvent::buttonType::eMiddleButton;
|
event->button = nsMouseEvent::buttonType::eMiddleButton;
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_UP;
|
event->message = NS_MOUSE_BUTTON_UP;
|
||||||
break;
|
break;
|
||||||
case UI::Input::PointerUpdateKind::PointerUpdateKind_RightButtonReleased:
|
case UI::Input::PointerUpdateKind::PointerUpdateKind_RightButtonReleased:
|
||||||
mouseEvent.button = nsMouseEvent::buttonType::eRightButton;
|
event->button = nsMouseEvent::buttonType::eRightButton;
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_UP;
|
event->message = NS_MOUSE_BUTTON_UP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
InitGeckoMouseEventFromPointerPoint(mouseEvent, aPoint);
|
InitGeckoMouseEventFromPointerPoint(event, aPoint);
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
DispatchAsyncEventIgnoreStatus(event);
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroInput::InitTouchEventTouchList(nsTouchEvent* aEvent)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aEvent);
|
||||||
|
mTouches.Enumerate(&AppendToTouchList,
|
||||||
|
static_cast<void*>(&aEvent->touches));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This event is raised when the user pushes the left mouse button, presses a
|
// This event is raised when the user pushes the left mouse button, presses a
|
||||||
@ -381,104 +389,40 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender,
|
|||||||
nsRefPtr<Touch> touch = CreateDOMTouch(currentPoint.Get());
|
nsRefPtr<Touch> touch = CreateDOMTouch(currentPoint.Get());
|
||||||
touch->mChanged = true;
|
touch->mChanged = true;
|
||||||
mTouches.Put(pointerId, touch);
|
mTouches.Put(pointerId, touch);
|
||||||
mTouchEvent.message = NS_TOUCH_START;
|
|
||||||
|
|
||||||
// If this is the first touchstart of a touch session,
|
nsTouchEvent* touchEvent =
|
||||||
// dispatch it now so we can see if preventDefault gets called on it.
|
new nsTouchEvent(true, NS_TOUCH_START, mWidget.Get());
|
||||||
|
|
||||||
if (mTouches.Count() == 1) {
|
if (mTouches.Count() == 1) {
|
||||||
nsEventStatus status;
|
// If this is the first touchstart of a touch session reset some
|
||||||
DispatchPendingTouchEvent(status, true);
|
// tracking flags and dispatch the event with a custom callback
|
||||||
mTouchStartDefaultPrevented = (nsEventStatus_eConsumeNoDefault == status);
|
// so we can check preventDefault result.
|
||||||
// If the first touchstart event has preventDefault called on it, then
|
mTouchStartDefaultPrevented = false;
|
||||||
// we will not perform any default actions associated with any touch
|
mTouchMoveDefaultPrevented = false;
|
||||||
// events for this session, including touchmove events.
|
mIsFirstTouchMove = true;
|
||||||
// Thus, mTouchStartDefaultPrevented implies mTouchMoveDefaultPrevented.
|
InitTouchEventTouchList(touchEvent);
|
||||||
mTouchMoveDefaultPrevented = mTouchStartDefaultPrevented;
|
DispatchAsyncTouchEventWithCallback(touchEvent, &MetroInput::OnPointerPressedCallback);
|
||||||
mIsFirstTouchMove = !mTouchStartDefaultPrevented;
|
} else {
|
||||||
|
InitTouchEventTouchList(touchEvent);
|
||||||
|
DispatchAsyncTouchEventIgnoreStatus(touchEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the first touchstart of this touch session had its preventDefault
|
|
||||||
// called on it, we will not perform any default actions for any of the
|
|
||||||
// touches in this touch session.
|
|
||||||
if (!mTouchStartDefaultPrevented) {
|
if (!mTouchStartDefaultPrevented) {
|
||||||
mGestureRecognizer->ProcessDownEvent(currentPoint.Get());
|
mGestureRecognizer->ProcessDownEvent(currentPoint.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This event is raised when the user lifts the left mouse button, lifts a
|
void
|
||||||
// pen from the surface, or lifts her/his finger from a touch screen.
|
MetroInput::OnPointerPressedCallback()
|
||||||
HRESULT
|
|
||||||
MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender,
|
|
||||||
UI::Core::IPointerEventArgs* aArgs)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_INPUT
|
nsEventStatus status = DeliverNextQueuedTouchEvent();
|
||||||
LogFunction();
|
mTouchStartDefaultPrevented = (nsEventStatus_eConsumeNoDefault == status);
|
||||||
#endif
|
// If content cancelled the first touchstart don't generate any gesture based
|
||||||
|
// input - clear the recognizer state without sending any events.
|
||||||
WRL::ComPtr<UI::Input::IPointerPoint> currentPoint;
|
if (mTouchStartDefaultPrevented) {
|
||||||
WRL::ComPtr<Devices::Input::IPointerDevice> device;
|
mGestureRecognizer->CompleteGesture();
|
||||||
Devices::Input::PointerDeviceType deviceType;
|
|
||||||
|
|
||||||
aArgs->get_CurrentPoint(currentPoint.GetAddressOf());
|
|
||||||
currentPoint->get_PointerDevice(device.GetAddressOf());
|
|
||||||
device->get_PointerDeviceType(&deviceType);
|
|
||||||
|
|
||||||
// For mouse and pen input, simply call our helper function
|
|
||||||
if (deviceType !=
|
|
||||||
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
|
||||||
OnPointerNonTouch(currentPoint.Get());
|
|
||||||
mGestureRecognizer->ProcessUpEvent(currentPoint.Get());
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is touch input.
|
|
||||||
// Get the touch associated with this touch point.
|
|
||||||
uint32_t pointerId;
|
|
||||||
currentPoint->get_PointerId(&pointerId);
|
|
||||||
nsRefPtr<Touch> touch = mTouches.Get(pointerId);
|
|
||||||
|
|
||||||
// We are about to dispatch a touchend. Before we do that, we should make
|
|
||||||
// sure that we don't have a touchmove or touchstart sitting around for this
|
|
||||||
// point.
|
|
||||||
if (touch->mChanged) {
|
|
||||||
DispatchPendingTouchEvent(true);
|
|
||||||
}
|
|
||||||
mTouches.Remove(pointerId);
|
|
||||||
|
|
||||||
// touchend events only have a single touch; the touch that has been removed
|
|
||||||
mTouchEvent.message = NS_TOUCH_END;
|
|
||||||
mTouchEvent.touches.Clear();
|
|
||||||
mTouchEvent.touches.AppendElement(CreateDOMTouch(currentPoint.Get()));
|
|
||||||
mTouchEvent.time = ::GetMessageTime();
|
|
||||||
mModifierKeyState.Update();
|
|
||||||
mModifierKeyState.InitInputEvent(mTouchEvent);
|
|
||||||
|
|
||||||
nsEventStatus status;
|
|
||||||
mWidget->DispatchEvent(&mTouchEvent, status);
|
|
||||||
if (status != nsEventStatus_eConsumeNoDefault) {
|
|
||||||
MultiTouchInput inputData(mTouchEvent);
|
|
||||||
if (MetroWidget::sAPZC) {
|
|
||||||
status = MetroWidget::sAPZC->ReceiveInputEvent(inputData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mTouchEvent.message should always be set to NS_TOUCH_MOVE
|
|
||||||
mTouchEvent.message = NS_TOUCH_MOVE;
|
|
||||||
|
|
||||||
// If the first touchstart of this touch session had its preventDefault
|
|
||||||
// called on it, we will not perform any default actions for any of the
|
|
||||||
// touches in this touch session. Note that we don't check
|
|
||||||
// mTouchMoveDefaultPrevented here. The reason is that, even if
|
|
||||||
// preventDefault was called on the first touchmove event, we might still
|
|
||||||
// want to dispatch a click (mousemove, mousedown, mouseup) in response to
|
|
||||||
// this touch.
|
|
||||||
if (!mTouchStartDefaultPrevented) {
|
|
||||||
mGestureRecognizer->ProcessUpEvent(currentPoint.Get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This event is raised when the user moves the mouse, moves a pen that is
|
// This event is raised when the user moves the mouse, moves a pen that is
|
||||||
@ -525,42 +469,119 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender,
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're modifying a touch entry that has a pending update, go through
|
// If we've accumulated a batch of pointer moves and we're now on a new batch
|
||||||
// with the update.
|
// at a new position send the previous batch. (perf opt)
|
||||||
if (touch->mChanged) {
|
if (touch->mChanged) {
|
||||||
DispatchPendingTouchEvent(true);
|
nsTouchEvent* touchEvent =
|
||||||
|
new nsTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get());
|
||||||
|
InitTouchEventTouchList(touchEvent);
|
||||||
|
DispatchAsyncTouchEventIgnoreStatus(touchEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
touch = CreateDOMTouch(currentPoint.Get());
|
touch = CreateDOMTouch(currentPoint.Get());
|
||||||
touch->mChanged = true;
|
touch->mChanged = true;
|
||||||
|
// replacing old touch point in mTouches map
|
||||||
mTouches.Put(pointerId, touch);
|
mTouches.Put(pointerId, touch);
|
||||||
|
|
||||||
// If this is the first touch move of our session, we should dispatch it
|
nsTouchEvent* touchEvent =
|
||||||
// and store our mTouchMoveDefaultPrevented value
|
new nsTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get());
|
||||||
|
|
||||||
|
// If this is the first touch move of our session, we should check the result.
|
||||||
|
// Note we may lose some touch move data here for the recognizer since we want
|
||||||
|
// to wait until we have the result of the first touchmove dispatch. For gesture
|
||||||
|
// based events this shouldn't break anything.
|
||||||
if (mIsFirstTouchMove) {
|
if (mIsFirstTouchMove) {
|
||||||
nsEventStatus status;
|
InitTouchEventTouchList(touchEvent);
|
||||||
DispatchPendingTouchEvent(status, true);
|
DispatchAsyncTouchEventWithCallback(touchEvent, &MetroInput::OnFirstPointerMoveCallback);
|
||||||
mTouchMoveDefaultPrevented = (nsEventStatus_eConsumeNoDefault == status);
|
|
||||||
mIsFirstTouchMove = false;
|
mIsFirstTouchMove = false;
|
||||||
|
} else {
|
||||||
|
// Only feed move input to the recognizer if the first touchstart and
|
||||||
|
// subsequent touchmove return results were not eConsumeNoDefault.
|
||||||
|
if (!mTouchStartDefaultPrevented && !mTouchMoveDefaultPrevented) {
|
||||||
|
WRL::ComPtr<Foundation::Collections::IVector<UI::Input::PointerPoint*>>
|
||||||
|
pointerPoints;
|
||||||
|
aArgs->GetIntermediatePoints(pointerPoints.GetAddressOf());
|
||||||
|
mGestureRecognizer->ProcessMoveEvents(pointerPoints.Get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We will perform default actions for touchmove events only if
|
return S_OK;
|
||||||
// preventDefault was not called on the first touchmove event and
|
}
|
||||||
// preventDefault was not called on the first touchstart event. Checking
|
|
||||||
// mTouchMoveDefaultPrevented is enough here because it will be set if
|
void
|
||||||
// mTouchStartDefaultPrevented is true.
|
MetroInput::OnFirstPointerMoveCallback()
|
||||||
if (!mTouchMoveDefaultPrevented) {
|
{
|
||||||
WRL::ComPtr<Foundation::Collections::IVector<UI::Input::PointerPoint*>>
|
nsTouchEvent* event = static_cast<nsTouchEvent*>(mInputEventQueue.PopFront());
|
||||||
pointerPoints;
|
MOZ_ASSERT(event);
|
||||||
aArgs->GetIntermediatePoints(pointerPoints.GetAddressOf());
|
nsEventStatus status;
|
||||||
mGestureRecognizer->ProcessMoveEvents(pointerPoints.Get());
|
mWidget->DispatchEvent(event, status);
|
||||||
|
mTouchMoveDefaultPrevented = (nsEventStatus_eConsumeNoDefault == status);
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This event is raised when the user lifts the left mouse button, lifts a
|
||||||
|
// pen from the surface, or lifts her/his finger from a touch screen.
|
||||||
|
HRESULT
|
||||||
|
MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender,
|
||||||
|
UI::Core::IPointerEventArgs* aArgs)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_INPUT
|
||||||
|
LogFunction();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WRL::ComPtr<UI::Input::IPointerPoint> currentPoint;
|
||||||
|
WRL::ComPtr<Devices::Input::IPointerDevice> device;
|
||||||
|
Devices::Input::PointerDeviceType deviceType;
|
||||||
|
|
||||||
|
aArgs->get_CurrentPoint(currentPoint.GetAddressOf());
|
||||||
|
currentPoint->get_PointerDevice(device.GetAddressOf());
|
||||||
|
device->get_PointerDeviceType(&deviceType);
|
||||||
|
|
||||||
|
// For mouse and pen input, simply call our helper function
|
||||||
|
if (deviceType !=
|
||||||
|
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
||||||
|
OnPointerNonTouch(currentPoint.Get());
|
||||||
|
mGestureRecognizer->ProcessUpEvent(currentPoint.Get());
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is touch input.
|
||||||
|
// Get the touch associated with this touch point.
|
||||||
|
uint32_t pointerId;
|
||||||
|
currentPoint->get_PointerId(&pointerId);
|
||||||
|
nsRefPtr<Touch> touch = mTouches.Get(pointerId);
|
||||||
|
|
||||||
|
// Purge any pending moves for this pointer
|
||||||
|
if (touch->mChanged) {
|
||||||
|
nsTouchEvent* touchEvent =
|
||||||
|
new nsTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get());
|
||||||
|
InitTouchEventTouchList(touchEvent);
|
||||||
|
DispatchAsyncTouchEventIgnoreStatus(touchEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove this touch point from our map. Eventually all touch points are
|
||||||
|
// removed for this session since we receive released events for every
|
||||||
|
// point.
|
||||||
|
mTouches.Remove(pointerId);
|
||||||
|
|
||||||
|
// touchend events only have a single touch; the touch that has been removed
|
||||||
|
nsTouchEvent* touchEvent =
|
||||||
|
new nsTouchEvent(true, NS_TOUCH_END, mWidget.Get());
|
||||||
|
touchEvent->touches.AppendElement(CreateDOMTouch(currentPoint.Get()));
|
||||||
|
DispatchAsyncTouchEventIgnoreStatus(touchEvent);
|
||||||
|
|
||||||
|
// If content didn't cancel the first touchstart feed touchend data to the
|
||||||
|
// recognizer.
|
||||||
|
if (!mTouchStartDefaultPrevented) {
|
||||||
|
mGestureRecognizer->ProcessUpEvent(currentPoint.Get());
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MetroInput::InitGeckoMouseEventFromPointerPoint(
|
MetroInput::InitGeckoMouseEventFromPointerPoint(
|
||||||
nsMouseEvent& aEvent,
|
nsMouseEvent* aEvent,
|
||||||
UI::Input::IPointerPoint* aPointerPoint) {
|
UI::Input::IPointerPoint* aPointerPoint) {
|
||||||
NS_ASSERTION(aPointerPoint, "InitGeckoMouseEventFromPointerPoint "
|
NS_ASSERTION(aPointerPoint, "InitGeckoMouseEventFromPointerPoint "
|
||||||
"called with null PointerPoint!");
|
"called with null PointerPoint!");
|
||||||
@ -581,19 +602,16 @@ MetroInput::InitGeckoMouseEventFromPointerPoint(
|
|||||||
props->get_Pressure(&pressure);
|
props->get_Pressure(&pressure);
|
||||||
mGestureRecognizer->CanBeDoubleTap(aPointerPoint, &canBeDoubleTap);
|
mGestureRecognizer->CanBeDoubleTap(aPointerPoint, &canBeDoubleTap);
|
||||||
|
|
||||||
mModifierKeyState.Update();
|
aEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
||||||
mModifierKeyState.InitInputEvent(aEvent);
|
|
||||||
aEvent.refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
|
||||||
aEvent.time = timestamp;
|
|
||||||
|
|
||||||
if (!canBeDoubleTap) {
|
if (!canBeDoubleTap) {
|
||||||
aEvent.clickCount = 1;
|
aEvent->clickCount = 1;
|
||||||
} else {
|
} else {
|
||||||
aEvent.clickCount = 2;
|
aEvent->clickCount = 2;
|
||||||
}
|
}
|
||||||
aEvent.pressure = pressure;
|
aEvent->pressure = pressure;
|
||||||
|
|
||||||
MozInputSourceFromDeviceType(deviceType, aEvent.inputSource);
|
MozInputSourceFromDeviceType(deviceType, aEvent->inputSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This event is raised when a precise pointer moves into the bounding box of
|
// This event is raised when a precise pointer moves into the bounding box of
|
||||||
@ -618,13 +636,13 @@ MetroInput::OnPointerEntered(UI::Core::ICoreWindow* aSender,
|
|||||||
// We only dispatch mouseenter and mouseexit events for mouse and pen input.
|
// We only dispatch mouseenter and mouseexit events for mouse and pen input.
|
||||||
if (deviceType !=
|
if (deviceType !=
|
||||||
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
||||||
nsMouseEvent mouseEvent(true,
|
nsMouseEvent* event = new nsMouseEvent(true,
|
||||||
NS_MOUSE_ENTER,
|
NS_MOUSE_ENTER,
|
||||||
mWidget.Get(),
|
mWidget.Get(),
|
||||||
nsMouseEvent::eReal,
|
nsMouseEvent::eReal,
|
||||||
nsMouseEvent::eNormal);
|
nsMouseEvent::eNormal);
|
||||||
InitGeckoMouseEventFromPointerPoint(mouseEvent, currentPoint.Get());
|
InitGeckoMouseEventFromPointerPoint(event, currentPoint.Get());
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
DispatchAsyncEventIgnoreStatus(event);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -651,13 +669,13 @@ MetroInput::OnPointerExited(UI::Core::ICoreWindow* aSender,
|
|||||||
// We only dispatch mouseenter and mouseexit events for mouse and pen input.
|
// We only dispatch mouseenter and mouseexit events for mouse and pen input.
|
||||||
if (deviceType !=
|
if (deviceType !=
|
||||||
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
Devices::Input::PointerDeviceType::PointerDeviceType_Touch) {
|
||||||
nsMouseEvent mouseEvent(true,
|
nsMouseEvent* event = new nsMouseEvent(true,
|
||||||
NS_MOUSE_EXIT,
|
NS_MOUSE_EXIT,
|
||||||
mWidget.Get(),
|
mWidget.Get(),
|
||||||
nsMouseEvent::eReal,
|
nsMouseEvent::eReal,
|
||||||
nsMouseEvent::eNormal);
|
nsMouseEvent::eNormal);
|
||||||
InitGeckoMouseEventFromPointerPoint(mouseEvent, currentPoint.Get());
|
InitGeckoMouseEventFromPointerPoint(event, currentPoint.Get());
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
DispatchAsyncEventIgnoreStatus(event);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -691,33 +709,27 @@ MetroInput::ProcessManipulationDelta(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send a gecko event indicating the magnification since the last update.
|
// Send a gecko event indicating the magnification since the last update.
|
||||||
nsSimpleGestureEvent magEvent(true,
|
nsSimpleGestureEvent* magEvent =
|
||||||
aMagEventType,
|
new nsSimpleGestureEvent(true, aMagEventType, mWidget.Get(), 0, 0.0);
|
||||||
mWidget.Get(), 0, 0.0);
|
|
||||||
magEvent.delta = aDelta.Expansion;
|
magEvent->delta = aDelta.Expansion;
|
||||||
mModifierKeyState.Update();
|
magEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
mModifierKeyState.InitInputEvent(magEvent);
|
magEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
|
||||||
magEvent.time = ::GetMessageTime();
|
DispatchAsyncEventIgnoreStatus(magEvent);
|
||||||
magEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
|
||||||
magEvent.refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
|
|
||||||
DispatchEventIgnoreStatus(&magEvent);
|
|
||||||
|
|
||||||
// Send a gecko event indicating the rotation since the last update.
|
// Send a gecko event indicating the rotation since the last update.
|
||||||
nsSimpleGestureEvent rotEvent(true,
|
nsSimpleGestureEvent* rotEvent =
|
||||||
aRotEventType,
|
new nsSimpleGestureEvent(true, aRotEventType, mWidget.Get(), 0, 0.0);
|
||||||
mWidget.Get(), 0, 0.0);
|
|
||||||
rotEvent.delta = aDelta.Rotation;
|
rotEvent->delta = aDelta.Rotation;
|
||||||
mModifierKeyState.Update();
|
rotEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
mModifierKeyState.InitInputEvent(rotEvent);
|
rotEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
|
||||||
rotEvent.time = ::GetMessageTime();
|
if (rotEvent->delta >= 0) {
|
||||||
rotEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
rotEvent->direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE;
|
||||||
rotEvent.refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
|
|
||||||
if (rotEvent.delta >= 0) {
|
|
||||||
rotEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE;
|
|
||||||
} else {
|
} else {
|
||||||
rotEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE;
|
rotEvent->direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE;
|
||||||
}
|
}
|
||||||
DispatchEventIgnoreStatus(&rotEvent);
|
DispatchAsyncEventIgnoreStatus(rotEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This event is raised when a gesture is detected to have started. The
|
// This event is raised when a gesture is detected to have started. The
|
||||||
@ -837,33 +849,29 @@ MetroInput::OnManipulationCompleted(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isHorizontalSwipe) {
|
if (isHorizontalSwipe) {
|
||||||
nsSimpleGestureEvent swipeEvent(true, NS_SIMPLE_GESTURE_SWIPE,
|
nsSimpleGestureEvent* swipeEvent =
|
||||||
mWidget.Get(), 0, 0.0);
|
new nsSimpleGestureEvent(true, NS_SIMPLE_GESTURE_SWIPE,
|
||||||
swipeEvent.direction = delta.Translation.X > 0
|
mWidget.Get(), 0, 0.0);
|
||||||
|
swipeEvent->direction = delta.Translation.X > 0
|
||||||
? nsIDOMSimpleGestureEvent::DIRECTION_RIGHT
|
? nsIDOMSimpleGestureEvent::DIRECTION_RIGHT
|
||||||
: nsIDOMSimpleGestureEvent::DIRECTION_LEFT;
|
: nsIDOMSimpleGestureEvent::DIRECTION_LEFT;
|
||||||
swipeEvent.delta = delta.Translation.X;
|
swipeEvent->delta = delta.Translation.X;
|
||||||
mModifierKeyState.Update();
|
swipeEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
mModifierKeyState.InitInputEvent(swipeEvent);
|
swipeEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
||||||
swipeEvent.time = ::GetMessageTime();
|
DispatchAsyncEventIgnoreStatus(swipeEvent);
|
||||||
swipeEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
|
||||||
swipeEvent.refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
|
||||||
DispatchEventIgnoreStatus(&swipeEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVerticalSwipe) {
|
if (isVerticalSwipe) {
|
||||||
nsSimpleGestureEvent swipeEvent(true, NS_SIMPLE_GESTURE_SWIPE,
|
nsSimpleGestureEvent* swipeEvent =
|
||||||
mWidget.Get(), 0, 0.0);
|
new nsSimpleGestureEvent(true, NS_SIMPLE_GESTURE_SWIPE,
|
||||||
swipeEvent.direction = delta.Translation.Y > 0
|
mWidget.Get(), 0, 0.0);
|
||||||
|
swipeEvent->direction = delta.Translation.Y > 0
|
||||||
? nsIDOMSimpleGestureEvent::DIRECTION_DOWN
|
? nsIDOMSimpleGestureEvent::DIRECTION_DOWN
|
||||||
: nsIDOMSimpleGestureEvent::DIRECTION_UP;
|
: nsIDOMSimpleGestureEvent::DIRECTION_UP;
|
||||||
swipeEvent.delta = delta.Translation.Y;
|
swipeEvent->delta = delta.Translation.Y;
|
||||||
mModifierKeyState.Update();
|
swipeEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
mModifierKeyState.InitInputEvent(swipeEvent);
|
swipeEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
||||||
swipeEvent.time = ::GetMessageTime();
|
DispatchAsyncEventIgnoreStatus(swipeEvent);
|
||||||
swipeEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
|
||||||
swipeEvent.refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
|
||||||
DispatchEventIgnoreStatus(&swipeEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -927,15 +935,18 @@ MetroInput::HandleDoubleTap(const LayoutDeviceIntPoint& aPoint)
|
|||||||
#ifdef DEBUG_INPUT
|
#ifdef DEBUG_INPUT
|
||||||
LogFunction();
|
LogFunction();
|
||||||
#endif
|
#endif
|
||||||
nsSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_TAP, mWidget.Get(), 0, 0.0);
|
nsSimpleGestureEvent* tapEvent =
|
||||||
mModifierKeyState.Update();
|
new nsSimpleGestureEvent(true,
|
||||||
mModifierKeyState.InitInputEvent(geckoEvent);
|
NS_SIMPLE_GESTURE_TAP,
|
||||||
geckoEvent.time = ::GetMessageTime();
|
mWidget.Get(),
|
||||||
geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
0,
|
||||||
geckoEvent.refPoint = aPoint;
|
0.0);
|
||||||
geckoEvent.clickCount = 2;
|
|
||||||
geckoEvent.pressure = 1;
|
tapEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
DispatchEventIgnoreStatus(&geckoEvent);
|
tapEvent->refPoint = aPoint;
|
||||||
|
tapEvent->clickCount = 2;
|
||||||
|
tapEvent->pressure = 1;
|
||||||
|
DispatchAsyncEventIgnoreStatus(tapEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -945,31 +956,39 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
|||||||
LogFunction();
|
LogFunction();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set up the mouse event that we'll reuse for mousemove, mousedown, and
|
// send mousemove
|
||||||
// mouseup
|
nsMouseEvent* mouseEvent = new nsMouseEvent(true,
|
||||||
nsMouseEvent mouseEvent(true,
|
NS_MOUSE_MOVE,
|
||||||
NS_MOUSE_MOVE,
|
mWidget.Get(),
|
||||||
mWidget.Get(),
|
nsMouseEvent::eReal,
|
||||||
nsMouseEvent::eReal,
|
nsMouseEvent::eNormal);
|
||||||
nsMouseEvent::eNormal);
|
mouseEvent->refPoint = aPoint;
|
||||||
mModifierKeyState.Update();
|
mouseEvent->clickCount = 1;
|
||||||
mModifierKeyState.InitInputEvent(mouseEvent);
|
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
mouseEvent.refPoint = aPoint;
|
DispatchAsyncEventIgnoreStatus(mouseEvent);
|
||||||
mouseEvent.time = ::GetMessageTime();
|
|
||||||
mouseEvent.clickCount = 1;
|
|
||||||
mouseEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
|
||||||
|
|
||||||
// Send the mousemove
|
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
|
||||||
|
|
||||||
// Send the mousedown
|
// Send the mousedown
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_DOWN;
|
mouseEvent = new nsMouseEvent(true,
|
||||||
mouseEvent.button = nsMouseEvent::buttonType::eLeftButton;
|
NS_MOUSE_BUTTON_DOWN,
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
mWidget.Get(),
|
||||||
|
nsMouseEvent::eReal,
|
||||||
|
nsMouseEvent::eNormal);
|
||||||
|
mouseEvent->refPoint = aPoint;
|
||||||
|
mouseEvent->clickCount = 1;
|
||||||
|
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
|
mouseEvent->button = nsMouseEvent::buttonType::eLeftButton;
|
||||||
|
DispatchAsyncEventIgnoreStatus(mouseEvent);
|
||||||
|
|
||||||
// Send the mouseup
|
mouseEvent = new nsMouseEvent(true,
|
||||||
mouseEvent.message = NS_MOUSE_BUTTON_UP;
|
NS_MOUSE_BUTTON_UP,
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
mWidget.Get(),
|
||||||
|
nsMouseEvent::eReal,
|
||||||
|
nsMouseEvent::eNormal);
|
||||||
|
mouseEvent->refPoint = aPoint;
|
||||||
|
mouseEvent->clickCount = 1;
|
||||||
|
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
|
mouseEvent->button = nsMouseEvent::buttonType::eLeftButton;
|
||||||
|
DispatchAsyncEventIgnoreStatus(mouseEvent);
|
||||||
|
|
||||||
// Send one more mousemove to avoid getting a hover state.
|
// Send one more mousemove to avoid getting a hover state.
|
||||||
// In the Metro environment for any application, a tap does not imply a
|
// In the Metro environment for any application, a tap does not imply a
|
||||||
@ -978,10 +997,15 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
|||||||
POINT point;
|
POINT point;
|
||||||
if (GetCursorPos(&point)) {
|
if (GetCursorPos(&point)) {
|
||||||
ScreenToClient((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW), &point);
|
ScreenToClient((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW), &point);
|
||||||
mouseEvent.refPoint = LayoutDeviceIntPoint(point.x, point.y);
|
mouseEvent = new nsMouseEvent(true,
|
||||||
mouseEvent.message = NS_MOUSE_MOVE;
|
NS_MOUSE_MOVE,
|
||||||
mouseEvent.button = 0;
|
mWidget.Get(),
|
||||||
DispatchEventIgnoreStatus(&mouseEvent);
|
nsMouseEvent::eReal,
|
||||||
|
nsMouseEvent::eNormal);
|
||||||
|
mouseEvent->refPoint = LayoutDeviceIntPoint(point.x, point.y);
|
||||||
|
mouseEvent->clickCount = 1;
|
||||||
|
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
|
DispatchAsyncEventIgnoreStatus(mouseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -993,17 +1017,14 @@ MetroInput::HandleLongTap(const LayoutDeviceIntPoint& aPoint)
|
|||||||
LogFunction();
|
LogFunction();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsMouseEvent contextMenu(true,
|
nsMouseEvent* contextEvent = new nsMouseEvent(true,
|
||||||
NS_CONTEXTMENU,
|
NS_CONTEXTMENU,
|
||||||
mWidget.Get(),
|
mWidget.Get(),
|
||||||
nsMouseEvent::eReal,
|
nsMouseEvent::eReal,
|
||||||
nsMouseEvent::eNormal);
|
nsMouseEvent::eNormal);
|
||||||
mModifierKeyState.Update();
|
contextEvent->refPoint = aPoint;
|
||||||
mModifierKeyState.InitInputEvent(contextMenu);
|
contextEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||||
contextMenu.refPoint = aPoint;
|
DispatchAsyncEventIgnoreStatus(contextEvent);
|
||||||
contextMenu.time = ::GetMessageTime();
|
|
||||||
contextMenu.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
|
||||||
DispatchEventIgnoreStatus(&contextMenu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1011,39 +1032,82 @@ MetroInput::HandleLongTap(const LayoutDeviceIntPoint& aPoint)
|
|||||||
*/
|
*/
|
||||||
nsEventStatus MetroInput::sThrowawayStatus;
|
nsEventStatus MetroInput::sThrowawayStatus;
|
||||||
|
|
||||||
// This function allows us to call MetroWidget's DispatchEvent function
|
void
|
||||||
// without passing in a status. It uses a static nsEventStatus whose value
|
MetroInput::DispatchAsyncEventIgnoreStatus(nsInputEvent* aEvent)
|
||||||
// is never read. This allows us to avoid the (admittedly small) overhead
|
{
|
||||||
// of creating a new nsEventStatus every time we dispatch an event.
|
aEvent->time = ::GetMessageTime();
|
||||||
|
mModifierKeyState.Update();
|
||||||
|
mModifierKeyState.InitInputEvent(*aEvent);
|
||||||
|
mInputEventQueue.Push(aEvent);
|
||||||
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
|
NS_NewRunnableMethod(this, &MetroInput::DeliverNextQueuedEventIgnoreStatus);
|
||||||
|
NS_DispatchToCurrentThread(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroInput::DeliverNextQueuedEventIgnoreStatus()
|
||||||
|
{
|
||||||
|
nsGUIEvent* event = static_cast<nsGUIEvent*>(mInputEventQueue.PopFront());
|
||||||
|
MOZ_ASSERT(event);
|
||||||
|
DispatchEventIgnoreStatus(event);
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsEventStatus
|
||||||
|
MetroInput::DeliverNextQueuedEvent()
|
||||||
|
{
|
||||||
|
nsGUIEvent* event = static_cast<nsGUIEvent*>(mInputEventQueue.PopFront());
|
||||||
|
MOZ_ASSERT(event);
|
||||||
|
nsEventStatus status;
|
||||||
|
mWidget->DispatchEvent(event, status);
|
||||||
|
delete event;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroInput::DispatchAsyncTouchEventIgnoreStatus(nsTouchEvent* aEvent)
|
||||||
|
{
|
||||||
|
aEvent->time = ::GetMessageTime();
|
||||||
|
mModifierKeyState.Update();
|
||||||
|
mModifierKeyState.InitInputEvent(*aEvent);
|
||||||
|
mInputEventQueue.Push(aEvent);
|
||||||
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
|
NS_NewRunnableMethod(this, &MetroInput::DeliverNextQueuedTouchEvent);
|
||||||
|
NS_DispatchToCurrentThread(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsEventStatus
|
||||||
|
MetroInput::DeliverNextQueuedTouchEvent()
|
||||||
|
{
|
||||||
|
nsTouchEvent* event = static_cast<nsTouchEvent*>(mInputEventQueue.PopFront());
|
||||||
|
MOZ_ASSERT(event);
|
||||||
|
nsEventStatus status;
|
||||||
|
mWidget->DispatchEvent(event, status);
|
||||||
|
if (status != nsEventStatus_eConsumeNoDefault && MetroWidget::sAPZC) {
|
||||||
|
MultiTouchInput inputData(*event);
|
||||||
|
MetroWidget::sAPZC->ReceiveInputEvent(inputData);
|
||||||
|
}
|
||||||
|
delete event;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroInput::DispatchAsyncTouchEventWithCallback(nsTouchEvent* aEvent, void (MetroInput::*Callback)())
|
||||||
|
{
|
||||||
|
aEvent->time = ::GetMessageTime();
|
||||||
|
mModifierKeyState.Update();
|
||||||
|
mModifierKeyState.InitInputEvent(*aEvent);
|
||||||
|
mInputEventQueue.Push(aEvent);
|
||||||
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
|
NS_NewRunnableMethod(this, Callback);
|
||||||
|
NS_DispatchToCurrentThread(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MetroInput::DispatchEventIgnoreStatus(nsGUIEvent *aEvent) {
|
MetroInput::DispatchEventIgnoreStatus(nsGUIEvent *aEvent) {
|
||||||
mWidget->DispatchEvent(aEvent, sThrowawayStatus);
|
mWidget->DispatchEvent(aEvent, sThrowawayStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MetroInput::DispatchPendingTouchEvent(nsEventStatus& aStatus, bool aDispatchToAPZC) {
|
|
||||||
mTouchEvent.touches.Clear();
|
|
||||||
mTouches.Enumerate(&AppendToTouchList,
|
|
||||||
static_cast<void*>(&mTouchEvent.touches));
|
|
||||||
mTouchEvent.time = ::GetMessageTime();
|
|
||||||
mModifierKeyState.Update();
|
|
||||||
mModifierKeyState.InitInputEvent(mTouchEvent);
|
|
||||||
|
|
||||||
mWidget->DispatchEvent(&mTouchEvent, aStatus);
|
|
||||||
if (aStatus != nsEventStatus_eConsumeNoDefault && aDispatchToAPZC && MetroWidget::sAPZC) {
|
|
||||||
MultiTouchInput inputData(mTouchEvent);
|
|
||||||
aStatus = MetroWidget::sAPZC->ReceiveInputEvent(inputData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mTouchEvent.message should always be set to NS_TOUCH_MOVE
|
|
||||||
mTouchEvent.message = NS_TOUCH_MOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MetroInput::DispatchPendingTouchEvent(bool aDispatchToAPZC) {
|
|
||||||
DispatchPendingTouchEvent(sThrowawayStatus, aDispatchToAPZC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MetroInput::UnregisterInputEvents() {
|
MetroInput::UnregisterInputEvents() {
|
||||||
// Unregister ourselves for the edge swipe event
|
// Unregister ourselves for the edge swipe event
|
||||||
@ -1085,8 +1149,6 @@ MetroInput::RegisterInputEvents()
|
|||||||
NS_ASSERTION(mWindow, "Must have a window to register for input events!");
|
NS_ASSERTION(mWindow, "Must have a window to register for input events!");
|
||||||
NS_ASSERTION(mGestureRecognizer,
|
NS_ASSERTION(mGestureRecognizer,
|
||||||
"Must have a GestureRecognizer for input events!");
|
"Must have a GestureRecognizer for input events!");
|
||||||
NS_ASSERTION(mDispatcher,
|
|
||||||
"Must have a CoreDispatcher to register for input events!");
|
|
||||||
// Register for edge swipe
|
// Register for edge swipe
|
||||||
WRL::ComPtr<UI::Input::IEdgeGestureStatics> edgeStatics;
|
WRL::ComPtr<UI::Input::IEdgeGestureStatics> edgeStatics;
|
||||||
Foundation::GetActivationFactory(
|
Foundation::GetActivationFactory(
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "nsGUIEvent.h" // mTouchEvent (nsTouchEvent)
|
#include "nsGUIEvent.h" // mTouchEvent (nsTouchEvent)
|
||||||
#include "nsHashKeys.h" // type of key for mTouches
|
#include "nsHashKeys.h" // type of key for mTouches
|
||||||
#include "mozwrlbase.h"
|
#include "mozwrlbase.h"
|
||||||
|
#include "nsDeque.h"
|
||||||
|
|
||||||
// System headers (alphabetical)
|
// System headers (alphabetical)
|
||||||
#include <EventToken.h> // EventRegistrationToken
|
#include <EventToken.h> // EventRegistrationToken
|
||||||
@ -44,7 +45,6 @@ namespace ABI {
|
|||||||
namespace UI {
|
namespace UI {
|
||||||
namespace Core {
|
namespace Core {
|
||||||
struct ICoreWindow;
|
struct ICoreWindow;
|
||||||
struct ICoreDispatcher;
|
|
||||||
struct IAcceleratorKeyEventArgs;
|
struct IAcceleratorKeyEventArgs;
|
||||||
struct IKeyEventArgs;
|
struct IKeyEventArgs;
|
||||||
struct IPointerEventArgs;
|
struct IPointerEventArgs;
|
||||||
@ -84,7 +84,6 @@ private:
|
|||||||
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
||||||
typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \
|
typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \
|
||||||
IAcceleratorKeyEventArgs;
|
IAcceleratorKeyEventArgs;
|
||||||
typedef ABI::Windows::UI::Core::ICoreDispatcher ICoreDispatcher;
|
|
||||||
typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
|
typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
|
||||||
typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
|
typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
|
||||||
|
|
||||||
@ -105,8 +104,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MetroInput(MetroWidget* aWidget,
|
MetroInput(MetroWidget* aWidget,
|
||||||
ICoreWindow* aWindow,
|
ICoreWindow* aWindow);
|
||||||
ICoreDispatcher* aDispatcher);
|
|
||||||
virtual ~MetroInput();
|
virtual ~MetroInput();
|
||||||
|
|
||||||
// These input events are received from our window. These are basic
|
// These input events are received from our window. These are basic
|
||||||
@ -157,7 +155,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||||
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
||||||
Microsoft::WRL::ComPtr<ICoreDispatcher> mDispatcher;
|
|
||||||
Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
|
Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
|
||||||
|
|
||||||
ModifierKeyState mModifierKeyState;
|
ModifierKeyState mModifierKeyState;
|
||||||
@ -168,16 +165,13 @@ private:
|
|||||||
|
|
||||||
// Event processing helpers. See function definitions for more info.
|
// Event processing helpers. See function definitions for more info.
|
||||||
void OnPointerNonTouch(IPointerPoint* aPoint);
|
void OnPointerNonTouch(IPointerPoint* aPoint);
|
||||||
void InitGeckoMouseEventFromPointerPoint(nsMouseEvent& aEvent,
|
void InitGeckoMouseEventFromPointerPoint(nsMouseEvent* aEvent,
|
||||||
IPointerPoint* aPoint);
|
IPointerPoint* aPoint);
|
||||||
void ProcessManipulationDelta(ManipulationDelta const& aDelta,
|
void ProcessManipulationDelta(ManipulationDelta const& aDelta,
|
||||||
Point const& aPosition,
|
Point const& aPosition,
|
||||||
uint32_t aMagEventType,
|
uint32_t aMagEventType,
|
||||||
uint32_t aRotEventType);
|
uint32_t aRotEventType);
|
||||||
|
|
||||||
void DispatchEventIgnoreStatus(nsGUIEvent *aEvent);
|
|
||||||
static nsEventStatus sThrowawayStatus;
|
|
||||||
|
|
||||||
// The W3C spec states that "whether preventDefault has been called" should
|
// The W3C spec states that "whether preventDefault has been called" should
|
||||||
// be tracked on a per-touchpoint basis, but it also states that touchstart
|
// be tracked on a per-touchpoint basis, but it also states that touchstart
|
||||||
// and touchmove events can contain multiple changed points. At the time of
|
// and touchmove events can contain multiple changed points. At the time of
|
||||||
@ -224,10 +218,7 @@ private:
|
|||||||
// the updated touchpoint info and record the fact that the touchpoint
|
// the updated touchpoint info and record the fact that the touchpoint
|
||||||
// has changed. If ever we try to update a touchpoint has already
|
// has changed. If ever we try to update a touchpoint has already
|
||||||
// changed, we dispatch a touch event containing all the changed touches.
|
// changed, we dispatch a touch event containing all the changed touches.
|
||||||
nsEventStatus mTouchEventStatus;
|
void InitTouchEventTouchList(nsTouchEvent* aEvent);
|
||||||
nsTouchEvent mTouchEvent;
|
|
||||||
void DispatchPendingTouchEvent(bool aDispatchToAPZC);
|
|
||||||
void DispatchPendingTouchEvent(nsEventStatus& status, bool aDispatchToAPZC);
|
|
||||||
nsBaseHashtable<nsUint32HashKey,
|
nsBaseHashtable<nsUint32HashKey,
|
||||||
nsRefPtr<mozilla::dom::Touch>,
|
nsRefPtr<mozilla::dom::Touch>,
|
||||||
nsRefPtr<mozilla::dom::Touch> > mTouches;
|
nsRefPtr<mozilla::dom::Touch> > mTouches;
|
||||||
@ -257,6 +248,34 @@ private:
|
|||||||
EventRegistrationToken mTokenManipulationCompleted;
|
EventRegistrationToken mTokenManipulationCompleted;
|
||||||
EventRegistrationToken mTokenTapped;
|
EventRegistrationToken mTokenTapped;
|
||||||
EventRegistrationToken mTokenRightTapped;
|
EventRegistrationToken mTokenRightTapped;
|
||||||
|
|
||||||
|
// Due to a limitation added in 8.1 the ui thread can't re-enter the main
|
||||||
|
// native event dispatcher in MetroAppShell. So all events delivered to us
|
||||||
|
// on the ui thread via a native event dispatch call get bounced through
|
||||||
|
// the gecko thread event queue using runnables. Most events can be sent
|
||||||
|
// async without the need to see the status result. Those that do have
|
||||||
|
// specialty callbacks. Note any event that arrives to us on the ui thread
|
||||||
|
// that originates from another thread is safe to send sync.
|
||||||
|
|
||||||
|
// Async event dispatching
|
||||||
|
void DispatchAsyncEventIgnoreStatus(nsInputEvent* aEvent);
|
||||||
|
void DispatchAsyncTouchEventIgnoreStatus(nsTouchEvent* aEvent);
|
||||||
|
void DispatchAsyncTouchEventWithCallback(nsTouchEvent* aEvent, void (MetroInput::*Callback)());
|
||||||
|
|
||||||
|
// Async event callbacks
|
||||||
|
void DeliverNextQueuedEventIgnoreStatus();
|
||||||
|
nsEventStatus DeliverNextQueuedEvent();
|
||||||
|
nsEventStatus DeliverNextQueuedTouchEvent();
|
||||||
|
|
||||||
|
// Misc. specialty async callbacks
|
||||||
|
void OnPointerPressedCallback();
|
||||||
|
void OnFirstPointerMoveCallback();
|
||||||
|
|
||||||
|
// Sync event dispatching
|
||||||
|
void DispatchEventIgnoreStatus(nsGUIEvent *aEvent);
|
||||||
|
|
||||||
|
nsDeque mInputEventQueue;
|
||||||
|
static nsEventStatus sThrowawayStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
} } }
|
} } }
|
||||||
|
@ -562,6 +562,124 @@ CloseGesture()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Async event sending for mouse and keyboard input.
|
||||||
|
|
||||||
|
// Simple Windows message wrapper for dispatching async events.
|
||||||
|
class DispatchMsg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam) :
|
||||||
|
mMsg(aMsg),
|
||||||
|
mWParam(aWParam),
|
||||||
|
mLParam(aLParam)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~DispatchMsg()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT mMsg;
|
||||||
|
WPARAM mWParam;
|
||||||
|
LPARAM mLParam;
|
||||||
|
};
|
||||||
|
|
||||||
|
DispatchMsg*
|
||||||
|
MetroWidget::CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
||||||
|
{
|
||||||
|
switch (aMsg) {
|
||||||
|
case WM_SETTINGCHANGE:
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
case WM_HSCROLL:
|
||||||
|
case WM_VSCROLL:
|
||||||
|
case MOZ_WM_HSCROLL:
|
||||||
|
case MOZ_WM_VSCROLL:
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
// MOZ_WM events are plugin specific, we keep them for completness
|
||||||
|
case MOZ_WM_MOUSEVWHEEL:
|
||||||
|
case MOZ_WM_MOUSEHWHEEL:
|
||||||
|
return new DispatchMsg(aMsg, aWParam, aLParam);
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unknown event being passed to CreateDispatchMsg.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroWidget::DispatchAsyncScrollEvent(DispatchMsg* aEvent)
|
||||||
|
{
|
||||||
|
mMsgEventQueue.Push(aEvent);
|
||||||
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
|
NS_NewRunnableMethod(this, &MetroWidget::DeliverNextScrollEvent);
|
||||||
|
NS_DispatchToCurrentThread(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroWidget::DeliverNextScrollEvent()
|
||||||
|
{
|
||||||
|
DispatchMsg* msg = static_cast<DispatchMsg*>(mMsgEventQueue.PopFront());
|
||||||
|
MOZ_ASSERT(msg);
|
||||||
|
MSGResult msgResult;
|
||||||
|
MouseScrollHandler::ProcessMessage(this, msg->mMsg, msg->mWParam, msg->mLParam, msgResult);
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// defined in nsWiondowBase, called from shared module KeyboardLayout.
|
||||||
|
bool
|
||||||
|
MetroWidget::DispatchKeyboardEvent(nsGUIEvent* aEvent)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aEvent);
|
||||||
|
nsKeyEvent* oldKeyEvent = static_cast<nsKeyEvent*>(aEvent);
|
||||||
|
nsKeyEvent* keyEvent =
|
||||||
|
new nsKeyEvent(oldKeyEvent->mFlags.mIsTrusted, oldKeyEvent->message, oldKeyEvent->widget);
|
||||||
|
// XXX note this leaves pluginEvent null, which is fine for now.
|
||||||
|
keyEvent->AssignKeyEventData(*oldKeyEvent, true);
|
||||||
|
mKeyEventQueue.Push(keyEvent);
|
||||||
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
|
NS_NewRunnableMethod(this, &MetroWidget::DeliverNextKeyboardEvent);
|
||||||
|
NS_DispatchToCurrentThread(runnable);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used in conjunction with mKeyEventQueue to find a keypress event
|
||||||
|
// that should not be delivered due to the return result of the
|
||||||
|
// preceeding keydown.
|
||||||
|
class KeyQueryIdAndCancel : public nsDequeFunctor {
|
||||||
|
public:
|
||||||
|
KeyQueryIdAndCancel(uint32_t aIdToCancel) :
|
||||||
|
mId(aIdToCancel) {
|
||||||
|
}
|
||||||
|
virtual void* operator() (void* aObject) {
|
||||||
|
nsKeyEvent* event = static_cast<nsKeyEvent*>(aObject);
|
||||||
|
if (event->mUniqueId == mId) {
|
||||||
|
event->mFlags.mPropagationStopped = true;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
uint32_t mId;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
MetroWidget::DeliverNextKeyboardEvent()
|
||||||
|
{
|
||||||
|
nsKeyEvent* event = static_cast<nsKeyEvent*>(mKeyEventQueue.PopFront());
|
||||||
|
if (event->mFlags.mPropagationStopped) {
|
||||||
|
// This can happen if a keypress was previously cancelled.
|
||||||
|
delete event;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DispatchWindowEvent(event) && event->message == NS_KEY_DOWN) {
|
||||||
|
// keydown events may be followed by multiple keypress events which
|
||||||
|
// shouldn't be sent if preventDefault is called on keydown.
|
||||||
|
KeyQueryIdAndCancel query(event->mUniqueId);
|
||||||
|
mKeyEventQueue.ForEach(query);
|
||||||
|
}
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
LRESULT CALLBACK
|
LRESULT CALLBACK
|
||||||
MetroWidget::StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
MetroWidget::StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
||||||
@ -589,10 +707,14 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
|||||||
// The result returned if we do not do default processing.
|
// The result returned if we do not do default processing.
|
||||||
LRESULT processResult = 0;
|
LRESULT processResult = 0;
|
||||||
|
|
||||||
MSGResult msgResult(&processResult);
|
// We ignore return results from the scroll module and pass everything
|
||||||
MouseScrollHandler::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult);
|
// to mMetroWndProc. These fall through to winrt handlers that generate
|
||||||
if (msgResult.mConsumed) {
|
// input events in MetroInput. Since we have no listeners for scroll
|
||||||
return processResult;
|
// events no processing should occur. For now processDefault must be left
|
||||||
|
// true since the mouse module consumes non-mouse wheel related events.
|
||||||
|
if (MouseScrollHandler::NeedsMessage(aMsg)) {
|
||||||
|
DispatchMsg* msg = CreateDispatchMsg(aMsg, aWParam, aLParam);
|
||||||
|
DispatchAsyncScrollEvent(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (aMsg) {
|
switch (aMsg) {
|
||||||
@ -604,7 +726,7 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
|||||||
DeleteObject(rgn);
|
DeleteObject(rgn);
|
||||||
if (region.IsEmpty())
|
if (region.IsEmpty())
|
||||||
break;
|
break;
|
||||||
mView->Render(region);
|
Paint(region);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,6 +746,9 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keyboard handling is passed to KeyboardLayout, which delivers gecko events
|
||||||
|
// via DispatchKeyboardEvent.
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
case WM_SYSKEYDOWN:
|
case WM_SYSKEYDOWN:
|
||||||
{
|
{
|
||||||
@ -983,6 +1108,8 @@ MetroWidget::GetPaintListener()
|
|||||||
|
|
||||||
void MetroWidget::Paint(const nsIntRegion& aInvalidRegion)
|
void MetroWidget::Paint(const nsIntRegion& aInvalidRegion)
|
||||||
{
|
{
|
||||||
|
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
|
||||||
|
|
||||||
nsIWidgetListener* listener = GetPaintListener();
|
nsIWidgetListener* listener = GetPaintListener();
|
||||||
if (!listener)
|
if (!listener)
|
||||||
return;
|
return;
|
||||||
|
@ -45,6 +45,8 @@ class FrameworkView;
|
|||||||
|
|
||||||
} } }
|
} } }
|
||||||
|
|
||||||
|
class DispatchMsg;
|
||||||
|
|
||||||
class MetroWidget : public nsWindowBase,
|
class MetroWidget : public nsWindowBase,
|
||||||
public mozilla::layers::GeckoContentController,
|
public mozilla::layers::GeckoContentController,
|
||||||
public nsIObserver
|
public nsIObserver
|
||||||
@ -73,6 +75,8 @@ public:
|
|||||||
|
|
||||||
// nsWindowBase
|
// nsWindowBase
|
||||||
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||||
|
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||||
|
virtual bool DispatchPluginEvent(const MSG &aMsg) MOZ_OVERRIDE { return false; }
|
||||||
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return true; }
|
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return true; }
|
||||||
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE { return nullptr; }
|
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE { return nullptr; }
|
||||||
// InitEvent assumes physical coordinates and is used by shared win32 code. Do
|
// InitEvent assumes physical coordinates and is used by shared win32 code. Do
|
||||||
@ -248,6 +252,15 @@ protected:
|
|||||||
mozilla::layers::FrameMetrics mFrameMetrics;
|
mozilla::layers::FrameMetrics mFrameMetrics;
|
||||||
uint64_t mRootLayerTreeId;
|
uint64_t mRootLayerTreeId;
|
||||||
|
|
||||||
|
// Async event dispatching
|
||||||
|
void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
|
||||||
|
void DeliverNextScrollEvent();
|
||||||
|
void DeliverNextKeyboardEvent();
|
||||||
|
DispatchMsg* CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
|
||||||
|
|
||||||
|
nsDeque mMsgEventQueue;
|
||||||
|
nsDeque mKeyEventQueue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@ MODULE = 'widget'
|
|||||||
|
|
||||||
CPP_SOURCES += [
|
CPP_SOURCES += [
|
||||||
'FrameworkView.cpp',
|
'FrameworkView.cpp',
|
||||||
'FrameworkViewGfx.cpp',
|
|
||||||
'MetroApp.cpp',
|
'MetroApp.cpp',
|
||||||
'MetroAppShell.cpp',
|
'MetroAppShell.cpp',
|
||||||
'MetroContracts.cpp',
|
'MetroContracts.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user