зеркало из https://github.com/mozilla/gecko-dev.git
merge m-c to devtools
This commit is contained in:
Коммит
9063436548
|
@ -26,6 +26,28 @@
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Viewer</string>
|
<string>Viewer</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>svg</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>image/svg+xml</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>SVG document</string>
|
||||||
|
<key>CFBundleTypeOSTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>TEXT</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>NSDocumentClass</key>
|
||||||
|
<string>BrowserDocument</string>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeExtensions</key>
|
<key>CFBundleTypeExtensions</key>
|
||||||
<array>
|
<array>
|
||||||
|
|
|
@ -946,6 +946,7 @@ pref("toolbar.customization.usesheet", false);
|
||||||
pref("dom.ipc.plugins.enabled.i386", false);
|
pref("dom.ipc.plugins.enabled.i386", false);
|
||||||
pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
|
pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
|
||||||
pref("dom.ipc.plugins.enabled.i386.javaplugin2_npapi.plugin", true);
|
pref("dom.ipc.plugins.enabled.i386.javaplugin2_npapi.plugin", true);
|
||||||
|
pref("dom.ipc.plugins.enabled.i386.javaappletplugin.plugin", true);
|
||||||
// x86_64 ipc preferences
|
// x86_64 ipc preferences
|
||||||
pref("dom.ipc.plugins.enabled.x86_64", true);
|
pref("dom.ipc.plugins.enabled.x86_64", true);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -134,13 +134,16 @@
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#channelSelectorStart {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#channelMenulist {
|
#channelMenulist {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-description {
|
.channel-description {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#detailsBox,
|
#detailsBox,
|
||||||
|
|
|
@ -127,8 +127,8 @@
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
||||||
<vbox id="channelSelector">
|
<vbox id="channelSelector">
|
||||||
<hbox pack="center" align="center">
|
<hbox pack="start" align="center">
|
||||||
<label>&channel.selector.start;</label>
|
<label id="channelSelectorStart">&channel.selector.start;</label>
|
||||||
<menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);">
|
<menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);">
|
||||||
<menupopup>
|
<menupopup>
|
||||||
<menuitem id="releaseMenuitem" label="Release" value="release"/>
|
<menuitem id="releaseMenuitem" label="Release" value="release"/>
|
||||||
|
@ -146,9 +146,14 @@
|
||||||
<description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
|
<description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
|
||||||
</deck>
|
</deck>
|
||||||
|
|
||||||
<hbox id="channelSelectorButtons" pack="center">
|
<hbox id="channelSelectorButtons" pack="end">
|
||||||
|
#ifdef XP_UNIX
|
||||||
|
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
|
||||||
|
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
|
||||||
|
#else
|
||||||
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
|
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
|
||||||
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
|
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
|
||||||
|
#endif
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
</deck>
|
</deck>
|
||||||
|
|
|
@ -2860,17 +2860,22 @@ SessionStoreService.prototype = {
|
||||||
|
|
||||||
// Attach data that will be restored on "load" event, after tab is restored.
|
// Attach data that will be restored on "load" event, after tab is restored.
|
||||||
if (activeIndex > -1) {
|
if (activeIndex > -1) {
|
||||||
|
let curSHEntry = browser.webNavigation.sessionHistory.
|
||||||
|
getEntryAtIndex(activeIndex, false).
|
||||||
|
QueryInterface(Ci.nsISHEntry);
|
||||||
|
|
||||||
// restore those aspects of the currently active documents which are not
|
// restore those aspects of the currently active documents which are not
|
||||||
// preserved in the plain history entries (mainly scroll state and text data)
|
// preserved in the plain history entries (mainly scroll state and text data)
|
||||||
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
|
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
|
||||||
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
|
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
|
||||||
browser.__SS_restore_tab = aTab;
|
browser.__SS_restore_tab = aTab;
|
||||||
|
browser.__SS_restore_docIdentifier = curSHEntry.docIdentifier;
|
||||||
|
|
||||||
didStartLoad = true;
|
didStartLoad = true;
|
||||||
try {
|
try {
|
||||||
// In order to work around certain issues in session history, we need to
|
// In order to work around certain issues in session history, we need to
|
||||||
// force session history to update its internal index and call reload
|
// force session history to update its internal index and call reload
|
||||||
// instead of gotoIndex. c.f. bug 597315
|
// instead of gotoIndex. See bug 597315.
|
||||||
browser.webNavigation.sessionHistory.getEntryAtIndex(activeIndex, true);
|
browser.webNavigation.sessionHistory.getEntryAtIndex(activeIndex, true);
|
||||||
browser.webNavigation.sessionHistory.
|
browser.webNavigation.sessionHistory.
|
||||||
QueryInterface(Ci.nsISHistory_2_0_BRANCH).reloadCurrentEntry();
|
QueryInterface(Ci.nsISHistory_2_0_BRANCH).reloadCurrentEntry();
|
||||||
|
@ -3163,12 +3168,19 @@ SessionStoreService.prototype = {
|
||||||
aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";
|
aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aBrowser.__SS_restore_docIdentifier) {
|
||||||
|
let sh = aBrowser.webNavigation.sessionHistory;
|
||||||
|
sh.getEntryAtIndex(sh.index, false).QueryInterface(Ci.nsISHEntry).
|
||||||
|
docIdentifier = aBrowser.__SS_restore_docIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
// notify the tabbrowser that this document has been completely restored
|
// notify the tabbrowser that this document has been completely restored
|
||||||
this._sendTabRestoredNotification(aBrowser.__SS_restore_tab);
|
this._sendTabRestoredNotification(aBrowser.__SS_restore_tab);
|
||||||
|
|
||||||
delete aBrowser.__SS_restore_data;
|
delete aBrowser.__SS_restore_data;
|
||||||
delete aBrowser.__SS_restore_pageStyle;
|
delete aBrowser.__SS_restore_pageStyle;
|
||||||
delete aBrowser.__SS_restore_tab;
|
delete aBrowser.__SS_restore_tab;
|
||||||
|
delete aBrowser.__SS_restore_docIdentifier;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,11 +44,15 @@ function checkState(tab) {
|
||||||
|
|
||||||
let popStateCount = 0;
|
let popStateCount = 0;
|
||||||
|
|
||||||
let handler = function(aEvent) {
|
tab.linkedBrowser.addEventListener('popstate', function(aEvent) {
|
||||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||||
if (popStateCount == 0) {
|
if (popStateCount == 0) {
|
||||||
popStateCount++;
|
popStateCount++;
|
||||||
//ok(aEvent.state, "Event should have a state property.");
|
|
||||||
|
is(tab.linkedBrowser.contentWindow.testState, 'foo',
|
||||||
|
'testState after going back');
|
||||||
|
|
||||||
|
ok(aEvent.state, "Event should have a state property.");
|
||||||
is(JSON.stringify(tab.linkedBrowser.contentWindow.history.state), JSON.stringify({obj1:1}),
|
is(JSON.stringify(tab.linkedBrowser.contentWindow.history.state), JSON.stringify({obj1:1}),
|
||||||
"first popstate object.");
|
"first popstate object.");
|
||||||
|
|
||||||
|
@ -78,15 +82,16 @@ function checkState(tab) {
|
||||||
|
|
||||||
// Clean up after ourselves and finish the test.
|
// Clean up after ourselves and finish the test.
|
||||||
tab.linkedBrowser.removeEventListener("popstate", arguments.callee, true);
|
tab.linkedBrowser.removeEventListener("popstate", arguments.callee, true);
|
||||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
};
|
}, true);
|
||||||
|
|
||||||
tab.linkedBrowser.addEventListener("load", handler, true);
|
// Set some state in the page's window. When we go back(), the page should
|
||||||
tab.linkedBrowser.addEventListener("popstate", handler, true);
|
// be retrieved from bfcache, and this state should still be there.
|
||||||
|
tab.linkedBrowser.contentWindow.testState = 'foo';
|
||||||
|
|
||||||
|
// Now go back. This should trigger the popstate event handler above.
|
||||||
tab.linkedBrowser.contentWindow.history.back();
|
tab.linkedBrowser.contentWindow.history.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,20 +124,24 @@ function test() {
|
||||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||||
let history = contentWindow.history;
|
let history = contentWindow.history;
|
||||||
history.pushState({obj1:1}, "title-obj1");
|
history.pushState({obj1:1}, "title-obj1");
|
||||||
history.pushState({obj2:2}, "title-obj2", "?foo");
|
history.pushState({obj2:2}, "title-obj2", "page2");
|
||||||
history.replaceState({obj3:3}, "title-obj3");
|
history.replaceState({obj3:3}, "title-obj3");
|
||||||
|
|
||||||
let state = ss.getTabState(tab);
|
let state = ss.getTabState(tab);
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
|
||||||
// In order to make sure that setWindowState actually modifies the
|
// Restore the state into a new tab. Things don't work well when we
|
||||||
// window's state, we modify the state here. checkState will fail if
|
// restore into the old tab, but that's not a real use case anyway.
|
||||||
// this change isn't overwritten by setWindowState.
|
let tab2 = gBrowser.addTab("about:blank");
|
||||||
history.replaceState({should_be_overwritten:true}, "title-overwritten");
|
ss.setTabState(tab2, state, true);
|
||||||
|
|
||||||
// Restore the state and make sure it looks right, after giving the event
|
// Run checkState() once the tab finishes loading its restored state.
|
||||||
// loop a chance to flush.
|
tab2.linkedBrowser.addEventListener("load", function() {
|
||||||
ss.setTabState(tab, state, true);
|
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||||
executeSoon(function() { checkState(tab); });
|
SimpleTest.executeSoon(function() {
|
||||||
|
checkState(tab2);
|
||||||
|
});
|
||||||
|
}, true);
|
||||||
|
|
||||||
}, true);
|
}, true);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
|
@ -61,7 +61,6 @@ namespace std {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std __attribute__((visibility("default"))) {
|
namespace std __attribute__((visibility("default"))) {
|
||||||
|
|
||||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)
|
||||||
/* Hack to avoid GLIBCXX_3.4.14 symbol versions */
|
/* Hack to avoid GLIBCXX_3.4.14 symbol versions */
|
||||||
struct _List_node_base
|
struct _List_node_base
|
||||||
|
@ -73,35 +72,61 @@ namespace std __attribute__((visibility("default"))) {
|
||||||
void transfer(_List_node_base * const __first,
|
void transfer(_List_node_base * const __first,
|
||||||
_List_node_base * const __last) throw();
|
_List_node_base * const __last) throw();
|
||||||
|
|
||||||
|
/* Hack to avoid GLIBCXX_3.4.15 symbol versions */
|
||||||
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)
|
||||||
|
static void swap(_List_node_base& __x, _List_node_base& __y) throw ();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace __detail {
|
||||||
|
|
||||||
|
struct _List_node_base
|
||||||
|
{
|
||||||
|
#endif
|
||||||
void _M_hook(_List_node_base * const __position) throw ();
|
void _M_hook(_List_node_base * const __position) throw ();
|
||||||
|
|
||||||
void _M_unhook() throw ();
|
void _M_unhook() throw ();
|
||||||
|
|
||||||
void _M_transfer(_List_node_base * const __first,
|
void _M_transfer(_List_node_base * const __first,
|
||||||
_List_node_base * const __last) throw();
|
_List_node_base * const __last) throw();
|
||||||
|
|
||||||
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)
|
||||||
|
static void swap(_List_node_base& __x, _List_node_base& __y) throw ();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The functions actually have the same implementation */
|
/* The functions actually have the same implementation */
|
||||||
void
|
void
|
||||||
_List_node_base::_M_hook(_List_node_base * const __position) throw ()
|
_List_node_base::_M_hook(_List_node_base * const __position) throw ()
|
||||||
{
|
{
|
||||||
hook(__position);
|
((std::_List_node_base *)this)->hook((std::_List_node_base * const) __position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_List_node_base::_M_unhook() throw ()
|
_List_node_base::_M_unhook() throw ()
|
||||||
{
|
{
|
||||||
unhook();
|
((std::_List_node_base *)this)->unhook();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_List_node_base::_M_transfer(_List_node_base * const __first,
|
_List_node_base::_M_transfer(_List_node_base * const __first,
|
||||||
_List_node_base * const __last) throw ()
|
_List_node_base * const __last) throw ()
|
||||||
{
|
{
|
||||||
transfer(__first, __last);
|
((std::_List_node_base *)this)->transfer((std::_List_node_base * const)__first,
|
||||||
|
(std::_List_node_base * const)__last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)
|
||||||
|
void
|
||||||
|
_List_node_base::swap(_List_node_base& __x, _List_node_base& __y) throw ()
|
||||||
|
{
|
||||||
|
std::_List_node_base::swap(*((std::_List_node_base *) &__x),
|
||||||
|
*((std::_List_node_base *) &__y));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* (__GNUC__ == 4) && (__GNUC_MINOR__ >= 5) */
|
||||||
|
|
||||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)
|
||||||
/* Hack to avoid GLIBCXX_3.4.11 symbol versions
|
/* Hack to avoid GLIBCXX_3.4.11 symbol versions
|
||||||
An inline definition of ctype<char>::_M_widen_init() used to be in
|
An inline definition of ctype<char>::_M_widen_init() used to be in
|
||||||
|
|
|
@ -707,6 +707,8 @@ ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
|
||||||
|
|
||||||
JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
|
JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
|
||||||
|
|
||||||
|
MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
|
||||||
|
|
||||||
# We only want to do the pymake sanity on Windows, other os's can cope
|
# We only want to do the pymake sanity on Windows, other os's can cope
|
||||||
ifeq ($(HOST_OS_ARCH),WINNT)
|
ifeq ($(HOST_OS_ARCH),WINNT)
|
||||||
# Ensure invariants between GNU Make and pymake
|
# Ensure invariants between GNU Make and pymake
|
||||||
|
|
|
@ -82,11 +82,7 @@ else
|
||||||
ELOG :=
|
ELOG :=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),WINNT)
|
|
||||||
_VPATH_SRCS = $(abspath $<)
|
_VPATH_SRCS = $(abspath $<)
|
||||||
else
|
|
||||||
_VPATH_SRCS = $<
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
|
# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
|
||||||
VPATH += $(DIST)/lib
|
VPATH += $(DIST)/lib
|
||||||
|
|
14
configure.in
14
configure.in
|
@ -2456,7 +2456,11 @@ ia64*-hpux*)
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*-openbsd*)
|
*-openbsd*)
|
||||||
DLL_SUFFIX='.so.$(if $(SO_VERSION),$(SO_VERSION),1.0)'
|
if test "$SO_VERSION"; then
|
||||||
|
DLL_SUFFIX=".so.$SO_VERSION"
|
||||||
|
else
|
||||||
|
DLL_SUFFIX=".so.1.0"
|
||||||
|
fi
|
||||||
MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib -Wl,-rpath-link,$(if $(X11BASE),$(X11BASE),/usr/X11R6)/lib'
|
MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib -Wl,-rpath-link,$(if $(X11BASE),$(X11BASE),/usr/X11R6)/lib'
|
||||||
DSO_CFLAGS=''
|
DSO_CFLAGS=''
|
||||||
DSO_PIC_CFLAGS='-fPIC'
|
DSO_PIC_CFLAGS='-fPIC'
|
||||||
|
@ -5019,6 +5023,7 @@ cairo-windows)
|
||||||
MOZ_WIDGET_TOOLKIT=windows
|
MOZ_WIDGET_TOOLKIT=windows
|
||||||
MOZ_WEBGL=1
|
MOZ_WEBGL=1
|
||||||
MOZ_PDF_PRINTING=1
|
MOZ_PDF_PRINTING=1
|
||||||
|
MOZ_INSTRUMENT_EVENT_LOOP=1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
cairo-gtk2|cairo-gtk2-x11)
|
cairo-gtk2|cairo-gtk2-x11)
|
||||||
|
@ -5036,6 +5041,7 @@ cairo-gtk2|cairo-gtk2-x11)
|
||||||
TK_LIBS='$(MOZ_GTK2_LIBS)'
|
TK_LIBS='$(MOZ_GTK2_LIBS)'
|
||||||
AC_DEFINE(MOZ_WIDGET_GTK2)
|
AC_DEFINE(MOZ_WIDGET_GTK2)
|
||||||
MOZ_PDF_PRINTING=1
|
MOZ_PDF_PRINTING=1
|
||||||
|
MOZ_INSTRUMENT_EVENT_LOOP=1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
cairo-gtk2-dfb)
|
cairo-gtk2-dfb)
|
||||||
|
@ -5095,6 +5101,7 @@ cairo-cocoa)
|
||||||
LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
|
LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
|
||||||
MOZ_FS_LAYOUT=bundle
|
MOZ_FS_LAYOUT=bundle
|
||||||
MOZ_WEBGL=1
|
MOZ_WEBGL=1
|
||||||
|
MOZ_INSTRUMENT_EVENT_LOOP=1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
cairo-android)
|
cairo-android)
|
||||||
|
@ -5118,6 +5125,10 @@ if test "$MOZ_ENABLE_XREMOTE"; then
|
||||||
AC_DEFINE(MOZ_ENABLE_XREMOTE)
|
AC_DEFINE(MOZ_ENABLE_XREMOTE)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
|
||||||
|
AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$COMPILE_ENVIRONMENT"; then
|
if test "$COMPILE_ENVIRONMENT"; then
|
||||||
if test "$MOZ_ENABLE_GTK2"; then
|
if test "$MOZ_ENABLE_GTK2"; then
|
||||||
if test "$MOZ_X11"; then
|
if test "$MOZ_X11"; then
|
||||||
|
@ -8988,6 +8999,7 @@ AC_SUBST(VPX_AS_CONVERSION)
|
||||||
AC_SUBST(VPX_ASM_SUFFIX)
|
AC_SUBST(VPX_ASM_SUFFIX)
|
||||||
AC_SUBST(VPX_X86_ASM)
|
AC_SUBST(VPX_X86_ASM)
|
||||||
AC_SUBST(VPX_ARM_ASM)
|
AC_SUBST(VPX_ARM_ASM)
|
||||||
|
AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
|
||||||
AC_SUBST(LIBJPEG_TURBO_AS)
|
AC_SUBST(LIBJPEG_TURBO_AS)
|
||||||
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
||||||
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
||||||
|
|
|
@ -1414,6 +1414,14 @@ public:
|
||||||
*/
|
*/
|
||||||
static PRBool URIIsLocalFile(nsIURI *aURI);
|
static PRBool URIIsLocalFile(nsIURI *aURI);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a URI, return set beforeHash to the part before the '#', and
|
||||||
|
* afterHash to the remainder of the URI, including the '#'.
|
||||||
|
*/
|
||||||
|
static nsresult SplitURIAtHash(nsIURI *aURI,
|
||||||
|
nsACString &aBeforeHash,
|
||||||
|
nsACString &aAfterHash);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the application manifest URI for this document. The manifest URI
|
* Get the application manifest URI for this document. The manifest URI
|
||||||
* is specified in the manifest= attribute of the root element of the
|
* is specified in the manifest= attribute of the root element of the
|
||||||
|
|
|
@ -5012,6 +5012,32 @@ nsContentUtils::URIIsLocalFile(nsIURI *aURI)
|
||||||
isFile;
|
isFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsContentUtils::SplitURIAtHash(nsIURI *aURI,
|
||||||
|
nsACString &aBeforeHash,
|
||||||
|
nsACString &aAfterHash)
|
||||||
|
{
|
||||||
|
// See bug 225910 for why we can't do this using nsIURL.
|
||||||
|
|
||||||
|
aBeforeHash.Truncate();
|
||||||
|
aAfterHash.Truncate();
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aURI);
|
||||||
|
|
||||||
|
nsCAutoString spec;
|
||||||
|
nsresult rv = aURI->GetSpec(spec);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRInt32 index = spec.FindChar('#');
|
||||||
|
if (index == -1) {
|
||||||
|
index = spec.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
aBeforeHash.Assign(Substring(spec, 0, index));
|
||||||
|
aAfterHash.Assign(Substring(spec, index));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsIScriptContext*
|
nsIScriptContext*
|
||||||
nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
|
nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
|
||||||
|
|
|
@ -42,7 +42,7 @@ function testCancelInPhase4() {
|
||||||
testCancelBeforePhase4();
|
testCancelBeforePhase4();
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
xhr2.open("GET", url, false); // note : synch-request
|
xhr2.open("GET", url);
|
||||||
xhr2.setRequestHeader("X-Request", "1", false);
|
xhr2.setRequestHeader("X-Request", "1", false);
|
||||||
|
|
||||||
try { xhr2.send(); }
|
try { xhr2.send(); }
|
||||||
|
@ -87,7 +87,7 @@ function testCancelBeforePhase4() {
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
xhr2.open("GET", url, false); // note : synch-request
|
xhr2.open("GET", url);
|
||||||
xhr2.setRequestHeader("X-Request", "1", false);
|
xhr2.setRequestHeader("X-Request", "1", false);
|
||||||
|
|
||||||
try { xhr2.send(); }
|
try { xhr2.send(); }
|
||||||
|
|
|
@ -85,6 +85,7 @@ CPPSRCS = \
|
||||||
nsDOMScrollAreaEvent.cpp \
|
nsDOMScrollAreaEvent.cpp \
|
||||||
nsDOMTransitionEvent.cpp \
|
nsDOMTransitionEvent.cpp \
|
||||||
nsDOMPopStateEvent.cpp \
|
nsDOMPopStateEvent.cpp \
|
||||||
|
nsDOMHashChangeEvent.cpp \
|
||||||
nsDOMCloseEvent.cpp \
|
nsDOMCloseEvent.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsDOMHashChangeEvent.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(nsDOMHashChangeEvent, nsDOMEvent)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(nsDOMHashChangeEvent, nsDOMEvent)
|
||||||
|
|
||||||
|
DOMCI_DATA(HashChangeEvent, nsDOMHashChangeEvent)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsDOMHashChangeEvent)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMHashChangeEvent)
|
||||||
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HashChangeEvent)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||||
|
|
||||||
|
nsDOMHashChangeEvent::~nsDOMHashChangeEvent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMHashChangeEvent::GetOldURL(nsAString &aURL)
|
||||||
|
{
|
||||||
|
aURL.Assign(mOldURL);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMHashChangeEvent::GetNewURL(nsAString &aURL)
|
||||||
|
{
|
||||||
|
aURL.Assign(mNewURL);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMHashChangeEvent::InitHashChangeEvent(const nsAString &aTypeArg,
|
||||||
|
PRBool aCanBubbleArg,
|
||||||
|
PRBool aCancelableArg,
|
||||||
|
const nsAString &aOldURL,
|
||||||
|
const nsAString &aNewURL)
|
||||||
|
{
|
||||||
|
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
mOldURL.Assign(aOldURL);
|
||||||
|
mNewURL.Assign(aNewURL);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
|
nsEvent* aEvent)
|
||||||
|
{
|
||||||
|
nsDOMHashChangeEvent* event =
|
||||||
|
new nsDOMHashChangeEvent(aPresContext, aEvent);
|
||||||
|
|
||||||
|
return CallQueryInterface(event, aInstancePtrResult);
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsDOMHashChangeEvent_h__
|
||||||
|
#define nsDOMHashChangeEvent_h__
|
||||||
|
|
||||||
|
class nsEvent;
|
||||||
|
|
||||||
|
#include "nsIDOMHashChangeEvent.h"
|
||||||
|
#include "nsDOMEvent.h"
|
||||||
|
#include "nsIVariant.h"
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
|
||||||
|
class nsDOMHashChangeEvent : public nsDOMEvent,
|
||||||
|
public nsIDOMHashChangeEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsDOMHashChangeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||||
|
: nsDOMEvent(aPresContext, aEvent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~nsDOMHashChangeEvent();
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_NSIDOMHASHCHANGEEVENT
|
||||||
|
|
||||||
|
NS_FORWARD_TO_NSDOMEVENT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsString mOldURL;
|
||||||
|
nsString mNewURL;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
|
nsEvent* aEvent);
|
||||||
|
|
||||||
|
#endif // nsDOMHashChangeEvent_h__
|
|
@ -50,6 +50,7 @@
|
||||||
#include "nsINode.h"
|
#include "nsINode.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsDOMPopStateEvent.h"
|
#include "nsDOMPopStateEvent.h"
|
||||||
|
#include "nsDOMHashChangeEvent.h"
|
||||||
#include "nsFrameLoader.h"
|
#include "nsFrameLoader.h"
|
||||||
|
|
||||||
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
||||||
|
@ -871,6 +872,8 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
||||||
return NS_NewDOMAudioAvailableEvent(aDOMEvent, aPresContext, nsnull);
|
return NS_NewDOMAudioAvailableEvent(aDOMEvent, aPresContext, nsnull);
|
||||||
if (aEventType.LowerCaseEqualsLiteral("closeevent"))
|
if (aEventType.LowerCaseEqualsLiteral("closeevent"))
|
||||||
return NS_NewDOMCloseEvent(aDOMEvent, aPresContext, nsnull);
|
return NS_NewDOMCloseEvent(aDOMEvent, aPresContext, nsnull);
|
||||||
|
if (aEventType.LowerCaseEqualsLiteral("hashchangeevent"))
|
||||||
|
return NS_NewDOMHashChangeEvent(aDOMEvent, aPresContext, nsnull);
|
||||||
|
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,50 @@ SVGPathData::GetPathSegAtLength(float aDistance) const
|
||||||
return NS_MAX(0U, segIndex - 1); // -1 because while loop takes us 1 too far
|
return NS_MAX(0U, segIndex - 1); // -1 because while loop takes us 1 too far
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SVG spec says we have to paint stroke caps for zero length subpaths:
|
||||||
|
*
|
||||||
|
* http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
|
||||||
|
*
|
||||||
|
* Cairo only does this for |stroke-linecap: round| and not for
|
||||||
|
* |stroke-linecap: square| (since that's what Adobe Acrobat has always done).
|
||||||
|
*
|
||||||
|
* To help us conform to the SVG spec we have this helper function to draw an
|
||||||
|
* approximation of square caps for zero length subpaths. It does this by
|
||||||
|
* inserting a subpath containing a single axis aligned straight line that is
|
||||||
|
* as small as it can be without cairo throwing it away for being too small to
|
||||||
|
* affect rendering. Cairo will then draw stroke caps for this axis aligned
|
||||||
|
* line, creating an axis aligned rectangle (approximating the square that
|
||||||
|
* would ideally be drawn).
|
||||||
|
*
|
||||||
|
* Note that this function inserts a subpath into the current gfx path that
|
||||||
|
* will be present during both fill and stroke operations.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ApproximateZeroLengthSubpathSquareCaps(const gfxPoint &aPoint, gfxContext *aCtx)
|
||||||
|
{
|
||||||
|
// Cairo's fixed point fractional part is 8 bits wide, so its device space
|
||||||
|
// coordinate granularity is 1/256 pixels. However, to prevent user space
|
||||||
|
// |aPoint| and |aPoint + tinyAdvance| being rounded to the same device
|
||||||
|
// coordinates, we double this for |tinyAdvance|:
|
||||||
|
|
||||||
|
const gfxSize tinyAdvance = aCtx->DeviceToUser(gfxSize(2.0/256.0, 0.0));
|
||||||
|
|
||||||
|
aCtx->MoveTo(aPoint);
|
||||||
|
aCtx->LineTo(aPoint + gfxPoint(tinyAdvance.width, tinyAdvance.height));
|
||||||
|
aCtx->MoveTo(aPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS \
|
||||||
|
do { \
|
||||||
|
if (capsAreSquare && !subpathHasLength && subpathContainsNonArc && \
|
||||||
|
SVGPathSegUtils::IsValidType(prevSegType) && \
|
||||||
|
(!IsMoveto(prevSegType) || \
|
||||||
|
segType == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH)) { \
|
||||||
|
ApproximateZeroLengthSubpathSquareCaps(segStart, aCtx); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
void
|
void
|
||||||
SVGPathData::ConstructPath(gfxContext *aCtx) const
|
SVGPathData::ConstructPath(gfxContext *aCtx) const
|
||||||
{
|
{
|
||||||
|
@ -244,9 +288,14 @@ SVGPathData::ConstructPath(gfxContext *aCtx) const
|
||||||
return; // paths without an initial moveto are invalid
|
return; // paths without an initial moveto are invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool capsAreSquare = aCtx->CurrentLineCap() == gfxContext::LINE_CAP_SQUARE;
|
||||||
|
PRBool subpathHasLength = PR_FALSE; // visual length
|
||||||
|
PRBool subpathContainsNonArc = PR_FALSE;
|
||||||
|
|
||||||
PRUint32 segType, prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
|
PRUint32 segType, prevSegType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
|
||||||
gfxPoint pathStart(0.0, 0.0); // start point of [sub]path
|
gfxPoint pathStart(0.0, 0.0); // start point of [sub]path
|
||||||
gfxPoint segEnd(0.0, 0.0); // end point of previous/current segment
|
gfxPoint segStart(0.0, 0.0);
|
||||||
|
gfxPoint segEnd;
|
||||||
gfxPoint cp1, cp2; // previous bezier's control points
|
gfxPoint cp1, cp2; // previous bezier's control points
|
||||||
gfxPoint tcp1, tcp2; // temporaries
|
gfxPoint tcp1, tcp2; // temporaries
|
||||||
|
|
||||||
|
@ -257,36 +306,50 @@ SVGPathData::ConstructPath(gfxContext *aCtx) const
|
||||||
PRUint32 i = 0;
|
PRUint32 i = 0;
|
||||||
while (i < mData.Length()) {
|
while (i < mData.Length()) {
|
||||||
segType = SVGPathSegUtils::DecodeType(mData[i++]);
|
segType = SVGPathSegUtils::DecodeType(mData[i++]);
|
||||||
|
PRUint32 argCount = SVGPathSegUtils::ArgCountForType(segType);
|
||||||
|
|
||||||
switch (segType)
|
switch (segType)
|
||||||
{
|
{
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH:
|
case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH:
|
||||||
|
// set this early to allow drawing of square caps for "M{x},{y} Z":
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
|
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
|
||||||
segEnd = pathStart;
|
segEnd = pathStart;
|
||||||
aCtx->ClosePath();
|
aCtx->ClosePath();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
|
||||||
|
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
|
||||||
pathStart = segEnd = gfxPoint(mData[i], mData[i+1]);
|
pathStart = segEnd = gfxPoint(mData[i], mData[i+1]);
|
||||||
aCtx->MoveTo(segEnd);
|
aCtx->MoveTo(segEnd);
|
||||||
i += 2;
|
subpathHasLength = PR_FALSE;
|
||||||
|
subpathContainsNonArc = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
|
||||||
pathStart = segEnd += gfxPoint(mData[i], mData[i+1]);
|
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
|
||||||
|
pathStart = segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
|
||||||
aCtx->MoveTo(segEnd);
|
aCtx->MoveTo(segEnd);
|
||||||
i += 2;
|
subpathHasLength = PR_FALSE;
|
||||||
|
subpathContainsNonArc = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
|
||||||
segEnd = gfxPoint(mData[i], mData[i+1]);
|
segEnd = gfxPoint(mData[i], mData[i+1]);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
i += 2;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
|
||||||
segEnd += gfxPoint(mData[i], mData[i+1]);
|
segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
i += 2;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
|
||||||
|
@ -294,126 +357,170 @@ SVGPathData::ConstructPath(gfxContext *aCtx) const
|
||||||
cp2 = gfxPoint(mData[i+2], mData[i+3]);
|
cp2 = gfxPoint(mData[i+2], mData[i+3]);
|
||||||
segEnd = gfxPoint(mData[i+4], mData[i+5]);
|
segEnd = gfxPoint(mData[i+4], mData[i+5]);
|
||||||
aCtx->CurveTo(cp1, cp2, segEnd);
|
aCtx->CurveTo(cp1, cp2, segEnd);
|
||||||
i += 6;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
|
||||||
cp1 = segEnd + gfxPoint(mData[i], mData[i+1]);
|
cp1 = segStart + gfxPoint(mData[i], mData[i+1]);
|
||||||
cp2 = segEnd + gfxPoint(mData[i+2], mData[i+3]);
|
cp2 = segStart + gfxPoint(mData[i+2], mData[i+3]);
|
||||||
segEnd += gfxPoint(mData[i+4], mData[i+5]);
|
segEnd = segStart + gfxPoint(mData[i+4], mData[i+5]);
|
||||||
aCtx->CurveTo(cp1, cp2, segEnd);
|
aCtx->CurveTo(cp1, cp2, segEnd);
|
||||||
i += 6;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
|
||||||
cp1 = gfxPoint(mData[i], mData[i+1]);
|
cp1 = gfxPoint(mData[i], mData[i+1]);
|
||||||
// Convert quadratic curve to cubic curve:
|
// Convert quadratic curve to cubic curve:
|
||||||
tcp1 = segEnd + (cp1 - segEnd) * 2 / 3;
|
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
|
||||||
segEnd = gfxPoint(mData[i+2], mData[i+3]); // changed before setting tcp2!
|
segEnd = gfxPoint(mData[i+2], mData[i+3]); // set before setting tcp2!
|
||||||
tcp2 = cp1 + (segEnd - cp1) / 3;
|
tcp2 = cp1 + (segEnd - cp1) / 3;
|
||||||
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
||||||
i += 4;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
|
||||||
cp1 = segEnd + gfxPoint(mData[i], mData[i+1]);
|
cp1 = segStart + gfxPoint(mData[i], mData[i+1]);
|
||||||
// Convert quadratic curve to cubic curve:
|
// Convert quadratic curve to cubic curve:
|
||||||
tcp1 = segEnd + (cp1 - segEnd) * 2 / 3;
|
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
|
||||||
segEnd += gfxPoint(mData[i+2], mData[i+3]); // changed before setting tcp2!
|
segEnd = segStart + gfxPoint(mData[i+2], mData[i+3]); // set before setting tcp2!
|
||||||
tcp2 = cp1 + (segEnd - cp1) / 3;
|
tcp2 = cp1 + (segEnd - cp1) / 3;
|
||||||
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
||||||
i += 4;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
|
||||||
{
|
{
|
||||||
gfxPoint radii(mData[i], mData[i+1]);
|
gfxPoint radii(mData[i], mData[i+1]);
|
||||||
gfxPoint start = segEnd;
|
gfxPoint segEnd = gfxPoint(mData[i+5], mData[i+6]);
|
||||||
gfxPoint end = gfxPoint(mData[i+5], mData[i+6]);
|
|
||||||
if (segType == nsIDOMSVGPathSeg::PATHSEG_ARC_REL) {
|
if (segType == nsIDOMSVGPathSeg::PATHSEG_ARC_REL) {
|
||||||
end += start;
|
segEnd += segStart;
|
||||||
}
|
}
|
||||||
segEnd = end;
|
if (segEnd != segStart) {
|
||||||
if (start != end) {
|
|
||||||
if (radii.x == 0.0f || radii.y == 0.0f) {
|
if (radii.x == 0.0f || radii.y == 0.0f) {
|
||||||
aCtx->LineTo(end);
|
aCtx->LineTo(segEnd);
|
||||||
i += 7;
|
} else {
|
||||||
break;
|
nsSVGArcConverter converter(segStart, segEnd, radii, mData[i+2],
|
||||||
}
|
mData[i+3] != 0, mData[i+4] != 0);
|
||||||
nsSVGArcConverter converter(start, end, radii, mData[i+2],
|
while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) {
|
||||||
mData[i+3] != 0, mData[i+4] != 0);
|
aCtx->CurveTo(cp1, cp2, segEnd);
|
||||||
while (converter.GetNextSegment(&cp1, &cp2, &end)) {
|
}
|
||||||
aCtx->CurveTo(cp1, cp2, end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += 7;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
|
||||||
segEnd = gfxPoint(mData[i++], segEnd.y);
|
segEnd = gfxPoint(mData[i], segStart.y);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
|
||||||
segEnd += gfxPoint(mData[i++], 0.0f);
|
segEnd = segStart + gfxPoint(mData[i], 0.0f);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
|
||||||
segEnd = gfxPoint(segEnd.x, mData[i++]);
|
segEnd = gfxPoint(segStart.x, mData[i]);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
|
||||||
segEnd += gfxPoint(0.0f, mData[i++]);
|
segEnd = segStart + gfxPoint(0.0f, mData[i]);
|
||||||
aCtx->LineTo(segEnd);
|
aCtx->LineTo(segEnd);
|
||||||
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
|
||||||
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segEnd * 2 - cp2 : segEnd;
|
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
|
||||||
cp2 = gfxPoint(mData[i], mData[i+1]);
|
cp2 = gfxPoint(mData[i], mData[i+1]);
|
||||||
segEnd = gfxPoint(mData[i+2], mData[i+3]);
|
segEnd = gfxPoint(mData[i+2], mData[i+3]);
|
||||||
aCtx->CurveTo(cp1, cp2, segEnd);
|
aCtx->CurveTo(cp1, cp2, segEnd);
|
||||||
i += 4;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
|
||||||
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segEnd * 2 - cp2 : segEnd;
|
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
|
||||||
cp2 = segEnd + gfxPoint(mData[i], mData[i+1]);
|
cp2 = segStart + gfxPoint(mData[i], mData[i+1]);
|
||||||
segEnd += gfxPoint(mData[i+2], mData[i+3]);
|
segEnd = segStart + gfxPoint(mData[i+2], mData[i+3]);
|
||||||
aCtx->CurveTo(cp1, cp2, segEnd);
|
aCtx->CurveTo(cp1, cp2, segEnd);
|
||||||
i += 4;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
|
||||||
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segEnd * 2 - cp1 : segEnd;
|
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
|
||||||
// Convert quadratic curve to cubic curve:
|
// Convert quadratic curve to cubic curve:
|
||||||
tcp1 = segEnd + (cp1 - segEnd) * 2 / 3;
|
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
|
||||||
segEnd = gfxPoint(mData[i], mData[i+1]); // changed before setting tcp2!
|
segEnd = gfxPoint(mData[i], mData[i+1]); // set before setting tcp2!
|
||||||
tcp2 = cp1 + (segEnd - cp1) / 3;
|
tcp2 = cp1 + (segEnd - cp1) / 3;
|
||||||
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
||||||
i += 2;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
||||||
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segEnd * 2 - cp1 : segEnd;
|
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
|
||||||
// Convert quadratic curve to cubic curve:
|
// Convert quadratic curve to cubic curve:
|
||||||
tcp1 = segEnd + (cp1 - segEnd) * 2 / 3;
|
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
|
||||||
segEnd = segEnd + gfxPoint(mData[i], mData[i+1]); // changed before setting tcp2!
|
segEnd = segStart + gfxPoint(mData[i], mData[i+1]); // changed before setting tcp2!
|
||||||
tcp2 = cp1 + (segEnd - cp1) / 3;
|
tcp2 = cp1 + (segEnd - cp1) / 3;
|
||||||
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
aCtx->CurveTo(tcp1, tcp2, segEnd);
|
||||||
i += 2;
|
if (!subpathHasLength) {
|
||||||
|
subpathHasLength = (segEnd != segStart || segEnd != cp1);
|
||||||
|
}
|
||||||
|
subpathContainsNonArc = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NS_NOTREACHED("Bad path segment type");
|
NS_NOTREACHED("Bad path segment type");
|
||||||
return; // according to spec we'd use everything up to the bad seg anyway
|
return; // according to spec we'd use everything up to the bad seg anyway
|
||||||
}
|
}
|
||||||
|
i += argCount;
|
||||||
prevSegType = segType;
|
prevSegType = segType;
|
||||||
|
segStart = segEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
|
NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
|
||||||
|
|
||||||
|
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfxFlattenedPath>
|
already_AddRefed<gfxFlattenedPath>
|
||||||
|
|
|
@ -79,6 +79,7 @@ _TEST_FILES = \
|
||||||
test_SVGAnimatedImageSMILDisabled.html \
|
test_SVGAnimatedImageSMILDisabled.html \
|
||||||
animated-svg-image-helper.html \
|
animated-svg-image-helper.html \
|
||||||
animated-svg-image-helper.svg \
|
animated-svg-image-helper.svg \
|
||||||
|
test_stroke-linecap-hit-testing.xhtml \
|
||||||
test_SVGLengthList.xhtml \
|
test_SVGLengthList.xhtml \
|
||||||
test_SVGLengthList-2.xhtml \
|
test_SVGLengthList-2.xhtml \
|
||||||
test_SVGPathSegList.xhtml \
|
test_SVGPathSegList.xhtml \
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=589648
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test hit-testing of line caps</title>
|
||||||
|
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body onload="run()">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function run()
|
||||||
|
{
|
||||||
|
var svg = document.getElementById('svg');
|
||||||
|
var div = document.getElementById("div");
|
||||||
|
var x = div.offsetLeft;
|
||||||
|
var y = div.offsetTop;
|
||||||
|
var got, expected;
|
||||||
|
|
||||||
|
got = document.elementFromPoint(5 + x, 5 + y);
|
||||||
|
expected = document.getElementById('zero-length-square-caps');
|
||||||
|
is(got, expected, 'Check hit on zero length subpath\'s square caps');
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500174">Mozilla Bug 500174</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<div width="100%" height="1" id="div"></div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="svg" width="400" height="300">
|
||||||
|
<path id="zero-length-square-caps" stroke="blue" stroke-width="50"
|
||||||
|
stroke-linecap="square" d="M25,25 L25,25"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -215,6 +215,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nsPluginError.h"
|
#include "nsPluginError.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||||
|
@ -8215,33 +8216,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
mAllowKeywordFixup =
|
mAllowKeywordFixup =
|
||||||
(aFlags & INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) != 0;
|
(aFlags & INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) != 0;
|
||||||
mURIResultedInDocument = PR_FALSE; // reset the clock...
|
mURIResultedInDocument = PR_FALSE; // reset the clock...
|
||||||
|
|
||||||
//
|
|
||||||
// First:
|
|
||||||
// Check to see if the new URI is an anchor in the existing document.
|
|
||||||
// Skip this check if we're doing some sort of abnormal load, if the
|
|
||||||
// new load is a non-history load and has postdata, or if we're doing
|
|
||||||
// a history load and the page identifiers of mOSHE and aSHEntry
|
|
||||||
// don't match.
|
|
||||||
//
|
|
||||||
PRBool allowScroll = PR_TRUE;
|
|
||||||
if (!aSHEntry) {
|
|
||||||
allowScroll = (aPostData == nsnull);
|
|
||||||
} else if (mOSHE) {
|
|
||||||
PRUint32 ourPageIdent;
|
|
||||||
mOSHE->GetPageIdentifier(&ourPageIdent);
|
|
||||||
PRUint32 otherPageIdent;
|
|
||||||
aSHEntry->GetPageIdentifier(&otherPageIdent);
|
|
||||||
allowScroll = (ourPageIdent == otherPageIdent);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (allowScroll) {
|
|
||||||
nsCOMPtr<nsIInputStream> currentPostData;
|
|
||||||
mOSHE->GetPostData(getter_AddRefs(currentPostData));
|
|
||||||
NS_ASSERTION(currentPostData == aPostData,
|
|
||||||
"Different POST data for entries for the same page?");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aLoadType == LOAD_NORMAL ||
|
if (aLoadType == LOAD_NORMAL ||
|
||||||
aLoadType == LOAD_STOP_CONTENT ||
|
aLoadType == LOAD_STOP_CONTENT ||
|
||||||
|
@ -8249,40 +8223,81 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
aLoadType == LOAD_HISTORY ||
|
aLoadType == LOAD_HISTORY ||
|
||||||
aLoadType == LOAD_LINK) {
|
aLoadType == LOAD_LINK) {
|
||||||
|
|
||||||
PRBool wasAnchor = PR_FALSE;
|
// Split mCurrentURI and aURI on the '#' character. Make sure we read
|
||||||
PRBool doHashchange = PR_FALSE;
|
// the return values of SplitURIAtHash; it might fail because
|
||||||
|
// mCurrentURI is null, for instance, and we don't want to allow a
|
||||||
|
// short-circuited navigation in that case.
|
||||||
|
nsCAutoString curBeforeHash, curHash, newBeforeHash, newHash;
|
||||||
|
nsresult splitRv1, splitRv2;
|
||||||
|
splitRv1 = nsContentUtils::SplitURIAtHash(mCurrentURI, curBeforeHash, curHash);
|
||||||
|
splitRv2 = nsContentUtils::SplitURIAtHash(aURI, newBeforeHash, newHash);
|
||||||
|
|
||||||
// Get the position of the scrollers.
|
PRBool sameExceptHashes = NS_SUCCEEDED(splitRv1) &&
|
||||||
nscoord cx = 0, cy = 0;
|
NS_SUCCEEDED(splitRv2) &&
|
||||||
GetCurScrollPos(ScrollOrientation_X, &cx);
|
curBeforeHash.Equals(newBeforeHash);
|
||||||
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
|
||||||
|
|
||||||
if (allowScroll) {
|
|
||||||
NS_ENSURE_SUCCESS(ScrollIfAnchor(aURI, &wasAnchor, aLoadType,
|
|
||||||
&doHashchange),
|
|
||||||
NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a history load, aSHEntry will have document identifier X
|
|
||||||
// if it was created as a result of a History.pushState() from a
|
|
||||||
// SHEntry with doc ident X, or if it was created by changing the hash
|
|
||||||
// of the URI corresponding to a SHEntry with doc ident X.
|
|
||||||
PRBool sameDocIdent = PR_FALSE;
|
PRBool sameDocIdent = PR_FALSE;
|
||||||
if (mOSHE && aSHEntry) {
|
if (mOSHE && aSHEntry) {
|
||||||
PRUint64 ourDocIdent, otherDocIdent;
|
// We're doing a history load.
|
||||||
mOSHE->GetDocIdentifier(&ourDocIdent);
|
|
||||||
aSHEntry->GetDocIdentifier(&otherDocIdent);
|
PRUint64 ourDocIdent, otherDocIdent;
|
||||||
sameDocIdent = (ourDocIdent == otherDocIdent);
|
mOSHE->GetDocIdentifier(&ourDocIdent);
|
||||||
|
aSHEntry->GetDocIdentifier(&otherDocIdent);
|
||||||
|
sameDocIdent = (ourDocIdent == otherDocIdent);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (sameDocIdent) {
|
||||||
|
nsCOMPtr<nsIInputStream> currentPostData;
|
||||||
|
mOSHE->GetPostData(getter_AddRefs(currentPostData));
|
||||||
|
NS_ASSERTION(currentPostData == aPostData,
|
||||||
|
"Different POST data for entries for the same page?");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a short-circuited load if the new URI differs from the current
|
// A short-circuited load happens when we navigate between two SHEntries
|
||||||
// URI only in the hash, or if the two entries belong to the same
|
// for the same document. We do a short-circuited load under two
|
||||||
// document and don't point to the same object.
|
// circumstances. Either
|
||||||
//
|
//
|
||||||
// (If we didn't check that the SHEntries are different objects,
|
// a) we're navigating between two different SHEntries which have the
|
||||||
// history.go(0) would short-circuit instead of triggering a true
|
// same document identifiers, or
|
||||||
// load, and we wouldn't dispatch an onload event to the page.)
|
//
|
||||||
if (wasAnchor || (sameDocIdent && (mOSHE != aSHEntry))) {
|
// b) we're navigating to a new shentry whose URI differs from the
|
||||||
|
// current URI only in its hash, the new hash is non-empty, and
|
||||||
|
// we're not doing a POST.
|
||||||
|
//
|
||||||
|
// The restriction tha the SHEntries in (a) must be different ensures
|
||||||
|
// that history.go(0) and the like trigger full refreshes, rather than
|
||||||
|
// short-circuited loads.
|
||||||
|
PRBool doShortCircuitedLoad = (sameDocIdent && mOSHE != aSHEntry) ||
|
||||||
|
(!aSHEntry && aPostData == nsnull &&
|
||||||
|
sameExceptHashes && !newHash.IsEmpty());
|
||||||
|
|
||||||
|
// Fire a hashchange event if we're doing a short-circuited load and the
|
||||||
|
// URIs differ only in their hashes.
|
||||||
|
PRBool doHashchange = doShortCircuitedLoad &&
|
||||||
|
sameExceptHashes &&
|
||||||
|
!curHash.Equals(newHash);
|
||||||
|
|
||||||
|
if (doShortCircuitedLoad) {
|
||||||
|
// Save the current URI; we need it if we fire a hashchange later.
|
||||||
|
nsCOMPtr<nsIURI> oldURI = mCurrentURI;
|
||||||
|
|
||||||
|
// Save the position of the scrollers.
|
||||||
|
nscoord cx = 0, cy = 0;
|
||||||
|
GetCurScrollPos(ScrollOrientation_X, &cx);
|
||||||
|
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
||||||
|
|
||||||
|
// We scroll the window precisely when we fire a hashchange event.
|
||||||
|
if (doHashchange) {
|
||||||
|
// Take the '#' off the hashes before passing them to
|
||||||
|
// ScrollToAnchor.
|
||||||
|
nsDependentCSubstring curHashName(curHash, 1);
|
||||||
|
nsDependentCSubstring newHashName(newHash, 1);
|
||||||
|
rv = ScrollToAnchor(curHashName, newHashName, aLoadType);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
mLoadType = aLoadType;
|
mLoadType = aLoadType;
|
||||||
mURIResultedInDocument = PR_TRUE;
|
mURIResultedInDocument = PR_TRUE;
|
||||||
|
|
||||||
|
@ -8307,7 +8322,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
OnNewURI(aURI, nsnull, owner, mLoadType, PR_TRUE, PR_TRUE, PR_TRUE);
|
OnNewURI(aURI, nsnull, owner, mLoadType, PR_TRUE, PR_TRUE, PR_TRUE);
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> postData;
|
nsCOMPtr<nsIInputStream> postData;
|
||||||
PRUint32 pageIdent = PR_UINT32_MAX;
|
PRUint64 docIdent = PRUint64(-1);
|
||||||
nsCOMPtr<nsISupports> cacheKey;
|
nsCOMPtr<nsISupports> cacheKey;
|
||||||
|
|
||||||
if (mOSHE) {
|
if (mOSHE) {
|
||||||
|
@ -8321,20 +8336,9 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
// wouldn't want here.
|
// wouldn't want here.
|
||||||
if (aLoadType & LOAD_CMD_NORMAL) {
|
if (aLoadType & LOAD_CMD_NORMAL) {
|
||||||
mOSHE->GetPostData(getter_AddRefs(postData));
|
mOSHE->GetPostData(getter_AddRefs(postData));
|
||||||
mOSHE->GetPageIdentifier(&pageIdent);
|
mOSHE->GetDocIdentifier(&docIdent);
|
||||||
mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
|
mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLSHE && wasAnchor) {
|
|
||||||
// If it's an anchor load, set mLSHE's doc identifier to
|
|
||||||
// mOSHE's doc identifier -- These are the same documents,
|
|
||||||
// as far as HTML5 is concerned.
|
|
||||||
PRUint64 docIdent;
|
|
||||||
rv = mOSHE->GetDocIdentifier(&docIdent);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
mLSHE->SetDocIdentifier(docIdent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign mOSHE to mLSHE. This will either be a new entry created
|
/* Assign mOSHE to mLSHE. This will either be a new entry created
|
||||||
|
@ -8354,10 +8358,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
if (cacheKey)
|
if (cacheKey)
|
||||||
mOSHE->SetCacheKey(cacheKey);
|
mOSHE->SetCacheKey(cacheKey);
|
||||||
|
|
||||||
// Propagate our page ident to the new mOSHE so that
|
// Propagate our document identifier to the new mOSHE so that
|
||||||
// we'll know it just differed by a scroll on the page.
|
// we'll know it's related by an anchor navigation or pushState.
|
||||||
if (pageIdent != PR_UINT32_MAX)
|
if (docIdent != PRUint64(-1))
|
||||||
mOSHE->SetPageIdentifier(pageIdent);
|
mOSHE->SetDocIdentifier(docIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore previous position of scroller(s), if we're moving
|
/* restore previous position of scroller(s), if we're moving
|
||||||
|
@ -8425,8 +8429,11 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||||
window->DispatchSyncPopState();
|
window->DispatchSyncPopState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doHashchange)
|
if (doHashchange) {
|
||||||
window->DispatchAsyncHashchange();
|
// Make sure to use oldURI here, not mCurrentURI, because by
|
||||||
|
// now, mCurrentURI has changed!
|
||||||
|
window->DispatchAsyncHashchange(oldURI, aURI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -9052,20 +9059,9 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDocShell::ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
|
nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
|
||||||
PRUint32 aLoadType, PRBool * aDoHashchange)
|
PRUint32 aLoadType)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aURI, "null uri arg");
|
|
||||||
NS_ASSERTION(aWasAnchor, "null anchor arg");
|
|
||||||
NS_PRECONDITION(aDoHashchange, "null hashchange arg");
|
|
||||||
|
|
||||||
if (!aURI || !aWasAnchor) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aWasAnchor = PR_FALSE;
|
|
||||||
*aDoHashchange = PR_FALSE;
|
|
||||||
|
|
||||||
if (!mCurrentURI) {
|
if (!mCurrentURI) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -9075,116 +9071,28 @@ nsDocShell::ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
|
||||||
if (NS_FAILED(rv) || !shell) {
|
if (NS_FAILED(rv) || !shell) {
|
||||||
// If we failed to get the shell, or if there is no shell,
|
// If we failed to get the shell, or if there is no shell,
|
||||||
// nothing left to do here.
|
// nothing left to do here.
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: we assume URIs are absolute for comparison purposes
|
|
||||||
|
|
||||||
nsCAutoString currentSpec;
|
|
||||||
NS_ENSURE_SUCCESS(mCurrentURI->GetSpec(currentSpec),
|
|
||||||
NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsCAutoString newSpec;
|
|
||||||
NS_ENSURE_SUCCESS(aURI->GetSpec(newSpec), NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
// Search for hash marks in the current URI and the new URI and
|
|
||||||
// take a copy of everything to the left of the hash for
|
|
||||||
// comparison.
|
|
||||||
|
|
||||||
const char kHash = '#';
|
|
||||||
|
|
||||||
// Split the new URI into a left and right part
|
|
||||||
// (assume we're parsing it out right)
|
|
||||||
nsACString::const_iterator urlStart, urlEnd, refStart, refEnd;
|
|
||||||
newSpec.BeginReading(urlStart);
|
|
||||||
newSpec.EndReading(refEnd);
|
|
||||||
|
|
||||||
PRInt32 hashNew = newSpec.FindChar(kHash);
|
|
||||||
if (hashNew == 0) {
|
|
||||||
return NS_OK; // Strange URI
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashNew > 0) {
|
|
||||||
// found it
|
|
||||||
urlEnd = urlStart;
|
|
||||||
urlEnd.advance(hashNew);
|
|
||||||
|
|
||||||
refStart = urlEnd;
|
|
||||||
++refStart; // advanced past '#'
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// no hash at all
|
|
||||||
urlEnd = refStart = refEnd;
|
|
||||||
}
|
|
||||||
const nsACString& sNewLeft = Substring(urlStart, urlEnd);
|
|
||||||
const nsACString& sNewRef = Substring(refStart, refEnd);
|
|
||||||
|
|
||||||
// Split the current URI in a left and right part
|
|
||||||
nsACString::const_iterator currentLeftStart, currentLeftEnd,
|
|
||||||
currentRefStart, currentRefEnd;
|
|
||||||
currentSpec.BeginReading(currentLeftStart);
|
|
||||||
currentSpec.EndReading(currentRefEnd);
|
|
||||||
|
|
||||||
PRInt32 hashCurrent = currentSpec.FindChar(kHash);
|
|
||||||
if (hashCurrent == 0) {
|
|
||||||
return NS_OK; // Strange URI
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashCurrent > 0) {
|
|
||||||
currentLeftEnd = currentLeftStart;
|
|
||||||
currentLeftEnd.advance(hashCurrent);
|
|
||||||
|
|
||||||
currentRefStart = currentLeftEnd;
|
|
||||||
++currentRefStart; // advance past '#'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// no hash at all in currentSpec
|
|
||||||
currentLeftEnd = currentRefStart = currentRefEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have no new anchor, we do not want to scroll, unless there is a
|
// If we have no new anchor, we do not want to scroll, unless there is a
|
||||||
// current anchor and we are doing a history load. So return if we have no
|
// current anchor and we are doing a history load. So return if we have no
|
||||||
// new anchor, and there is no current anchor or the load is not a history
|
// new anchor, and there is no current anchor or the load is not a history
|
||||||
// load.
|
// load.
|
||||||
NS_ASSERTION(hashNew != 0 && hashCurrent != 0,
|
if ((aCurHash.IsEmpty() || aLoadType != LOAD_HISTORY) &&
|
||||||
"What happened to the early returns above?");
|
aNewHash.IsEmpty()) {
|
||||||
if (hashNew == kNotFound &&
|
|
||||||
(hashCurrent == kNotFound || aLoadType != LOAD_HISTORY)) {
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare the URIs.
|
|
||||||
//
|
|
||||||
// NOTE: this is a case sensitive comparison because some parts of the
|
|
||||||
// URI are case sensitive, and some are not. i.e. the domain name
|
|
||||||
// is case insensitive but the the paths are not.
|
|
||||||
//
|
|
||||||
// This means that comparing "http://www.ABC.com/" to "http://www.abc.com/"
|
|
||||||
// will fail this test.
|
|
||||||
|
|
||||||
if (!Substring(currentLeftStart, currentLeftEnd).Equals(sNewLeft)) {
|
|
||||||
return NS_OK; // URIs not the same
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we know we are dealing with an anchor
|
|
||||||
*aWasAnchor = PR_TRUE;
|
|
||||||
|
|
||||||
// We should fire a hashchange event once we're done here if the two hashes
|
|
||||||
// are different.
|
|
||||||
*aDoHashchange = !Substring(currentRefStart, currentRefEnd).Equals(sNewRef);
|
|
||||||
|
|
||||||
// Both the new and current URIs refer to the same page. We can now
|
// Both the new and current URIs refer to the same page. We can now
|
||||||
// browse to the hash stored in the new URI.
|
// browse to the hash stored in the new URI.
|
||||||
|
|
||||||
if (!sNewRef.IsEmpty()) {
|
if (!aNewHash.IsEmpty()) {
|
||||||
// anchor is there, but if it's a load from history,
|
// anchor is there, but if it's a load from history,
|
||||||
// we don't have any anchor jumping to do
|
// we don't have any anchor jumping to do
|
||||||
PRBool scroll = aLoadType != LOAD_HISTORY &&
|
PRBool scroll = aLoadType != LOAD_HISTORY &&
|
||||||
aLoadType != LOAD_RELOAD_NORMAL;
|
aLoadType != LOAD_RELOAD_NORMAL;
|
||||||
|
|
||||||
char *str = ToNewCString(sNewRef);
|
char *str = ToNewCString(aNewHash);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -9226,7 +9134,7 @@ nsDocShell::ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
|
||||||
nsXPIDLString uStr;
|
nsXPIDLString uStr;
|
||||||
|
|
||||||
rv = textToSubURI->UnEscapeAndConvert(PromiseFlatCString(aCharset).get(),
|
rv = textToSubURI->UnEscapeAndConvert(PromiseFlatCString(aCharset).get(),
|
||||||
PromiseFlatCString(sNewRef).get(),
|
PromiseFlatCString(aNewHash).get(),
|
||||||
getter_Copies(uStr));
|
getter_Copies(uStr));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
|
|
@ -332,8 +332,8 @@ protected:
|
||||||
nsIURILoader * aURILoader,
|
nsIURILoader * aURILoader,
|
||||||
PRBool aBypassClassifier);
|
PRBool aBypassClassifier);
|
||||||
|
|
||||||
nsresult ScrollIfAnchor(nsIURI * aURI, PRBool * aWasAnchor,
|
nsresult ScrollToAnchor(nsACString & curHash, nsACString & newHash,
|
||||||
PRUint32 aLoadType, PRBool * aDoHashchange);
|
PRUint32 aLoadType);
|
||||||
|
|
||||||
// Tries to stringify a given variant by converting it to JSON. This only
|
// Tries to stringify a given variant by converting it to JSON. This only
|
||||||
// works if the variant is backed by a JSVal.
|
// works if the variant is backed by a JSVal.
|
||||||
|
|
|
@ -58,7 +58,7 @@ class nsDocShellEditorData;
|
||||||
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
|
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
|
||||||
|
|
||||||
|
|
||||||
[scriptable, uuid(39b73c3a-48eb-4189-8069-247279c3c42d)]
|
[scriptable, uuid(5f3ebf43-6944-45fb-b1b1-78a05bf9370b)]
|
||||||
interface nsISHEntry : nsIHistoryEntry
|
interface nsISHEntry : nsIHistoryEntry
|
||||||
{
|
{
|
||||||
/** URI for the document */
|
/** URI for the document */
|
||||||
|
@ -139,22 +139,12 @@ interface nsISHEntry : nsIHistoryEntry
|
||||||
*/
|
*/
|
||||||
attribute unsigned long ID;
|
attribute unsigned long ID;
|
||||||
|
|
||||||
/**
|
|
||||||
* pageIdentifier is an integer that should be the same for two entries
|
|
||||||
* attached to the same docshell only if the two entries are entries for
|
|
||||||
* the same page in the sense that one could go from the state represented
|
|
||||||
* by one to the state represented by the other simply by scrolling (so the
|
|
||||||
* entries are separated by an anchor traversal or a subframe navigation in
|
|
||||||
* some other frame).
|
|
||||||
*/
|
|
||||||
attribute unsigned long pageIdentifier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* docIdentifier is an integer that should be the same for two entries
|
* docIdentifier is an integer that should be the same for two entries
|
||||||
* attached to the same docshell if and only if the two entries are entries
|
* attached to the same docshell if and only if the two entries are entries
|
||||||
* for the same document. In practice, two entries A and B will have the
|
* for the same document. In practice, two entries A and B will have the
|
||||||
* same docIdentifier if they have the same pageIdentifier or if B was
|
* same docIdentifier if we arrived at B by clicking an anchor link in A or
|
||||||
* created by A calling history.pushState().
|
* if B was created by A's calling history.pushState().
|
||||||
*/
|
*/
|
||||||
attribute unsigned long long docIdentifier;
|
attribute unsigned long long docIdentifier;
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,6 @@ static void StopTrackingEntry(nsSHEntry *aEntry)
|
||||||
nsSHEntry::nsSHEntry()
|
nsSHEntry::nsSHEntry()
|
||||||
: mLoadType(0)
|
: mLoadType(0)
|
||||||
, mID(gEntryID++)
|
, mID(gEntryID++)
|
||||||
, mPageIdentifier(mID)
|
|
||||||
, mDocIdentifier(gEntryDocIdentifier++)
|
, mDocIdentifier(gEntryDocIdentifier++)
|
||||||
, mScrollPositionX(0)
|
, mScrollPositionX(0)
|
||||||
, mScrollPositionY(0)
|
, mScrollPositionY(0)
|
||||||
|
@ -130,7 +129,6 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
||||||
, mLayoutHistoryState(other.mLayoutHistoryState)
|
, mLayoutHistoryState(other.mLayoutHistoryState)
|
||||||
, mLoadType(0) // XXX why not copy?
|
, mLoadType(0) // XXX why not copy?
|
||||||
, mID(other.mID)
|
, mID(other.mID)
|
||||||
, mPageIdentifier(other.mPageIdentifier)
|
|
||||||
, mDocIdentifier(other.mDocIdentifier)
|
, mDocIdentifier(other.mDocIdentifier)
|
||||||
, mScrollPositionX(0) // XXX why not copy?
|
, mScrollPositionX(0) // XXX why not copy?
|
||||||
, mScrollPositionY(0) // XXX why not copy?
|
, mScrollPositionY(0) // XXX why not copy?
|
||||||
|
@ -391,18 +389,6 @@ NS_IMETHODIMP nsSHEntry::SetID(PRUint32 aID)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsSHEntry::GetPageIdentifier(PRUint32 * aResult)
|
|
||||||
{
|
|
||||||
*aResult = mPageIdentifier;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsSHEntry::SetPageIdentifier(PRUint32 aPageIdentifier)
|
|
||||||
{
|
|
||||||
mPageIdentifier = aPageIdentifier;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsSHEntry::GetDocIdentifier(PRUint64 * aResult)
|
NS_IMETHODIMP nsSHEntry::GetDocIdentifier(PRUint64 * aResult)
|
||||||
{
|
{
|
||||||
*aResult = mDocIdentifier;
|
*aResult = mDocIdentifier;
|
||||||
|
|
|
@ -99,7 +99,6 @@ private:
|
||||||
nsCOMArray<nsISHEntry> mChildren;
|
nsCOMArray<nsISHEntry> mChildren;
|
||||||
PRUint32 mLoadType;
|
PRUint32 mLoadType;
|
||||||
PRUint32 mID;
|
PRUint32 mID;
|
||||||
PRUint32 mPageIdentifier;
|
|
||||||
PRInt64 mDocIdentifier;
|
PRInt64 mDocIdentifier;
|
||||||
PRInt32 mScrollPositionX;
|
PRInt32 mScrollPositionX;
|
||||||
PRInt32 mScrollPositionY;
|
PRInt32 mScrollPositionY;
|
||||||
|
|
|
@ -97,6 +97,9 @@ _TEST_FILES = \
|
||||||
test_bug634834.html \
|
test_bug634834.html \
|
||||||
file_bug634834.html \
|
file_bug634834.html \
|
||||||
test_bug637644.html \
|
test_bug637644.html \
|
||||||
|
test_bug640387_1.html \
|
||||||
|
test_bug640387_2.html \
|
||||||
|
file_bug640387.html \
|
||||||
test_framedhistoryframes.html \
|
test_framedhistoryframes.html \
|
||||||
test_windowedhistoryframes.html \
|
test_windowedhistoryframes.html \
|
||||||
historyframes.html \
|
historyframes.html \
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<html>
|
||||||
|
<body onhashchange='hashchange()' onload='load()' onpopstate='popstate()'>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function hashchange() {
|
||||||
|
var f = (opener || parent).childHashchange;
|
||||||
|
if (f)
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
var f = (opener || parent).childLoad;
|
||||||
|
if (f)
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
function popstate() {
|
||||||
|
var f = (opener || parent).childPopstate;
|
||||||
|
if (f)
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
Not much to see here...
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -135,10 +135,6 @@ function run_test() {
|
||||||
yield;
|
yield;
|
||||||
eventExpected("Going forward should trigger a hashchange.");
|
eventExpected("Going forward should trigger a hashchange.");
|
||||||
|
|
||||||
frameCw.window.location.hash = "";
|
|
||||||
yield;
|
|
||||||
eventExpected("Changing window.location.hash should trigger a hashchange.");
|
|
||||||
|
|
||||||
// window.location has a trailing '#' right now, so we append "link1", not
|
// window.location has a trailing '#' right now, so we append "link1", not
|
||||||
// "#link1".
|
// "#link1".
|
||||||
frameCw.window.location = frameCw.window.location + "link1";
|
frameCw.window.location = frameCw.window.location + "link1";
|
||||||
|
@ -187,8 +183,8 @@ function run_test() {
|
||||||
"Event type should be 'hashchange'.");
|
"Event type should be 'hashchange'.");
|
||||||
is(gSampleEvent.cancelable, false,
|
is(gSampleEvent.cancelable, false,
|
||||||
"The hashchange event shouldn't be cancelable.");
|
"The hashchange event shouldn't be cancelable.");
|
||||||
is(gSampleEvent.bubbles, false,
|
is(gSampleEvent.bubbles, true,
|
||||||
"The hashchange event shouldn't bubble.");
|
"The hashchange event should bubble.");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TEST 3 tests that:
|
* TEST 3 tests that:
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=640387
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 640387</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=640387">Mozilla Bug 640387</a>
|
||||||
|
|
||||||
|
<script type='application/javascript;version=1.7'>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
/* Spin the event loop so we get out of the onload handler. */
|
||||||
|
SimpleTest.executeSoon(function() { gGen.next() });
|
||||||
|
yield;
|
||||||
|
|
||||||
|
popup.history.pushState('', '', '#hash1');
|
||||||
|
popup.history.pushState('', '', '#hash2');
|
||||||
|
|
||||||
|
// Now the history looks like:
|
||||||
|
// file_bug640387.html
|
||||||
|
// file_bug640387.html#hash1
|
||||||
|
// file_bug640387.html#hash2 <-- current
|
||||||
|
|
||||||
|
// Going back should trigger a hashchange, which will wake us up from the
|
||||||
|
// yield.
|
||||||
|
popup.history.back();
|
||||||
|
yield;
|
||||||
|
ok(true, 'Got first hashchange.');
|
||||||
|
|
||||||
|
// Going back should wake us up again.
|
||||||
|
popup.history.back();
|
||||||
|
yield;
|
||||||
|
ok(true, 'Got second hashchange.');
|
||||||
|
|
||||||
|
// Now the history looks like:
|
||||||
|
// file_bug640387.html <-- current
|
||||||
|
// file_bug640387.html#hash1
|
||||||
|
// file_bug640387.html#hash2
|
||||||
|
|
||||||
|
// Going forward should trigger a hashchange.
|
||||||
|
popup.history.forward();
|
||||||
|
yield;
|
||||||
|
ok(true, 'Got third hashchange.');
|
||||||
|
|
||||||
|
// Now modify the history so it looks like:
|
||||||
|
// file_bug640387.html
|
||||||
|
// file_bug640387.html#hash1
|
||||||
|
// file_bug640387.html#hash1 <-- current
|
||||||
|
popup.history.pushState('', '', '#hash1');
|
||||||
|
|
||||||
|
// Now when we go back, we should not get a hashchange. Instead, wait for a
|
||||||
|
// popstate. We need to asynchronously go back because popstate is fired
|
||||||
|
// sync.
|
||||||
|
gHashchangeExpected = false;
|
||||||
|
gCallbackOnPopstate = true;
|
||||||
|
SimpleTest.executeSoon(function() { popup.history.back() });
|
||||||
|
yield;
|
||||||
|
ok(true, 'Got popstate.');
|
||||||
|
gCallbackOnPopstate = false;
|
||||||
|
|
||||||
|
// Spin the event loop so hashchange has a chance to fire, if it's going to.
|
||||||
|
SimpleTest.executeSoon(function() { gGen.next() });
|
||||||
|
yield;
|
||||||
|
|
||||||
|
popup.close();
|
||||||
|
SimpleTest.finish();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
gGen = null;
|
||||||
|
function childLoad() {
|
||||||
|
gGen = test();
|
||||||
|
gGen.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
gHashchangeExpected = true;
|
||||||
|
function childHashchange() {
|
||||||
|
if (gHashchangeExpected) {
|
||||||
|
gGen.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ok(false, "Got hashchange when we weren't expecting one.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gCallbackOnPopstate = false;
|
||||||
|
function childPopstate() {
|
||||||
|
if (gCallbackOnPopstate) {
|
||||||
|
gGen.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need to run this test in a popup, because navigating an iframe
|
||||||
|
* back/forwards tends to cause intermittent orange. */
|
||||||
|
popup = window.open('file_bug640387.html');
|
||||||
|
|
||||||
|
/* Control now flows up to childLoad(), called once the popup loads. */
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=640387
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 640387</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=640387">Mozilla Bug 640387</a>
|
||||||
|
|
||||||
|
<!-- Test that, when going from
|
||||||
|
|
||||||
|
http://example.com/#foo
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
http://example.com/
|
||||||
|
|
||||||
|
via a non-history load, we do a true load, rather than a scroll. -->
|
||||||
|
|
||||||
|
<script type='application/javascript;version=1.7'>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
callbackOnLoad = false;
|
||||||
|
function childLoad() {
|
||||||
|
if (callbackOnLoad) {
|
||||||
|
callbackOnLoad = false;
|
||||||
|
gGen.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorOnHashchange = false;
|
||||||
|
callbackOnHashchange = false;
|
||||||
|
function childHashchange() {
|
||||||
|
if (errorOnHashchange) {
|
||||||
|
ok(false, 'Got unexpected hashchange.');
|
||||||
|
}
|
||||||
|
if (callbackOnHashchange) {
|
||||||
|
callbackOnHashchange = false;
|
||||||
|
gGen.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
var iframe = $('iframe').contentWindow;
|
||||||
|
|
||||||
|
ok(true, 'Got first load');
|
||||||
|
|
||||||
|
// Spin the event loop so we exit the onload handler.
|
||||||
|
SimpleTest.executeSoon(function() { gGen.next() });
|
||||||
|
yield;
|
||||||
|
|
||||||
|
let origLocation = iframe.location + '';
|
||||||
|
callbackOnHashchange = true;
|
||||||
|
iframe.location.hash = '#1';
|
||||||
|
// Wait for a hashchange event.
|
||||||
|
yield;
|
||||||
|
|
||||||
|
ok(true, 'Got hashchange.');
|
||||||
|
|
||||||
|
iframe.location = origLocation;
|
||||||
|
// This should produce a load event and *not* a hashchange, because the
|
||||||
|
// result of the load is a different document than we had previously.
|
||||||
|
callbackOnLoad = true;
|
||||||
|
errorOnHashchange = true;
|
||||||
|
yield;
|
||||||
|
|
||||||
|
ok(true, 'Got final load.');
|
||||||
|
|
||||||
|
// Spin the event loop to give hashchange a chance to fire, if it's going to.
|
||||||
|
SimpleTest.executeSoon(function() { gGen.next() });
|
||||||
|
yield;
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbackOnLoad = true;
|
||||||
|
gGen = run_test();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<iframe id='iframe' src='file_bug640387.html'></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -87,6 +87,7 @@
|
||||||
#include "nsIDOMKeyEvent.h"
|
#include "nsIDOMKeyEvent.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
#include "nsIDOMPopStateEvent.h"
|
#include "nsIDOMPopStateEvent.h"
|
||||||
|
#include "nsIDOMHashChangeEvent.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsDOMWindowUtils.h"
|
#include "nsDOMWindowUtils.h"
|
||||||
#include "nsIDOMGlobalPropertyInitializer.h"
|
#include "nsIDOMGlobalPropertyInitializer.h"
|
||||||
|
@ -1440,6 +1441,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(PopStateEvent, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(PopStateEvent, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
|
NS_DEFINE_CLASSINFO_DATA(HashChangeEvent, nsDOMGenericSH,
|
||||||
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
|
||||||
|
@ -2580,6 +2583,11 @@ nsDOMClassInfo::Init()
|
||||||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
|
DOM_CLASSINFO_MAP_BEGIN(HashChangeEvent, nsIDOMHashChangeEvent)
|
||||||
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHashChangeEvent)
|
||||||
|
DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
|
||||||
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
|
DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
|
||||||
|
|
|
@ -478,6 +478,7 @@ DOMCI_CLASS(PaintRequestList)
|
||||||
|
|
||||||
DOMCI_CLASS(ScrollAreaEvent)
|
DOMCI_CLASS(ScrollAreaEvent)
|
||||||
DOMCI_CLASS(PopStateEvent)
|
DOMCI_CLASS(PopStateEvent)
|
||||||
|
DOMCI_CLASS(HashChangeEvent)
|
||||||
|
|
||||||
DOMCI_CLASS(EventListenerInfo)
|
DOMCI_CLASS(EventListenerInfo)
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
#include "nsIDOMMessageEvent.h"
|
#include "nsIDOMMessageEvent.h"
|
||||||
#include "nsIDOMPopupBlockedEvent.h"
|
#include "nsIDOMPopupBlockedEvent.h"
|
||||||
#include "nsIDOMPopStateEvent.h"
|
#include "nsIDOMPopStateEvent.h"
|
||||||
|
#include "nsIDOMHashChangeEvent.h"
|
||||||
#include "nsIDOMOfflineResourceList.h"
|
#include "nsIDOMOfflineResourceList.h"
|
||||||
#include "nsIDOMGeoGeolocation.h"
|
#include "nsIDOMGeoGeolocation.h"
|
||||||
#include "nsIDOMDesktopNotification.h"
|
#include "nsIDOMDesktopNotification.h"
|
||||||
|
@ -7681,19 +7682,59 @@ nsGlobalWindow::PageHidden()
|
||||||
mNeedsFocus = PR_TRUE;
|
mNeedsFocus = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
class HashchangeCallback : public nsRunnable
|
||||||
nsGlobalWindow::DispatchAsyncHashchange()
|
|
||||||
{
|
{
|
||||||
FORWARD_TO_INNER(DispatchAsyncHashchange, (), NS_OK);
|
public:
|
||||||
|
HashchangeCallback(const nsAString &aOldURL,
|
||||||
|
const nsAString &aNewURL,
|
||||||
|
nsGlobalWindow* aWindow)
|
||||||
|
: mWindow(aWindow)
|
||||||
|
{
|
||||||
|
mOldURL.Assign(aOldURL);
|
||||||
|
mNewURL.Assign(aNewURL);
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> event =
|
NS_IMETHOD Run()
|
||||||
NS_NewRunnableMethod(this, &nsGlobalWindow::FireHashchange);
|
{
|
||||||
|
NS_PRECONDITION(NS_IsMainThread(), "Should be called on the main thread.");
|
||||||
|
return mWindow->FireHashchange(mOldURL, mNewURL);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_DispatchToCurrentThread(event);
|
private:
|
||||||
|
nsString mOldURL;
|
||||||
|
nsString mNewURL;
|
||||||
|
nsRefPtr<nsGlobalWindow> mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsGlobalWindow::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
|
||||||
|
{
|
||||||
|
FORWARD_TO_INNER(DispatchAsyncHashchange, (aOldURI, aNewURI), NS_OK);
|
||||||
|
|
||||||
|
// Make sure that aOldURI and aNewURI are identical up to the '#', and that
|
||||||
|
// their hashes are different.
|
||||||
|
nsCAutoString oldBeforeHash, oldHash, newBeforeHash, newHash;
|
||||||
|
nsContentUtils::SplitURIAtHash(aOldURI, oldBeforeHash, oldHash);
|
||||||
|
nsContentUtils::SplitURIAtHash(aNewURI, newBeforeHash, newHash);
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(oldBeforeHash.Equals(newBeforeHash));
|
||||||
|
NS_ENSURE_STATE(!oldHash.Equals(newHash));
|
||||||
|
|
||||||
|
nsCAutoString oldSpec, newSpec;
|
||||||
|
aOldURI->GetSpec(oldSpec);
|
||||||
|
aNewURI->GetSpec(newSpec);
|
||||||
|
|
||||||
|
NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
|
||||||
|
NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRunnable> callback =
|
||||||
|
new HashchangeCallback(oldWideSpec, newWideSpec, this);
|
||||||
|
return NS_DispatchToMainThread(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsGlobalWindow::FireHashchange()
|
nsGlobalWindow::FireHashchange(const nsAString &aOldURL,
|
||||||
|
const nsAString &aNewURL)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(IsInnerWindow(), NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(IsInnerWindow(), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
@ -7701,11 +7742,40 @@ nsGlobalWindow::FireHashchange()
|
||||||
if (IsFrozen())
|
if (IsFrozen())
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
// Dispatch the hashchange event, which doesn't bubble and isn't cancelable,
|
// Get a presentation shell for use in creating the hashchange event.
|
||||||
// to the outer window.
|
NS_ENSURE_STATE(mDoc);
|
||||||
return nsContentUtils::DispatchTrustedEvent(mDoc, GetOuterWindow(),
|
|
||||||
NS_LITERAL_STRING("hashchange"),
|
nsIPresShell *shell = mDoc->GetShell();
|
||||||
PR_FALSE, PR_FALSE);
|
nsRefPtr<nsPresContext> presContext;
|
||||||
|
if (shell) {
|
||||||
|
presContext = shell->GetPresContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new hashchange event.
|
||||||
|
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||||
|
nsresult rv =
|
||||||
|
nsEventDispatcher::CreateEvent(presContext, nsnull,
|
||||||
|
NS_LITERAL_STRING("hashchangeevent"),
|
||||||
|
getter_AddRefs(domEvent));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
|
||||||
|
NS_ENSURE_TRUE(privateEvent, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMHashChangeEvent> hashchangeEvent = do_QueryInterface(domEvent);
|
||||||
|
NS_ENSURE_TRUE(hashchangeEvent, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
|
// The hashchange event bubbles and isn't cancellable.
|
||||||
|
rv = hashchangeEvent->InitHashChangeEvent(NS_LITERAL_STRING("hashchange"),
|
||||||
|
PR_TRUE, PR_FALSE,
|
||||||
|
aOldURL, aNewURL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = privateEvent->SetTrusted(PR_TRUE);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRBool dummy;
|
||||||
|
return DispatchEvent(hashchangeEvent, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -548,7 +548,7 @@ public:
|
||||||
virtual PRBool TakeFocus(PRBool aFocus, PRUint32 aFocusMethod);
|
virtual PRBool TakeFocus(PRBool aFocus, PRUint32 aFocusMethod);
|
||||||
virtual void SetReadyForFocus();
|
virtual void SetReadyForFocus();
|
||||||
virtual void PageHidden();
|
virtual void PageHidden();
|
||||||
virtual nsresult DispatchAsyncHashchange();
|
virtual nsresult DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI);
|
||||||
virtual nsresult DispatchSyncPopState();
|
virtual nsresult DispatchSyncPopState();
|
||||||
|
|
||||||
virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin);
|
virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin);
|
||||||
|
@ -588,6 +588,8 @@ private:
|
||||||
void DisableAccelerationUpdates();
|
void DisableAccelerationUpdates();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class HashchangeCallback;
|
||||||
|
|
||||||
// Object Management
|
// Object Management
|
||||||
virtual ~nsGlobalWindow();
|
virtual ~nsGlobalWindow();
|
||||||
void CleanUp(PRBool aIgnoreModalDialog);
|
void CleanUp(PRBool aIgnoreModalDialog);
|
||||||
|
@ -716,7 +718,7 @@ protected:
|
||||||
const nsAString &aPopupWindowName,
|
const nsAString &aPopupWindowName,
|
||||||
const nsAString &aPopupWindowFeatures);
|
const nsAString &aPopupWindowFeatures);
|
||||||
void FireOfflineStatusEvent();
|
void FireOfflineStatusEvent();
|
||||||
nsresult FireHashchange();
|
nsresult FireHashchange(const nsAString &aOldURL, const nsAString &aNewURL);
|
||||||
|
|
||||||
void FlushPendingNotifications(mozFlushType aType);
|
void FlushPendingNotifications(mozFlushType aType);
|
||||||
void EnsureReflowFlushAndPaint();
|
void EnsureReflowFlushAndPaint();
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsEvent.h"
|
#include "nsEvent.h"
|
||||||
|
#include "nsIURI.h"
|
||||||
|
|
||||||
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
|
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
|
||||||
|
|
||||||
|
@ -537,7 +538,8 @@ public:
|
||||||
* Instructs this window to asynchronously dispatch a hashchange event. This
|
* Instructs this window to asynchronously dispatch a hashchange event. This
|
||||||
* method must be called on an inner window.
|
* method must be called on an inner window.
|
||||||
*/
|
*/
|
||||||
virtual nsresult DispatchAsyncHashchange() = 0;
|
virtual nsresult DispatchAsyncHashchange(nsIURI *aOldURI,
|
||||||
|
nsIURI *aNewURI) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs this window to synchronously dispatch a popState event.
|
* Instructs this window to synchronously dispatch a popState event.
|
||||||
|
|
|
@ -88,6 +88,7 @@ XPIDLSRCS = \
|
||||||
nsIDOMPopStateEvent.idl \
|
nsIDOMPopStateEvent.idl \
|
||||||
nsIDOMCloseEvent.idl \
|
nsIDOMCloseEvent.idl \
|
||||||
nsIDOMEventException.idl \
|
nsIDOMEventException.idl \
|
||||||
|
nsIDOMHashChangeEvent.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifdef MOZ_CSS_ANIMATIONS
|
ifdef MOZ_CSS_ANIMATIONS
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsIDOMEvent.idl"
|
||||||
|
|
||||||
|
[scriptable, uuid(34850f11-8b88-43ce-8d55-9aa8b18753bd)]
|
||||||
|
interface nsIDOMHashChangeEvent : nsIDOMEvent
|
||||||
|
{
|
||||||
|
readonly attribute DOMString oldURL;
|
||||||
|
readonly attribute DOMString newURL;
|
||||||
|
|
||||||
|
void initHashChangeEvent(in DOMString typeArg,
|
||||||
|
in boolean canBubbleArg,
|
||||||
|
in boolean cancelableArg,
|
||||||
|
in DOMString oldURLArg,
|
||||||
|
in DOMString newURLArg);
|
||||||
|
};
|
|
@ -50,6 +50,9 @@ _TEST_FILES = \
|
||||||
historyframes.html \
|
historyframes.html \
|
||||||
test_497898.html \
|
test_497898.html \
|
||||||
test_bug504220.html \
|
test_bug504220.html \
|
||||||
|
test_bug628069_1.html \
|
||||||
|
test_bug628069_2.html \
|
||||||
|
file_bug628069.html \
|
||||||
test_bug631440.html \
|
test_bug631440.html \
|
||||||
test_consoleAPI.html \
|
test_consoleAPI.html \
|
||||||
test_domWindowUtils.html \
|
test_domWindowUtils.html \
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<html>
|
||||||
|
<body onhashchange='hashchange(event)' onload='load()'>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function hashchange(e) {
|
||||||
|
(opener || parent).childHashchange(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
(opener || parent).childLoad();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
Just a shell of a page.
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=628069
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 628069</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=628069">Mozilla Bug 628069</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
<iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
|
||||||
|
<div id="status" style="display: none"></div>
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
|
||||||
|
/** Test for Bug 628069 **/
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
popup = window.open('file_bug628069.html');
|
||||||
|
|
||||||
|
// Control flows into childLoad, once the popup loads.
|
||||||
|
|
||||||
|
gOrigURL = null;
|
||||||
|
function childLoad() {
|
||||||
|
gOrigURL = popup.location + '';
|
||||||
|
|
||||||
|
popup.location.hash = '#hash';
|
||||||
|
|
||||||
|
// This should trigger a hashchange, so control should flow down to
|
||||||
|
// childHashchange.
|
||||||
|
}
|
||||||
|
|
||||||
|
function childHashchange(e) {
|
||||||
|
is(e.oldURL, gOrigURL, 'event.oldURL');
|
||||||
|
is(e.newURL, gOrigURL + '#hash', 'event.newURL');
|
||||||
|
popup.close();
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=628069
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 628069</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=628069">Mozilla Bug 628069</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
<iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
|
||||||
|
<div id="status" style="display: none"></div>
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
|
||||||
|
/** Test for Bug 628069 **/
|
||||||
|
|
||||||
|
gotHashChange = 0;
|
||||||
|
document.addEventListener("hashChange", function(e) {
|
||||||
|
gotHashChange = 1;
|
||||||
|
is(e.oldURL, "oldURL");
|
||||||
|
is(e.newURL, "newURL");
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
let hc = document.createEvent("HashChangeEvent");
|
||||||
|
hc.initHashChangeEvent("hashChange", true, false, "oldURL", "newURL");
|
||||||
|
document.documentElement.dispatchEvent(hc);
|
||||||
|
is(gotHashChange, 1, 'Document received hashchange event.');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=600570
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600570">Mozilla Bug 600570</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600570">Mozilla Bug 600570</a>
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<textarea>
|
<textarea spellcheck="false">
|
||||||
aaa
|
aaa
|
||||||
[bbb]</textarea>
|
[bbb]</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,17 +45,19 @@ SimpleTest.waitForFocus(function() {
|
||||||
t.addEventListener("input", function() {
|
t.addEventListener("input", function() {
|
||||||
t.removeEventListener("input", arguments.callee, false);
|
t.removeEventListener("input", arguments.callee, false);
|
||||||
|
|
||||||
is(t.value, "[aaa\nbbb]", "The value of the textarea should be correct");
|
setTimeout(function() { // Avoid the assertion in bug 649797
|
||||||
synthesizeKey("A", {accelKey: true});
|
is(t.value, "[aaa\nbbb]", "The value of the textarea should be correct");
|
||||||
is(t.selectionStart, 0, "Select all should set the selection start to the beginning of textarea");
|
synthesizeKey("A", {accelKey: true});
|
||||||
is(t.selectionEnd, 9, "Select all should set the selection end to the end of textarea");
|
is(t.selectionStart, 0, "Select all should set the selection start to the beginning of textarea");
|
||||||
|
is(t.selectionEnd, 9, "Select all should set the selection end to the end of textarea");
|
||||||
|
|
||||||
var afterPaste = snapshotWindow(window);
|
var afterPaste = snapshotWindow(window);
|
||||||
|
|
||||||
var res = compareSnapshots(afterSetValue, afterPaste, true);
|
var res = compareSnapshots(afterSetValue, afterPaste, true);
|
||||||
ok(res[0], "Pasting and setting the value directly should result in the same rendering");
|
ok(res[0], "Pasting and setting the value directly should result in the same rendering");
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
}, 0);
|
||||||
}, false);
|
}, false);
|
||||||
synthesizeKey("VK_RIGHT", {});
|
synthesizeKey("VK_RIGHT", {});
|
||||||
synthesizeKey("V", {accelKey: true});
|
synthesizeKey("V", {accelKey: true});
|
||||||
|
|
|
@ -80,7 +80,7 @@ typedef struct _cairo_d2d_device cairo_d2d_device_t;
|
||||||
|
|
||||||
struct _cairo_d2d_surface {
|
struct _cairo_d2d_surface {
|
||||||
_cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
|
_cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
|
||||||
textRenderingInit(true)
|
textRenderingInit(false)
|
||||||
{
|
{
|
||||||
_cairo_clip_init (&this->clip);
|
_cairo_clip_init (&this->clip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ cairo_d2d_create_device_from_d3d10device(ID3D10Device1 *d3d10device)
|
||||||
CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
|
CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
|
||||||
D3D10_SUBRESOURCE_DATA data;
|
D3D10_SUBRESOURCE_DATA data;
|
||||||
CD3D10_TEXTURE2D_DESC textDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
CD3D10_TEXTURE2D_DESC textDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
TEXT_TEXTURE_WIDTH,
|
TEXT_TEXTURE_WIDTH,
|
||||||
TEXT_TEXTURE_HEIGHT,
|
TEXT_TEXTURE_HEIGHT,
|
||||||
1, 1);
|
1, 1);
|
||||||
|
|
||||||
|
@ -352,10 +352,10 @@ cairo_release_device(cairo_device_t *device)
|
||||||
if (!newrefcnt) {
|
if (!newrefcnt) {
|
||||||
// Call the correct destructor
|
// Call the correct destructor
|
||||||
cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
|
cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
|
||||||
HMODULE d3d10_1 = d2d_device->mD3D10_1;
|
HMODULE d3d10_1 = d2d_device->mD3D10_1;
|
||||||
delete d2d_device;
|
delete d2d_device;
|
||||||
_cairo_d2d_release_factory();
|
_cairo_d2d_release_factory();
|
||||||
FreeLibrary(d3d10_1);
|
FreeLibrary(d3d10_1);
|
||||||
}
|
}
|
||||||
return newrefcnt;
|
return newrefcnt;
|
||||||
}
|
}
|
||||||
|
@ -779,7 +779,7 @@ _cairo_d2d_get_buffer_texture(cairo_d2d_surface_t *surface)
|
||||||
surface->surface->QueryInterface(&surf);
|
surface->surface->QueryInterface(&surf);
|
||||||
surf->GetDesc(&surfDesc);
|
surf->GetDesc(&surfDesc);
|
||||||
CD3D10_TEXTURE2D_DESC softDesc(surfDesc.Format, surfDesc.Width, surfDesc.Height);
|
CD3D10_TEXTURE2D_DESC softDesc(surfDesc.Format, surfDesc.Width, surfDesc.Height);
|
||||||
softDesc.MipLevels = 1;
|
softDesc.MipLevels = 1;
|
||||||
softDesc.Usage = D3D10_USAGE_DEFAULT;
|
softDesc.Usage = D3D10_USAGE_DEFAULT;
|
||||||
softDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
softDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||||
surface->device->mD3D10Device->CreateTexture2D(&softDesc, NULL, &surface->bufferTexture);
|
surface->device->mD3D10Device->CreateTexture2D(&softDesc, NULL, &surface->bufferTexture);
|
||||||
|
@ -1158,9 +1158,9 @@ _cairo_d2d_create_strokestyle_for_stroke_style(const cairo_stroke_style_t *style
|
||||||
(FLOAT)style->miter_limit,
|
(FLOAT)style->miter_limit,
|
||||||
dashStyle,
|
dashStyle,
|
||||||
(FLOAT)style->dash_offset),
|
(FLOAT)style->dash_offset),
|
||||||
dashes,
|
dashes,
|
||||||
style->num_dashes,
|
style->num_dashes,
|
||||||
&strokeStyle);
|
&strokeStyle);
|
||||||
delete [] dashes;
|
delete [] dashes;
|
||||||
return strokeStyle;
|
return strokeStyle;
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1225,7 @@ static void _d2d_snapshot_detached(cairo_surface_t *surface)
|
||||||
}
|
}
|
||||||
if (!--existingBitmap->refs) {
|
if (!--existingBitmap->refs) {
|
||||||
cache_usage -= _d2d_compute_bitmap_mem_size(existingBitmap->bitmap);
|
cache_usage -= _d2d_compute_bitmap_mem_size(existingBitmap->bitmap);
|
||||||
delete existingBitmap;
|
delete existingBitmap;
|
||||||
}
|
}
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
}
|
}
|
||||||
|
@ -1463,8 +1463,8 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||||
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
|
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
|
||||||
float offset_factor = (outer_radius - inner_radius) / outer_radius;
|
float offset_factor = (outer_radius - inner_radius) / outer_radius;
|
||||||
float global_offset = inner_radius / outer_radius;
|
float global_offset = inner_radius / outer_radius;
|
||||||
|
|
||||||
num_stops++; // Add a stop on the outer radius.
|
num_stops++; // Add a stop on the outer radius.
|
||||||
if (inner_radius != 0) {
|
if (inner_radius != 0) {
|
||||||
num_stops++; // Add a stop on the inner radius.
|
num_stops++; // Add a stop on the inner radius.
|
||||||
}
|
}
|
||||||
|
@ -1572,11 +1572,11 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||||
|
|
||||||
double max_dist, min_dist;
|
double max_dist, min_dist;
|
||||||
max_dist = MAX(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
|
max_dist = MAX(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
|
||||||
_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
|
_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
|
||||||
max_dist = MAX(max_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
|
max_dist = MAX(max_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
|
||||||
max_dist = MAX(max_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
|
max_dist = MAX(max_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
|
||||||
min_dist = MIN(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
|
min_dist = MIN(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
|
||||||
_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
|
_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
|
||||||
min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
|
min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
|
||||||
min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
|
min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
|
||||||
|
|
||||||
|
@ -1758,7 +1758,7 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||||
*/
|
*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (srcSurf->device != d2dsurf->device) {
|
if (srcSurf->device != d2dsurf->device) {
|
||||||
/* This code does not work if the source surface does not use
|
/* This code does not work if the source surface does not use
|
||||||
* the same device. Some work could be done to do something
|
* the same device. Some work could be done to do something
|
||||||
* fairly efficient here, for now, fallback.
|
* fairly efficient here, for now, fallback.
|
||||||
|
@ -1830,7 +1830,7 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||||
/* First we check which part of the image is inside the viewable area. */
|
/* First we check which part of the image is inside the viewable area. */
|
||||||
_cairo_d2d_calculate_visible_rect(d2dsurf, srcSurf, &mat, &xoffset, &yoffset, &width, &height);
|
_cairo_d2d_calculate_visible_rect(d2dsurf, srcSurf, &mat, &xoffset, &yoffset, &width, &height);
|
||||||
|
|
||||||
cairo_matrix_translate(&mat, xoffset, yoffset);
|
cairo_matrix_translate(&mat, xoffset, yoffset);
|
||||||
|
|
||||||
if (width > maxSize || height > maxSize) {
|
if (width > maxSize || height > maxSize) {
|
||||||
/*
|
/*
|
||||||
|
@ -1840,11 +1840,11 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||||
* We need to size it to at least the diagonal size of this surface, in order to prevent ever
|
* We need to size it to at least the diagonal size of this surface, in order to prevent ever
|
||||||
* upsampling this again when drawing it to the surface. We want the resized surface
|
* upsampling this again when drawing it to the surface. We want the resized surface
|
||||||
* to be as small as possible to limit pixman required fill rate.
|
* to be as small as possible to limit pixman required fill rate.
|
||||||
*
|
*
|
||||||
* Note this isn't necessarily perfect. Imagine having a 5x5 pixel destination and
|
* Note this isn't necessarily perfect. Imagine having a 5x5 pixel destination and
|
||||||
* a 10x5 image containing a line of blackpixels, white pixels, black pixels, if you rotate
|
* a 10x5 image containing a line of blackpixels, white pixels, black pixels, if you rotate
|
||||||
* this by 45 degrees and scale it to a size of 5x5 pixels and composite it to the destination,
|
* this by 45 degrees and scale it to a size of 5x5 pixels and composite it to the destination,
|
||||||
* the composition will require all 10 original columns to do the best possible sampling.
|
* the composition will require all 10 original columns to do the best possible sampling.
|
||||||
*/
|
*/
|
||||||
RefPtr<IDXGISurface> surf;
|
RefPtr<IDXGISurface> surf;
|
||||||
d2dsurf->surface->QueryInterface(&surf);
|
d2dsurf->surface->QueryInterface(&surf);
|
||||||
|
@ -1978,10 +1978,10 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||||
cachebitmap->dirty = false;
|
cachebitmap->dirty = false;
|
||||||
cachebitmap->bitmap = sourceBitmap;
|
cachebitmap->bitmap = sourceBitmap;
|
||||||
cachebitmap->device = d2dsurf->device;
|
cachebitmap->device = d2dsurf->device;
|
||||||
/*
|
/*
|
||||||
* This will start out with two references, one on the snapshot
|
* This will start out with two references, one on the snapshot
|
||||||
* and one more in the user data structure.
|
* and one more in the user data structure.
|
||||||
*/
|
*/
|
||||||
cachebitmap->refs = 2;
|
cachebitmap->refs = 2;
|
||||||
cairo_surface_set_user_data(surfacePattern->surface,
|
cairo_surface_set_user_data(surfacePattern->surface,
|
||||||
key,
|
key,
|
||||||
|
@ -2272,7 +2272,7 @@ _cairo_d2d_clear (cairo_d2d_surface_t *d2dsurf,
|
||||||
|
|
||||||
d2dsurf->rt->PushAxisAlignedClip(
|
d2dsurf->rt->PushAxisAlignedClip(
|
||||||
D2D1::RectF((FLOAT)rect.x,
|
D2D1::RectF((FLOAT)rect.x,
|
||||||
(FLOAT)rect.y,
|
(FLOAT)rect.y,
|
||||||
(FLOAT)rect.x + rect.width,
|
(FLOAT)rect.x + rect.width,
|
||||||
(FLOAT)rect.y + rect.height),
|
(FLOAT)rect.y + rect.height),
|
||||||
D2D1_ANTIALIAS_MODE_ALIASED);
|
D2D1_ANTIALIAS_MODE_ALIASED);
|
||||||
|
@ -2288,7 +2288,7 @@ _cairo_d2d_clear (cairo_d2d_surface_t *d2dsurf,
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
|
static cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
|
||||||
const cairo_pattern_t *source)
|
const cairo_pattern_t *source)
|
||||||
{
|
{
|
||||||
if (op == CAIRO_OPERATOR_SOURCE) {
|
if (op == CAIRO_OPERATOR_SOURCE) {
|
||||||
/** Operator over is easier for D2D! If the source if opaque, change */
|
/** Operator over is easier for D2D! If the source if opaque, change */
|
||||||
|
@ -2655,7 +2655,7 @@ _cairo_d2d_copy_surface(cairo_d2d_surface_t *dst,
|
||||||
src->device->mD3D10Device->CopyResource(srcResource, src->surface);
|
src->device->mD3D10Device->CopyResource(srcResource, src->surface);
|
||||||
} else {
|
} else {
|
||||||
// Need to flush the source too if it's a different surface.
|
// Need to flush the source too if it's a different surface.
|
||||||
_cairo_d2d_flush(src);
|
_cairo_d2d_flush(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// One copy for each rectangle in the final clipping region.
|
// One copy for each rectangle in the final clipping region.
|
||||||
|
@ -2705,7 +2705,7 @@ _cairo_d2d_blend_surface(cairo_d2d_surface_t *dst,
|
||||||
const cairo_matrix_t *transform,
|
const cairo_matrix_t *transform,
|
||||||
cairo_box_t *box,
|
cairo_box_t *box,
|
||||||
cairo_clip_t *clip,
|
cairo_clip_t *clip,
|
||||||
cairo_filter_t filter,
|
cairo_filter_t filter,
|
||||||
float opacity)
|
float opacity)
|
||||||
{
|
{
|
||||||
if (dst == src) {
|
if (dst == src) {
|
||||||
|
@ -2804,12 +2804,12 @@ _cairo_d2d_blend_surface(cairo_d2d_surface_t *dst,
|
||||||
*/
|
*/
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_d2d_try_fastblit(cairo_d2d_surface_t *dst,
|
_cairo_d2d_try_fastblit(cairo_d2d_surface_t *dst,
|
||||||
cairo_surface_t *src,
|
cairo_surface_t *src,
|
||||||
cairo_box_t *box,
|
cairo_box_t *box,
|
||||||
const cairo_matrix_t *matrix,
|
const cairo_matrix_t *matrix,
|
||||||
cairo_clip_t *clip,
|
cairo_clip_t *clip,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
cairo_filter_t filter,
|
cairo_filter_t filter,
|
||||||
float opacity = 1.0f)
|
float opacity = 1.0f)
|
||||||
{
|
{
|
||||||
if (op == CAIRO_OPERATOR_OVER && src->content == CAIRO_CONTENT_COLOR) {
|
if (op == CAIRO_OPERATOR_OVER && src->content == CAIRO_CONTENT_COLOR) {
|
||||||
|
@ -3102,8 +3102,8 @@ _cairo_d2d_paint(void *surface,
|
||||||
reinterpret_cast<const cairo_surface_pattern_t*>(source);
|
reinterpret_cast<const cairo_surface_pattern_t*>(source);
|
||||||
|
|
||||||
status = _cairo_d2d_try_fastblit(d2dsurf, surf_pattern->surface,
|
status = _cairo_d2d_try_fastblit(d2dsurf, surf_pattern->surface,
|
||||||
NULL, &source->matrix, clip,
|
NULL, &source->matrix, clip,
|
||||||
op, source->filter);
|
op, source->filter);
|
||||||
|
|
||||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
return status;
|
return status;
|
||||||
|
@ -3230,7 +3230,7 @@ _cairo_d2d_mask(void *surface,
|
||||||
&source->matrix,
|
&source->matrix,
|
||||||
clip,
|
clip,
|
||||||
op,
|
op,
|
||||||
source->filter,
|
source->filter,
|
||||||
solidAlphaValue);
|
solidAlphaValue);
|
||||||
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -3432,8 +3432,8 @@ _cairo_d2d_fill(void *surface,
|
||||||
const cairo_surface_pattern_t *surf_pattern =
|
const cairo_surface_pattern_t *surf_pattern =
|
||||||
reinterpret_cast<const cairo_surface_pattern_t*>(source);
|
reinterpret_cast<const cairo_surface_pattern_t*>(source);
|
||||||
cairo_int_status_t rv = _cairo_d2d_try_fastblit(d2dsurf, surf_pattern->surface,
|
cairo_int_status_t rv = _cairo_d2d_try_fastblit(d2dsurf, surf_pattern->surface,
|
||||||
&box, &source->matrix, clip, op,
|
&box, &source->matrix, clip, op,
|
||||||
source->filter);
|
source->filter);
|
||||||
|
|
||||||
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -3583,7 +3583,11 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with rendering modes CreateGlyphRunAnalysis doesn't accept.
|
// Deal with rendering modes CreateGlyphRunAnalysis doesn't accept.
|
||||||
if (renderMode == DWRITE_RENDERING_MODE_DEFAULT) {
|
switch (renderMode) {
|
||||||
|
case DWRITE_RENDERING_MODE_ALIASED:
|
||||||
|
// ClearType texture creation will fail in this mode, so bail out
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
case DWRITE_RENDERING_MODE_DEFAULT:
|
||||||
// As per DWRITE_RENDERING_MODE documentation, pick Natural for font
|
// As per DWRITE_RENDERING_MODE documentation, pick Natural for font
|
||||||
// sizes under 16 ppem
|
// sizes under 16 ppem
|
||||||
if (scaled_font->base.font_matrix.yy < 16.0f) {
|
if (scaled_font->base.font_matrix.yy < 16.0f) {
|
||||||
|
@ -3591,15 +3595,24 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
|
||||||
} else {
|
} else {
|
||||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||||
}
|
}
|
||||||
} else if (renderMode == DWRITE_RENDERING_MODE_OUTLINE) {
|
break;
|
||||||
|
case DWRITE_RENDERING_MODE_OUTLINE:
|
||||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWRITE_MEASURING_MODE measureMode =
|
||||||
|
renderMode <= DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC ? DWRITE_MEASURING_MODE_GDI_CLASSIC :
|
||||||
|
renderMode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL ? DWRITE_MEASURING_MODE_GDI_NATURAL :
|
||||||
|
DWRITE_MEASURING_MODE_NATURAL;
|
||||||
|
|
||||||
hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
||||||
1.0f,
|
1.0f,
|
||||||
transform ? &dwmat : 0,
|
transform ? &dwmat : 0,
|
||||||
renderMode,
|
renderMode,
|
||||||
DWRITE_MEASURING_MODE_NATURAL,
|
measureMode,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
&analysis);
|
&analysis);
|
||||||
|
@ -3799,7 +3812,7 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
|
||||||
ID3D10EffectVectorVariable *textColor = effect->GetVariableByName("TextColor")->AsVector();
|
ID3D10EffectVectorVariable *textColor = effect->GetVariableByName("TextColor")->AsVector();
|
||||||
|
|
||||||
float colorVal[] = { float(source->color.red * source->color.alpha),
|
float colorVal[] = { float(source->color.red * source->color.alpha),
|
||||||
float(source->color.green * source->color.alpha),
|
float(source->color.green * source->color.alpha),
|
||||||
float(source->color.blue * source->color.alpha),
|
float(source->color.blue * source->color.alpha),
|
||||||
float(source->color.alpha) };
|
float(source->color.alpha) };
|
||||||
textColor->SetFloatVector(colorVal);
|
textColor->SetFloatVector(colorVal);
|
||||||
|
@ -3919,18 +3932,62 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||||
cleartype_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
cleartype_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dwritesf->antialias_mode) {
|
RefPtr<IDWriteRenderingParams> params;
|
||||||
case CAIRO_ANTIALIAS_NONE:
|
target_rt->GetTextRenderingParams(¶ms);
|
||||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
|
||||||
break;
|
DWRITE_RENDERING_MODE renderMode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||||
case CAIRO_ANTIALIAS_GRAY:
|
if (params) {
|
||||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
HRESULT hr = dwriteff->dwriteface->GetRecommendedRenderingMode(
|
||||||
break;
|
(FLOAT)dwritesf->base.font_matrix.yy,
|
||||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
1.0f,
|
||||||
target_rt->SetTextAntialiasMode(cleartype_quality);
|
DWRITE_MEASURING_MODE_NATURAL,
|
||||||
break;
|
params,
|
||||||
|
&renderMode);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
// this probably never happens, but let's play it safe
|
||||||
|
renderMode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deal with rendering modes CreateGlyphRunAnalysis doesn't accept
|
||||||
|
switch (renderMode) {
|
||||||
|
case DWRITE_RENDERING_MODE_DEFAULT:
|
||||||
|
// As per DWRITE_RENDERING_MODE documentation, pick Natural for font
|
||||||
|
// sizes under 16 ppem
|
||||||
|
if (dwritesf->base.font_matrix.yy < 16.0f) {
|
||||||
|
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
|
||||||
|
} else {
|
||||||
|
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DWRITE_RENDERING_MODE_OUTLINE:
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dwritesf->antialias_mode) {
|
||||||
|
case CAIRO_ANTIALIAS_NONE:
|
||||||
|
cleartype_quality = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||||
|
break;
|
||||||
|
case CAIRO_ANTIALIAS_GRAY:
|
||||||
|
cleartype_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderMode == DWRITE_RENDERING_MODE_ALIASED) {
|
||||||
|
cleartype_quality = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_rt->SetTextAntialiasMode(cleartype_quality);
|
||||||
|
|
||||||
|
DWRITE_MEASURING_MODE measureMode =
|
||||||
|
renderMode <= DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC ? DWRITE_MEASURING_MODE_GDI_CLASSIC :
|
||||||
|
renderMode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL ? DWRITE_MEASURING_MODE_GDI_NATURAL :
|
||||||
|
DWRITE_MEASURING_MODE_NATURAL;
|
||||||
|
|
||||||
cairo_bool_t transform = FALSE;
|
cairo_bool_t transform = FALSE;
|
||||||
|
|
||||||
DWRITE_GLYPH_RUN run;
|
DWRITE_GLYPH_RUN run;
|
||||||
|
@ -3949,8 +4006,8 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||||
DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
||||||
1.0f,
|
1.0f,
|
||||||
transform ? &dwmat : 0,
|
transform ? &dwmat : 0,
|
||||||
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
|
renderMode,
|
||||||
DWRITE_MEASURING_MODE_NATURAL,
|
measureMode,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
&analysis);
|
&analysis);
|
||||||
|
@ -3987,7 +4044,7 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||||
brush->SetTransform(&mat_brush);
|
brush->SetTransform(&mat_brush);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush, dwritesf->measuring_mode);
|
target_rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush, measureMode);
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||||
|
@ -4019,14 +4076,13 @@ _cairo_d2d_show_glyphs (void *surface,
|
||||||
}
|
}
|
||||||
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
|
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
|
||||||
if (!d2dsurf->textRenderingInit) {
|
if (!d2dsurf->textRenderingInit) {
|
||||||
RefPtr<IDWriteRenderingParams> params;
|
RefPtr<IDWriteRenderingParams> params = DWriteFactory::RenderingParams();
|
||||||
DWriteFactory::Instance()->CreateRenderingParams(¶ms);
|
|
||||||
d2dsurf->rt->SetTextRenderingParams(params);
|
d2dsurf->rt->SetTextRenderingParams(params);
|
||||||
d2dsurf->textRenderingInit = true;
|
d2dsurf->textRenderingInit = true;
|
||||||
}
|
}
|
||||||
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
|
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
|
||||||
status = (cairo_int_status_t)
|
status = (cairo_int_status_t)
|
||||||
_cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
|
_cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4131,7 +4187,7 @@ cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
|
||||||
}
|
}
|
||||||
/** Get the backbuffer surface from the swap chain */
|
/** Get the backbuffer surface from the swap chain */
|
||||||
hr = newSurf->dxgiChain->GetBuffer(0,
|
hr = newSurf->dxgiChain->GetBuffer(0,
|
||||||
IID_PPV_ARGS(&newSurf->surface));
|
IID_PPV_ARGS(&newSurf->surface));
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto FAIL_HWND;
|
goto FAIL_HWND;
|
||||||
|
@ -4176,8 +4232,8 @@ FAIL_HWND:
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
cairo_d2d_surface_create(cairo_device_t *device,
|
cairo_d2d_surface_create(cairo_device_t *device,
|
||||||
cairo_format_t format,
|
cairo_format_t format,
|
||||||
int width,
|
int width,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE));
|
return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE));
|
||||||
|
@ -4474,7 +4530,7 @@ FAIL_CREATE:
|
||||||
void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip)
|
void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip)
|
||||||
{
|
{
|
||||||
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
||||||
|
|
||||||
|
@ -4537,7 +4593,7 @@ HDC
|
||||||
cairo_d2d_get_dc(cairo_surface_t *surface, cairo_bool_t retain_contents)
|
cairo_d2d_get_dc(cairo_surface_t *surface, cairo_bool_t retain_contents)
|
||||||
{
|
{
|
||||||
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
||||||
|
|
||||||
|
@ -4578,7 +4634,7 @@ void
|
||||||
cairo_d2d_release_dc(cairo_surface_t *surface, const cairo_rectangle_int_t *updated_rect)
|
cairo_d2d_release_dc(cairo_surface_t *surface, const cairo_rectangle_int_t *updated_rect)
|
||||||
{
|
{
|
||||||
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,13 @@ private:
|
||||||
|
|
||||||
IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
|
IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
|
||||||
IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
|
IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
|
||||||
|
IDWriteRenderingParams *DWriteFactory::mRenderingParams = NULL;
|
||||||
|
FLOAT DWriteFactory::mGamma = -1.0;
|
||||||
|
FLOAT DWriteFactory::mEnhancedContrast = -1.0;
|
||||||
|
FLOAT DWriteFactory::mClearTypeLevel = -1.0;
|
||||||
|
int DWriteFactory::mPixelGeometry = -1;
|
||||||
|
int DWriteFactory::mRenderingMode = -1;
|
||||||
|
|
||||||
ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
|
ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
|
||||||
ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
|
ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
|
||||||
|
|
||||||
|
@ -298,7 +305,6 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
// Cannot use C++ style new since cairo deallocates this.
|
// Cannot use C++ style new since cairo deallocates this.
|
||||||
*font_face = (cairo_font_face_t*)face;
|
*font_face = (cairo_font_face_t*)face;
|
||||||
|
|
||||||
_cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
|
_cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
|
||||||
} else {
|
} else {
|
||||||
free(face);
|
free(face);
|
||||||
|
@ -349,7 +355,7 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
|
||||||
scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
|
scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
|
||||||
scaled_font->mat.yy == scaled_font->base.font_matrix.yy) {
|
scaled_font->mat.yy == scaled_font->base.font_matrix.yy) {
|
||||||
// Fast route, don't actually use a transform but just
|
// Fast route, don't actually use a transform but just
|
||||||
// set the correct font size.
|
// set the correct font size.
|
||||||
*transformed = 0;
|
*transformed = 0;
|
||||||
|
|
||||||
run->fontEmSize = (FLOAT)scaled_font->base.font_matrix.yy;
|
run->fontEmSize = (FLOAT)scaled_font->base.font_matrix.yy;
|
||||||
|
@ -371,14 +377,14 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
|
||||||
cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
|
cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
|
||||||
// Since we will multiply by our ctm matrix later for rotation effects
|
// Since we will multiply by our ctm matrix later for rotation effects
|
||||||
// and such, adjust positions by the inverse matrix now. Y-axis is
|
// and such, adjust positions by the inverse matrix now. Y-axis is
|
||||||
// inverted! Therefor the offset is -y.
|
// inverted! Therefor the offset is -y.
|
||||||
offsets[i].ascenderOffset = -(FLOAT)y;
|
offsets[i].ascenderOffset = -(FLOAT)y;
|
||||||
offsets[i].advanceOffset = (FLOAT)x;
|
offsets[i].advanceOffset = (FLOAT)x;
|
||||||
advances[i] = 0.0;
|
advances[i] = 0.0;
|
||||||
}
|
}
|
||||||
// The font matrix takes care of the scaling if we have a transform,
|
// The font matrix takes care of the scaling if we have a transform,
|
||||||
// emSize should be 1.
|
// emSize should be 1.
|
||||||
run->fontEmSize = 1.0f;
|
run->fontEmSize = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,22 +721,22 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
|
||||||
|
|
||||||
// TODO: Treat swap_xy.
|
// TODO: Treat swap_xy.
|
||||||
extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) /
|
extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) /
|
||||||
fontMetrics.designUnitsPerEm;
|
fontMetrics.designUnitsPerEm;
|
||||||
extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) /
|
extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) /
|
||||||
fontMetrics.designUnitsPerEm;
|
fontMetrics.designUnitsPerEm;
|
||||||
extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm;
|
extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm;
|
||||||
extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm;
|
extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm;
|
||||||
extents.y_advance = 0.0;
|
extents.y_advance = 0.0;
|
||||||
extents.y_bearing = (FLOAT)(metrics.topSideBearing - metrics.verticalOriginY) /
|
extents.y_bearing = (FLOAT)(metrics.topSideBearing - metrics.verticalOriginY) /
|
||||||
fontMetrics.designUnitsPerEm;
|
fontMetrics.designUnitsPerEm;
|
||||||
|
|
||||||
// We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics
|
// We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics
|
||||||
// for the glyph outline, without accounting for hinting/gridfitting/antialiasing,
|
// for the glyph outline, without accounting for hinting/gridfitting/antialiasing,
|
||||||
// and therefore it does not always cover all pixels that will actually be touched.
|
// and therefore it does not always cover all pixels that will actually be touched.
|
||||||
if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE &&
|
if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE &&
|
||||||
extents.width > 0 && extents.height > 0) {
|
extents.width > 0 && extents.height > 0) {
|
||||||
extents.width += scaled_font->mat_inverse.xx * 2;
|
extents.width += scaled_font->mat_inverse.xx * 2;
|
||||||
extents.x_bearing -= scaled_font->mat_inverse.xx;
|
extents.x_bearing -= scaled_font->mat_inverse.xx;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||||
|
@ -753,22 +759,22 @@ public:
|
||||||
// IUnknown interface
|
// IUnknown interface
|
||||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||||
{
|
{
|
||||||
if (iid != __uuidof(IDWriteGeometrySink))
|
if (iid != __uuidof(IDWriteGeometrySink))
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
*ppObject = static_cast<IDWriteGeometrySink*>(this);
|
*ppObject = static_cast<IDWriteGeometrySink*>(this);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHOD_(ULONG, AddRef)()
|
IFACEMETHOD_(ULONG, AddRef)()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHOD_(ULONG, Release)()
|
IFACEMETHOD_(ULONG, Release)()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode)
|
IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode)
|
||||||
|
@ -822,7 +828,7 @@ public:
|
||||||
|
|
||||||
IFACEMETHODIMP_(void) AddBeziers(
|
IFACEMETHODIMP_(void) AddBeziers(
|
||||||
const D2D1_BEZIER_SEGMENT *beziers,
|
const D2D1_BEZIER_SEGMENT *beziers,
|
||||||
UINT beziersCount)
|
UINT beziersCount)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < beziersCount; i++) {
|
for (unsigned int i = 0; i < beziersCount; i++) {
|
||||||
cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
|
cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
|
||||||
|
@ -837,7 +843,7 @@ public:
|
||||||
|
|
||||||
IFACEMETHODIMP_(void) AddLines(
|
IFACEMETHODIMP_(void) AddLines(
|
||||||
const D2D1_POINT_2F *points,
|
const D2D1_POINT_2F *points,
|
||||||
UINT pointsCount)
|
UINT pointsCount)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < pointsCount; i++) {
|
for (unsigned int i = 0; i < pointsCount; i++) {
|
||||||
cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
|
cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
|
||||||
|
@ -853,7 +859,7 @@ private:
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
|
_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
|
||||||
cairo_scaled_glyph_t *scaled_glyph)
|
cairo_scaled_glyph_t *scaled_glyph)
|
||||||
{
|
{
|
||||||
cairo_path_fixed_t *path;
|
cairo_path_fixed_t *path;
|
||||||
path = _cairo_path_fixed_create();
|
path = _cairo_path_fixed_create();
|
||||||
|
@ -999,8 +1005,8 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
|
||||||
|
|
||||||
cairo_surface_set_device_offset (image, -x1, -y1);
|
cairo_surface_set_device_offset (image, -x1, -y1);
|
||||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||||
&scaled_font->base,
|
&scaled_font->base,
|
||||||
(cairo_image_surface_t *) image);
|
(cairo_image_surface_t *) image);
|
||||||
|
|
||||||
FAIL:
|
FAIL:
|
||||||
cairo_surface_destroy (&surface->base);
|
cairo_surface_destroy (&surface->base);
|
||||||
|
@ -1009,7 +1015,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
_cairo_dwrite_load_truetype_table(void *scaled_font,
|
_cairo_dwrite_load_truetype_table(void *scaled_font,
|
||||||
unsigned long tag,
|
unsigned long tag,
|
||||||
long offset,
|
long offset,
|
||||||
unsigned char *buffer,
|
unsigned char *buffer,
|
||||||
|
@ -1070,6 +1076,13 @@ cairo_dwrite_scaled_font_allow_manual_show_glyphs(void* dwrite_scaled_font, cair
|
||||||
font->manual_show_glyphs_allowed = allowed;
|
font->manual_show_glyphs_allowed = allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
|
||||||
|
int geometry, int mode)
|
||||||
|
{
|
||||||
|
DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
||||||
DWRITE_MATRIX *transform,
|
DWRITE_MATRIX *transform,
|
||||||
|
@ -1081,8 +1094,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
||||||
DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
|
DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
|
||||||
IDWriteBitmapRenderTarget *rt;
|
IDWriteBitmapRenderTarget *rt;
|
||||||
|
|
||||||
IDWriteRenderingParams *params;
|
IDWriteRenderingParams *params = DWriteFactory::RenderingParams();
|
||||||
DWriteFactory::Instance()->CreateRenderingParams(¶ms);
|
|
||||||
|
|
||||||
gdiInterop->CreateBitmapRenderTarget(surface->dc,
|
gdiInterop->CreateBitmapRenderTarget(surface->dc,
|
||||||
area.right - area.left,
|
area.right - area.left,
|
||||||
|
@ -1304,7 +1316,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
||||||
offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
|
offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
|
||||||
advances[i] = 0.0;
|
advances[i] = 0.0;
|
||||||
}
|
}
|
||||||
run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
|
run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
|
||||||
} else {
|
} else {
|
||||||
transform = TRUE;
|
transform = TRUE;
|
||||||
|
|
||||||
|
@ -1314,10 +1326,10 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
||||||
double y = glyphs[i].y - fontArea.top;
|
double y = glyphs[i].y - fontArea.top;
|
||||||
cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
|
cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
|
||||||
/**
|
/**
|
||||||
* Since we will multiply by our ctm matrix later for rotation effects
|
* Since we will multiply by our ctm matrix later for rotation effects
|
||||||
* and such, adjust positions by the inverse matrix now. The Y-axis
|
* and such, adjust positions by the inverse matrix now. The Y-axis
|
||||||
* is inverted so the offset becomes negative.
|
* is inverted so the offset becomes negative.
|
||||||
*/
|
*/
|
||||||
offsets[i].ascenderOffset = -(FLOAT)y;
|
offsets[i].ascenderOffset = -(FLOAT)y;
|
||||||
offsets[i].advanceOffset = (FLOAT)x;
|
offsets[i].advanceOffset = (FLOAT)x;
|
||||||
advances[i] = 0.0;
|
advances[i] = 0.0;
|
||||||
|
@ -1370,6 +1382,49 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
||||||
return CAIRO_INT_STATUS_SUCCESS;
|
return CAIRO_INT_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ENHANCED_CONTRAST_REGISTRY_KEY \
|
||||||
|
HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
|
||||||
|
|
||||||
|
void
|
||||||
|
DWriteFactory::CreateRenderingParams()
|
||||||
|
{
|
||||||
|
if (!Instance()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<IDWriteRenderingParams> defaultParams;
|
||||||
|
Instance()->CreateRenderingParams(&defaultParams);
|
||||||
|
|
||||||
|
// For EnhancedContrast, we override the default if the user has not set it
|
||||||
|
// in the registry (by using the ClearType Tuner).
|
||||||
|
FLOAT contrast;
|
||||||
|
if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) {
|
||||||
|
contrast = mEnhancedContrast;
|
||||||
|
} else {
|
||||||
|
HKEY hKey;
|
||||||
|
if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
|
||||||
|
0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
contrast = defaultParams->GetEnhancedContrast();
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
} else {
|
||||||
|
contrast = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For parameters that have not been explicitly set via the SetRenderingParams API,
|
||||||
|
// we copy values from default params (or our overridden value for contrast)
|
||||||
|
Instance()->CreateCustomRenderingParams(
|
||||||
|
mGamma >= 1.0 && mGamma <= 2.2 ? mGamma : defaultParams->GetGamma(),
|
||||||
|
contrast,
|
||||||
|
mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? mClearTypeLevel : defaultParams->GetClearTypeLevel(),
|
||||||
|
mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
|
||||||
|
(DWRITE_PIXEL_GEOMETRY)mPixelGeometry : defaultParams->GetPixelGeometry(),
|
||||||
|
mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
|
||||||
|
(DWRITE_RENDERING_MODE)mRenderingMode : defaultParams->GetRenderingMode(),
|
||||||
|
&mRenderingParams);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
|
// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
|
||||||
// of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
|
// of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
|
||||||
// paths or blitting glyph bitmaps.
|
// paths or blitting glyph bitmaps.
|
||||||
|
|
|
@ -92,9 +92,46 @@ public:
|
||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IDWriteRenderingParams *RenderingParams()
|
||||||
|
{
|
||||||
|
if (!mRenderingParams) {
|
||||||
|
CreateRenderingParams();
|
||||||
|
}
|
||||||
|
if (mRenderingParams) {
|
||||||
|
mRenderingParams->AddRef();
|
||||||
|
}
|
||||||
|
return mRenderingParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetRenderingParams(FLOAT aGamma,
|
||||||
|
FLOAT aEnhancedContrast,
|
||||||
|
FLOAT aClearTypeLevel,
|
||||||
|
int aPixelGeometry,
|
||||||
|
int aRenderingMode)
|
||||||
|
{
|
||||||
|
mGamma = aGamma;
|
||||||
|
mEnhancedContrast = aEnhancedContrast;
|
||||||
|
mClearTypeLevel = aClearTypeLevel;
|
||||||
|
mPixelGeometry = aPixelGeometry;
|
||||||
|
mRenderingMode = aRenderingMode;
|
||||||
|
// discard any current RenderingParams object
|
||||||
|
if (mRenderingParams) {
|
||||||
|
mRenderingParams->Release();
|
||||||
|
mRenderingParams = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void CreateRenderingParams();
|
||||||
|
|
||||||
static IDWriteFactory *mFactoryInstance;
|
static IDWriteFactory *mFactoryInstance;
|
||||||
static IDWriteFontCollection *mSystemCollection;
|
static IDWriteFontCollection *mSystemCollection;
|
||||||
|
static IDWriteRenderingParams *mRenderingParams;
|
||||||
|
static FLOAT mGamma;
|
||||||
|
static FLOAT mEnhancedContrast;
|
||||||
|
static FLOAT mClearTypeLevel;
|
||||||
|
static int mPixelGeometry;
|
||||||
|
static int mRenderingMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* cairo_font_face_t implementation */
|
/* cairo_font_face_t implementation */
|
||||||
|
|
|
@ -126,6 +126,9 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void *dwrite_font, void *dwrit
|
||||||
void
|
void
|
||||||
cairo_dwrite_scaled_font_allow_manual_show_glyphs(void *dwrite_scaled_font, cairo_bool_t allowed);
|
cairo_dwrite_scaled_font_allow_manual_show_glyphs(void *dwrite_scaled_font, cairo_bool_t allowed);
|
||||||
|
|
||||||
|
void
|
||||||
|
cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
|
||||||
|
|
||||||
#endif /* CAIRO_HAS_DWRITE_FONT */
|
#endif /* CAIRO_HAS_DWRITE_FONT */
|
||||||
|
|
||||||
#if CAIRO_HAS_D2D_SURFACE
|
#if CAIRO_HAS_D2D_SURFACE
|
||||||
|
|
|
@ -149,7 +149,10 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((anAAOption == gfxFont::kAntialiasDefault && UsingClearType()) ||
|
if ((anAAOption == gfxFont::kAntialiasDefault &&
|
||||||
|
UsingClearType() &&
|
||||||
|
(gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
|
||||||
|
DWRITE_MEASURING_MODE_NATURAL)) ||
|
||||||
anAAOption == gfxFont::kAntialiasSubpixel)
|
anAAOption == gfxFont::kAntialiasSubpixel)
|
||||||
{
|
{
|
||||||
mUseSubpixelPositions = PR_TRUE;
|
mUseSubpixelPositions = PR_TRUE;
|
||||||
|
@ -248,16 +251,12 @@ gfxDWriteFont::ComputeMetrics()
|
||||||
mMetrics = new gfxFont::Metrics;
|
mMetrics = new gfxFont::Metrics;
|
||||||
::memset(mMetrics, 0, sizeof(*mMetrics));
|
::memset(mMetrics, 0, sizeof(*mMetrics));
|
||||||
|
|
||||||
mMetrics->xHeight =
|
mFUnitsConvFactor = float(mAdjustedSize / fontMetrics.designUnitsPerEm);
|
||||||
((gfxFloat)fontMetrics.xHeight /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
|
|
||||||
mMetrics->maxAscent =
|
mMetrics->xHeight = fontMetrics.xHeight * mFUnitsConvFactor;
|
||||||
ceil(((gfxFloat)fontMetrics.ascent /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize);
|
mMetrics->maxAscent = ceil(fontMetrics.ascent * mFUnitsConvFactor);
|
||||||
mMetrics->maxDescent =
|
mMetrics->maxDescent = ceil(fontMetrics.descent * mFUnitsConvFactor);
|
||||||
ceil(((gfxFloat)fontMetrics.descent /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize);
|
|
||||||
mMetrics->maxHeight = mMetrics->maxAscent + mMetrics->maxDescent;
|
mMetrics->maxHeight = mMetrics->maxAscent + mMetrics->maxDescent;
|
||||||
|
|
||||||
mMetrics->emHeight = mAdjustedSize;
|
mMetrics->emHeight = mAdjustedSize;
|
||||||
|
@ -282,88 +281,72 @@ gfxDWriteFont::ComputeMetrics()
|
||||||
if (exists && len >= sizeof(mozilla::HheaTable)) {
|
if (exists && len >= sizeof(mozilla::HheaTable)) {
|
||||||
const mozilla::HheaTable* hhea =
|
const mozilla::HheaTable* hhea =
|
||||||
reinterpret_cast<const mozilla::HheaTable*>(tableData);
|
reinterpret_cast<const mozilla::HheaTable*>(tableData);
|
||||||
mMetrics->maxAdvance = ((gfxFloat)PRUint16(hhea->advanceWidthMax) /
|
mMetrics->maxAdvance =
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
PRUint16(hhea->advanceWidthMax) * mFUnitsConvFactor;
|
||||||
}
|
}
|
||||||
mFontFace->ReleaseFontTable(tableContext);
|
mFontFace->ReleaseFontTable(tableContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
mMetrics->internalLeading = NS_MAX(mMetrics->maxHeight - mMetrics->emHeight, 0.0);
|
mMetrics->internalLeading = NS_MAX(mMetrics->maxHeight - mMetrics->emHeight, 0.0);
|
||||||
mMetrics->externalLeading =
|
mMetrics->externalLeading = ceil(fontMetrics.lineGap * mFUnitsConvFactor);
|
||||||
ceil(((gfxFloat)fontMetrics.lineGap /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize);
|
|
||||||
|
|
||||||
UINT16 glyph = (PRUint16)GetSpaceGlyph();
|
UINT16 glyph = (PRUint16)GetSpaceGlyph();
|
||||||
DWRITE_GLYPH_METRICS metrics;
|
mMetrics->spaceWidth = MeasureGlyphWidth(glyph);
|
||||||
mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics);
|
|
||||||
mMetrics->spaceWidth =
|
|
||||||
((gfxFloat)metrics.advanceWidth /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
|
|
||||||
// try to get aveCharWidth from the OS/2 table, fall back to measuring 'x'
|
// try to get aveCharWidth from the OS/2 table, fall back to measuring 'x'
|
||||||
// if the table is not available
|
// if the table is not available or if using hinted/pixel-snapped widths
|
||||||
mMetrics->aveCharWidth = 0;
|
if (mUseSubpixelPositions) {
|
||||||
hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('O', 'S', '/', '2'),
|
mMetrics->aveCharWidth = 0;
|
||||||
(const void**)&tableData,
|
hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('O', 'S', '/', '2'),
|
||||||
&len,
|
(const void**)&tableData,
|
||||||
&tableContext,
|
&len,
|
||||||
&exists);
|
&tableContext,
|
||||||
if (SUCCEEDED(hr)) {
|
&exists);
|
||||||
if (exists && len >= 4) {
|
if (SUCCEEDED(hr)) {
|
||||||
// Not checking against sizeof(mozilla::OS2Table) here because older
|
if (exists && len >= 4) {
|
||||||
// versions of the table have different sizes; we only need the first
|
// Not checking against sizeof(mozilla::OS2Table) here because older
|
||||||
// two 16-bit fields here.
|
// versions of the table have different sizes; we only need the first
|
||||||
const mozilla::OS2Table* os2 =
|
// two 16-bit fields here.
|
||||||
reinterpret_cast<const mozilla::OS2Table*>(tableData);
|
const mozilla::OS2Table* os2 =
|
||||||
mMetrics->aveCharWidth = ((gfxFloat)PRInt16(os2->xAvgCharWidth) /
|
reinterpret_cast<const mozilla::OS2Table*>(tableData);
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
mMetrics->aveCharWidth =
|
||||||
|
PRInt16(os2->xAvgCharWidth) * mFUnitsConvFactor;
|
||||||
|
}
|
||||||
|
mFontFace->ReleaseFontTable(tableContext);
|
||||||
}
|
}
|
||||||
mFontFace->ReleaseFontTable(tableContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 ucs;
|
UINT32 ucs;
|
||||||
if (mMetrics->aveCharWidth < 1) {
|
if (mMetrics->aveCharWidth < 1) {
|
||||||
ucs = L'x';
|
ucs = L'x';
|
||||||
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph)) &&
|
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph))) {
|
||||||
SUCCEEDED(mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics))) {
|
mMetrics->aveCharWidth = MeasureGlyphWidth(glyph);
|
||||||
mMetrics->aveCharWidth =
|
}
|
||||||
((gfxFloat)metrics.advanceWidth /
|
if (mMetrics->aveCharWidth < 1) {
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
} else {
|
|
||||||
// Let's just assume the X is square.
|
// Let's just assume the X is square.
|
||||||
mMetrics->aveCharWidth =
|
mMetrics->aveCharWidth = fontMetrics.xHeight * mFUnitsConvFactor;
|
||||||
((gfxFloat)fontMetrics.xHeight /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ucs = L'0';
|
ucs = L'0';
|
||||||
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph)) &&
|
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph))) {
|
||||||
SUCCEEDED(mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics))) {
|
mMetrics->zeroOrAveCharWidth = MeasureGlyphWidth(glyph);
|
||||||
mMetrics->zeroOrAveCharWidth =
|
}
|
||||||
((gfxFloat)metrics.advanceWidth /
|
if (mMetrics->zeroOrAveCharWidth < 1) {
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
} else {
|
|
||||||
mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
|
mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
mMetrics->underlineOffset =
|
mMetrics->underlineOffset =
|
||||||
((gfxFloat)fontMetrics.underlinePosition /
|
fontMetrics.underlinePosition * mFUnitsConvFactor;
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
mMetrics->underlineSize =
|
mMetrics->underlineSize =
|
||||||
((gfxFloat)fontMetrics.underlineThickness /
|
fontMetrics.underlineThickness * mFUnitsConvFactor;
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
mMetrics->strikeoutOffset =
|
||||||
mMetrics->strikeoutOffset =
|
fontMetrics.strikethroughPosition * mFUnitsConvFactor;
|
||||||
((gfxFloat)fontMetrics.strikethroughPosition /
|
mMetrics->strikeoutSize =
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
fontMetrics.strikethroughThickness * mFUnitsConvFactor;
|
||||||
mMetrics->strikeoutSize =
|
|
||||||
((gfxFloat)fontMetrics.strikethroughThickness /
|
|
||||||
fontMetrics.designUnitsPerEm) * mAdjustedSize;
|
|
||||||
mMetrics->superscriptOffset = 0;
|
mMetrics->superscriptOffset = 0;
|
||||||
mMetrics->subscriptOffset = 0;
|
mMetrics->subscriptOffset = 0;
|
||||||
|
|
||||||
mFUnitsConvFactor = float(mAdjustedSize / fontMetrics.designUnitsPerEm);
|
|
||||||
|
|
||||||
SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
|
SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -697,26 +680,30 @@ gfxDWriteFont::GetGlyphWidth(gfxContext *aCtx, PRUint16 aGID)
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWRITE_GLYPH_METRICS glyphMetrics;
|
width = NS_lround(MeasureGlyphWidth(aGID) * 65536.0);
|
||||||
HRESULT hr;
|
|
||||||
if (mUseSubpixelPositions) {
|
|
||||||
hr = mFontFace->GetDesignGlyphMetrics(
|
|
||||||
&aGID, 1, &glyphMetrics, FALSE);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
width =
|
|
||||||
NS_lround(glyphMetrics.advanceWidth * mFUnitsConvFactor *
|
|
||||||
65536.0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hr = mFontFace->GetGdiCompatibleGlyphMetrics(
|
|
||||||
FLOAT(mAdjustedSize), 1.0f, nsnull, FALSE,
|
|
||||||
&aGID, 1, &glyphMetrics, FALSE);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
width =
|
|
||||||
NS_lround(glyphMetrics.advanceWidth * mFUnitsConvFactor) << 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mGlyphWidths.Put(aGID, width);
|
mGlyphWidths.Put(aGID, width);
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxFloat
|
||||||
|
gfxDWriteFont::MeasureGlyphWidth(PRUint16 aGlyph)
|
||||||
|
{
|
||||||
|
DWRITE_GLYPH_METRICS metrics;
|
||||||
|
HRESULT hr;
|
||||||
|
if (mUseSubpixelPositions) {
|
||||||
|
hr = mFontFace->GetDesignGlyphMetrics(&aGlyph, 1, &metrics, FALSE);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
return metrics.advanceWidth * mFUnitsConvFactor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hr = mFontFace->GetGdiCompatibleGlyphMetrics(
|
||||||
|
FLOAT(mAdjustedSize), 1.0f, nsnull,
|
||||||
|
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
|
||||||
|
DWRITE_MEASURING_MODE_GDI_NATURAL,
|
||||||
|
&aGlyph, 1, &metrics, FALSE);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
return NS_lround(metrics.advanceWidth * mFUnitsConvFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -98,6 +98,8 @@ protected:
|
||||||
|
|
||||||
cairo_scaled_font_t *CairoScaledFont();
|
cairo_scaled_font_t *CairoScaledFont();
|
||||||
|
|
||||||
|
gfxFloat MeasureGlyphWidth(PRUint16 aGlyph);
|
||||||
|
|
||||||
static void DestroyBlobFunc(void* userArg);
|
static void DestroyBlobFunc(void* userArg);
|
||||||
|
|
||||||
nsRefPtr<IDWriteFontFace> mFontFace;
|
nsRefPtr<IDWriteFontFace> mFontFace;
|
||||||
|
|
|
@ -2666,7 +2666,6 @@ gfxFontGroup::GetGeneration()
|
||||||
void
|
void
|
||||||
gfxFontGroup::UpdateFontList()
|
gfxFontGroup::UpdateFontList()
|
||||||
{
|
{
|
||||||
// if user font set is set, check to see if font list needs updating
|
|
||||||
if (mUserFontSet && mCurrGeneration != GetGeneration()) {
|
if (mUserFontSet && mCurrGeneration != GetGeneration()) {
|
||||||
// xxx - can probably improve this to detect when all fonts were found, so no need to update list
|
// xxx - can probably improve this to detect when all fonts were found, so no need to update list
|
||||||
mFonts.Clear();
|
mFonts.Clear();
|
||||||
|
|
|
@ -58,6 +58,10 @@
|
||||||
#include "nsUnicodeRange.h"
|
#include "nsUnicodeRange.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
#include "gfxWindowsPlatform.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FloatToFixed(f) (65536 * (f))
|
#define FloatToFixed(f) (65536 * (f))
|
||||||
#define FixedToFloat(f) ((f) * (1.0 / 65536.0))
|
#define FixedToFloat(f) ((f) * (1.0 / 65536.0))
|
||||||
// Right shifts of negative (signed) integers are undefined, as are overflows
|
// Right shifts of negative (signed) integers are undefined, as are overflows
|
||||||
|
@ -946,8 +950,12 @@ GetRoundOffsetsToPixels(gfxContext *aContext,
|
||||||
#if CAIRO_HAS_DWRITE_FONT // dwrite backend is not in std cairo releases yet
|
#if CAIRO_HAS_DWRITE_FONT // dwrite backend is not in std cairo releases yet
|
||||||
case CAIRO_FONT_TYPE_DWRITE:
|
case CAIRO_FONT_TYPE_DWRITE:
|
||||||
// show_glyphs is implemented on the font and so is used for
|
// show_glyphs is implemented on the font and so is used for
|
||||||
// all surface types.
|
// all surface types; however, it may pixel-snap depending on
|
||||||
return;
|
// the dwrite rendering mode
|
||||||
|
if (gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
|
||||||
|
DWRITE_MEASURING_MODE_NATURAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
case CAIRO_FONT_TYPE_QUARTZ:
|
case CAIRO_FONT_TYPE_QUARTZ:
|
||||||
// Quartz surfaces implement show_glyphs for Quartz fonts
|
// Quartz surfaces implement show_glyphs for Quartz fonts
|
||||||
|
|
|
@ -158,6 +158,13 @@ NS_IMPL_ISUPPORTS1(D2DVRAMReporter, nsIMemoryReporter)
|
||||||
#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
|
#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
|
||||||
#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
|
#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
|
||||||
|
|
||||||
|
#define GFX_CLEARTYPE_PARAMS "gfx.font_rendering.cleartype_params."
|
||||||
|
#define GFX_CLEARTYPE_PARAMS_GAMMA "gfx.font_rendering.cleartype_params.gamma"
|
||||||
|
#define GFX_CLEARTYPE_PARAMS_CONTRAST "gfx.font_rendering.cleartype_params.enhanced_contrast"
|
||||||
|
#define GFX_CLEARTYPE_PARAMS_LEVEL "gfx.font_rendering.cleartype_params.cleartype_level"
|
||||||
|
#define GFX_CLEARTYPE_PARAMS_STRUCTURE "gfx.font_rendering.cleartype_params.pixel_structure"
|
||||||
|
#define GFX_CLEARTYPE_PARAMS_MODE "gfx.font_rendering.cleartype_params.rendering_mode"
|
||||||
|
|
||||||
#ifdef MOZ_FT2_FONTS
|
#ifdef MOZ_FT2_FONTS
|
||||||
static FT_Library gPlatformFTLibrary = NULL;
|
static FT_Library gPlatformFTLibrary = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -343,6 +350,8 @@ gfxWindowsPlatform::UpdateRenderMode()
|
||||||
mDWriteFactory = factory;
|
mDWriteFactory = factory;
|
||||||
factory->Release();
|
factory->Release();
|
||||||
|
|
||||||
|
SetupClearTypeParams(pref);
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
reporter.SetSuccessful();
|
reporter.SetSuccessful();
|
||||||
}
|
}
|
||||||
|
@ -790,6 +799,8 @@ gfxWindowsPlatform::FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aP
|
||||||
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
|
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
|
||||||
} else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
|
} else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
|
||||||
mUseClearTypeAlways = UNINITIALIZED_VALUE;
|
mUseClearTypeAlways = UNINITIALIZED_VALUE;
|
||||||
|
} else if (!strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
|
||||||
|
SetupClearTypeParams(aPrefBranch);
|
||||||
} else {
|
} else {
|
||||||
clearTextFontCaches = PR_FALSE;
|
clearTextFontCaches = PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -803,6 +814,67 @@ gfxWindowsPlatform::FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxWindowsPlatform::SetupClearTypeParams(nsIPrefBranch *aPrefBranch)
|
||||||
|
{
|
||||||
|
#if CAIRO_HAS_DWRITE_FONT
|
||||||
|
if (GetDWriteFactory()) {
|
||||||
|
// any missing prefs will default to invalid (-1) and be ignored;
|
||||||
|
// out-of-range values will also be ignored
|
||||||
|
FLOAT gamma = -1.0;
|
||||||
|
FLOAT contrast = -1.0;
|
||||||
|
FLOAT level = -1.0;
|
||||||
|
int geometry = -1;
|
||||||
|
int mode = -1;
|
||||||
|
PRInt32 value;
|
||||||
|
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(GFX_CLEARTYPE_PARAMS_GAMMA,
|
||||||
|
&value))) {
|
||||||
|
if (value >= 1000 && value <= 2200) {
|
||||||
|
gamma = (FLOAT)value / 1000.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(GFX_CLEARTYPE_PARAMS_CONTRAST,
|
||||||
|
&value))) {
|
||||||
|
if (value >= 0 && value <= 1000) {
|
||||||
|
contrast = (FLOAT)value / 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(GFX_CLEARTYPE_PARAMS_LEVEL,
|
||||||
|
&value))) {
|
||||||
|
if (value >= 0 && value <= 100) {
|
||||||
|
level = (FLOAT)value / 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(GFX_CLEARTYPE_PARAMS_STRUCTURE,
|
||||||
|
&value))) {
|
||||||
|
if (value >= 0 && value <= 2) {
|
||||||
|
geometry = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NS_SUCCEEDED(aPrefBranch->GetIntPref(GFX_CLEARTYPE_PARAMS_MODE,
|
||||||
|
&value))) {
|
||||||
|
if (value >= 0 && value <= 5) {
|
||||||
|
mode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cairo_dwrite_set_cleartype_params(gamma, contrast, level, geometry, mode);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case DWRITE_RENDERING_MODE_ALIASED:
|
||||||
|
case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC:
|
||||||
|
mMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
|
||||||
|
break;
|
||||||
|
case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL:
|
||||||
|
mMeasuringMode = DWRITE_MEASURING_MODE_GDI_NATURAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
gfxWindowsPlatform::IsOptimus()
|
gfxWindowsPlatform::IsOptimus()
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,9 +238,12 @@ public:
|
||||||
|
|
||||||
virtual void FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref);
|
virtual void FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref);
|
||||||
|
|
||||||
|
void SetupClearTypeParams(nsIPrefBranch *aPrefBranch);
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||||
IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
|
IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
|
||||||
inline PRBool DWriteEnabled() { return mUseDirectWrite; }
|
inline PRBool DWriteEnabled() { return mUseDirectWrite; }
|
||||||
|
inline DWRITE_MEASURING_MODE DWriteMeasuringMode() { return mMeasuringMode; }
|
||||||
#else
|
#else
|
||||||
inline PRBool DWriteEnabled() { return PR_FALSE; }
|
inline PRBool DWriteEnabled() { return PR_FALSE; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -270,6 +273,7 @@ private:
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||||
nsRefPtr<IDWriteFactory> mDWriteFactory;
|
nsRefPtr<IDWriteFactory> mDWriteFactory;
|
||||||
|
DWRITE_MEASURING_MODE mMeasuringMode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||||
cairo_device_t *mD2DDevice;
|
cairo_device_t *mD2DDevice;
|
||||||
|
|
|
@ -82,11 +82,7 @@ else
|
||||||
ELOG :=
|
ELOG :=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS_ARCH),WINNT)
|
|
||||||
_VPATH_SRCS = $(abspath $<)
|
_VPATH_SRCS = $(abspath $<)
|
||||||
else
|
|
||||||
_VPATH_SRCS = $<
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
|
# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
|
||||||
VPATH += $(DIST)/lib
|
VPATH += $(DIST)/lib
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
#elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX)
|
#elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
|
|
||||||
# if defined(__FreeBSD__)
|
# if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
# include <pthread_np.h>
|
# include <pthread_np.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
@ -446,8 +446,10 @@ public:
|
||||||
PRBool SendNativeEvents()
|
PRBool SendNativeEvents()
|
||||||
{
|
{
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
// XXX we should remove the plugin name check
|
||||||
return mPluginWindow->type == NPWindowTypeDrawable &&
|
return mPluginWindow->type == NPWindowTypeDrawable &&
|
||||||
MatchPluginName("Shockwave Flash");
|
(MatchPluginName("Shockwave Flash") ||
|
||||||
|
MatchPluginName("Test Plug-in"));
|
||||||
#elif defined(MOZ_X11) || defined(XP_MACOSX)
|
#elif defined(MOZ_X11) || defined(XP_MACOSX)
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -62,8 +62,8 @@ fails-if(Android) == 386339.html 386339-ref.html
|
||||||
== 409375.html 409375-ref.html
|
== 409375.html 409375-ref.html
|
||||||
== 413542-1.html 413542-1-ref.html
|
== 413542-1.html 413542-1-ref.html
|
||||||
== 413542-2.html 413542-2-ref.html
|
== 413542-2.html 413542-2-ref.html
|
||||||
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 413928-1.html 413928-1-ref.html
|
== 413928-1.html 413928-1-ref.html
|
||||||
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 413928-2.html 413928-2-ref.html
|
== 413928-2.html 413928-2-ref.html
|
||||||
== 425338-1a.html 425338-1-ref.html
|
== 425338-1a.html 425338-1-ref.html
|
||||||
== 425338-1b.html 425338-1-ref.html
|
== 425338-1b.html 425338-1-ref.html
|
||||||
== 489517-1.html 489517-1-ref.html
|
== 489517-1.html 489517-1-ref.html
|
||||||
|
|
|
@ -675,7 +675,7 @@ fails-if(Android) != 376532-3.html 376532-3-ref.html
|
||||||
== 379178-html.html 379178-html-ref.html
|
== 379178-html.html 379178-html-ref.html
|
||||||
== 379178-svg.svg 379178-svg-ref.svg
|
== 379178-svg.svg 379178-svg-ref.svg
|
||||||
== 379316-1.html 379316-1-ref.html
|
== 379316-1.html 379316-1-ref.html
|
||||||
fails-if(Android) random-if(cocoaWidget) == 379316-2.html 379316-2-ref.html # bug 379786
|
fails-if(Android) random-if(cocoaWidget) fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 379316-2.html 379316-2-ref.html # bug 379786
|
||||||
== 379328-1.html 379328-1-ref.html
|
== 379328-1.html 379328-1-ref.html
|
||||||
== 379349-1a.xhtml 379349-1-ref.xhtml
|
== 379349-1a.xhtml 379349-1-ref.xhtml
|
||||||
== 379349-1b.xhtml 379349-1-ref.xhtml
|
== 379349-1b.xhtml 379349-1-ref.xhtml
|
||||||
|
|
|
@ -196,6 +196,8 @@ fails-if(Android) random-if(gtk2Widget) != text-language-01.xhtml text-language-
|
||||||
== text-layout-03.svg text-layout-03-ref.svg
|
== text-layout-03.svg text-layout-03-ref.svg
|
||||||
== text-scale-01.svg text-scale-01-ref.svg
|
== text-scale-01.svg text-scale-01-ref.svg
|
||||||
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
|
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
|
||||||
|
== stroke-linecap-square-w-zero-length-segs-01.svg pass.svg
|
||||||
|
== stroke-linecap-square-w-zero-length-segs-02.svg pass.svg
|
||||||
== text-style-01a.svg text-style-01-ref.svg
|
== text-style-01a.svg text-style-01-ref.svg
|
||||||
== text-style-01b.svg text-style-01-ref.svg
|
== text-style-01b.svg text-style-01-ref.svg
|
||||||
== text-style-01c.svg text-style-01-ref.svg
|
== text-style-01c.svg text-style-01-ref.svg
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/licenses/publicdomain/
|
||||||
|
-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|
||||||
|
<title>Test 'stroke-linecap: square' with zero length path segments</title>
|
||||||
|
|
||||||
|
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=589648 -->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
path {
|
||||||
|
stroke-width: 20px;
|
||||||
|
stroke-linecap: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect {
|
||||||
|
fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect lime squares to cover red rects */
|
||||||
|
path.squares-expected {
|
||||||
|
stroke: lime;
|
||||||
|
}
|
||||||
|
|
||||||
|
path.squares-not-expected {
|
||||||
|
stroke: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* thicker stroke to cover squares-not-expected paths */
|
||||||
|
path.coverer {
|
||||||
|
stroke: lime;
|
||||||
|
stroke-width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to show edges of shapes to help in debugging:
|
||||||
|
g > rect {
|
||||||
|
stroke: red;
|
||||||
|
stroke-width: 5px;
|
||||||
|
}
|
||||||
|
path.coverer {
|
||||||
|
stroke: lime;
|
||||||
|
stroke-width: 18px;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<rect width="100%" height="100%" style="fill:lime"/>
|
||||||
|
|
||||||
|
<!-- Column 1: test single segment zero-length subpaths: -->
|
||||||
|
|
||||||
|
<g transform="translate(25,25)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 L0,0 M20,20 L30,30 M50,50 L50,50 M70,70 L80,80 M100,100 L100,100"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(25,75)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 C0,0 0,0 0,0 M20,20 L30,30 M50,50 C50,50 50,50 50,50 M70,70 L80,80 M100,100 C100,100 100,100 100,100"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(25,125)">
|
||||||
|
<path class="squares-not-expected" d="M0,0 A0,10 0 0 0 0,0 M20,20 L30,30 M50,50 A0,10 0 0 0 50,50 M70,70 L80,80 M100,100 A0,10 0 0 0 100,100"/>
|
||||||
|
<path class="coverer" d="M20,20 L30,30 M70,70 L80,80"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(25,175)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 Z M20,20 L30,30 M50,50 Z M70,70 L80,80 M100,100 Z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Column 2: test multi-segment zero-length subpaths: -->
|
||||||
|
|
||||||
|
<g transform="translate(175,25)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 L0,0 M0,0 L0,0 M20,20 L30,30 M50,50 L50,50 L50,50 M70,70 L80,80 M100,100 L100,100 L100,100"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(177,75)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 C0,0 0,0 0,0 C0,0 0,0 0,0 M20,20 L30,30 M50,50 C50,50 50,50 50,50 C50,50 50,50 50,50 M70,70 L80,80 M100,100 C100,100 100,100 100,100 C100,100 100,100 100,100"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(175,125)">
|
||||||
|
<path class="squares-not-expected" d="M0,0 A0,10 0 0 0 0,0 A0,10 0 0 0 0,0 M20,20 L30,30 M50,50 A0,10 0 0 0 50,50 A0,10 0 0 0 50,50 M70,70 L80,80 M100,100 A0,10 0 0 0 100,100 A0,10 0 0 0 100,100"/>
|
||||||
|
<path class="coverer" d="M20,20 L30,30 M70,70 L80,80"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(175,175)">
|
||||||
|
<rect x="-9" y="-9" width="18" height="18"/>
|
||||||
|
<rect x="41" y="41" width="18" height="18"/>
|
||||||
|
<rect x="91" y="91" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M0,0 Z Z M20,20 L30,30 M50,50 Z Z M70,70 L80,80 M100,100 Z Z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Column 3: test non-zero-length subpaths that begin, end and contain
|
||||||
|
zero length segments: -->
|
||||||
|
|
||||||
|
<g transform="translate(325,25)">
|
||||||
|
<path class="squares-not-expected" d="M20,20 L20,20 L30,30 L30,30 L40,40 L40,40"/>
|
||||||
|
<path class="coverer" d="M20,20 L40,40"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(325,75)">
|
||||||
|
<path class="squares-not-expected" d="M20,20 C20,20 20,20 20,20 C20,20 30,30 30,30 C30,30 30,30 30,30 C30,30 40,40 40,40 C40,40 40,40 40,40"/>
|
||||||
|
<path class="coverer" d="M20,20 L40,40"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g transform="translate(325,125)">
|
||||||
|
<path class="squares-not-expected" d="M20,20 A0,10 0 0 0 20,20 A0,10 0 0 0 30,30 A0,10 0 0 0 30,30 A0,10 0 0 0 40,40 A0,10 0 0 0 40,40"/>
|
||||||
|
<path class="coverer" d="M20,20 L40,40"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- this one is shorter because the Z's mean we only have path end points
|
||||||
|
at 20,20 -->
|
||||||
|
<g transform="translate(325,175)">
|
||||||
|
<rect x="11" y="11" width="18" height="18"/>
|
||||||
|
<path class="squares-expected" d="M20,20 Z L30,30 Z L40,40 Z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Column 4: test loan movetos -->
|
||||||
|
|
||||||
|
<g transform="translate(425,25)">
|
||||||
|
<path class="squares-not-expected" d="M0,0 M0,0 M20,20 L30,30 M50,50 M50,50 M70,70 L80,80 M100,100 M100,100"/>
|
||||||
|
<path class="coverer" d="M20,20 L30,30 M70,70 L80,80"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 4.7 KiB |
|
@ -0,0 +1,28 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/licenses/publicdomain/
|
||||||
|
-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
|
||||||
|
|
||||||
|
<title>Test 'stroke-linecap: square' with zero length path segments</title>
|
||||||
|
|
||||||
|
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=589648 -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function run()
|
||||||
|
{
|
||||||
|
document.getElementById('path').setAttribute('stroke-linecap', 'butt');
|
||||||
|
document.documentElement.removeAttribute('class');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("MozReftestInvalidate", run, false);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<rect width="100%" height="100%" style="fill:lime"/>
|
||||||
|
|
||||||
|
<path id="path" stroke="red" stroke-width="200" stroke-linecap="square"
|
||||||
|
d="M100,100 L100,100"/>
|
||||||
|
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 735 B |
|
@ -105,11 +105,6 @@ public:
|
||||||
NS_IMETHOD NotifyRedrawSuspended()=0;
|
NS_IMETHOD NotifyRedrawSuspended()=0;
|
||||||
NS_IMETHOD NotifyRedrawUnsuspended()=0;
|
NS_IMETHOD NotifyRedrawUnsuspended()=0;
|
||||||
|
|
||||||
// Set whether we should stop multiplying matrices when building up
|
|
||||||
// the current transformation matrix at this frame.
|
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate)=0;
|
|
||||||
virtual PRBool GetMatrixPropagation()=0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this frame's contribution to the rect returned by a GetBBox() call
|
* Get this frame's contribution to the rect returned by a GetBBox() call
|
||||||
* that occurred either on this element, or on one of its ancestors.
|
* that occurred either on this element, or on one of its ancestors.
|
||||||
|
|
|
@ -93,7 +93,7 @@ nsSVGContainerFrame::Init(nsIContent* aContent,
|
||||||
nsIFrame* aParent,
|
nsIFrame* aParent,
|
||||||
nsIFrame* aPrevInFlow)
|
nsIFrame* aPrevInFlow)
|
||||||
{
|
{
|
||||||
AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD);
|
||||||
nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
|
nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,6 @@ nsSVGDisplayContainerFrame::Init(nsIContent* aContent,
|
||||||
nsIFrame* aParent,
|
nsIFrame* aParent,
|
||||||
nsIFrame* aPrevInFlow)
|
nsIFrame* aPrevInFlow)
|
||||||
{
|
{
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
if (!(GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
|
if (!(GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
|
||||||
AddStateBits(aParent->GetStateBits() &
|
AddStateBits(aParent->GetStateBits() &
|
||||||
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
|
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
|
||||||
|
@ -283,20 +282,3 @@ nsSVGDisplayContainerFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspac
|
||||||
|
|
||||||
return bboxUnion;
|
return bboxUnion;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsSVGDisplayContainerFrame::SetMatrixPropagation(PRBool aPropagate)
|
|
||||||
{
|
|
||||||
if (aPropagate) {
|
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
} else {
|
|
||||||
RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsSVGDisplayContainerFrame::GetMatrixPropagation()
|
|
||||||
{
|
|
||||||
return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM) != 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -112,8 +112,6 @@ public:
|
||||||
virtual void NotifySVGChanged(PRUint32 aFlags);
|
virtual void NotifySVGChanged(PRUint32 aFlags);
|
||||||
NS_IMETHOD NotifyRedrawSuspended();
|
NS_IMETHOD NotifyRedrawSuspended();
|
||||||
NS_IMETHOD NotifyRedrawUnsuspended();
|
NS_IMETHOD NotifyRedrawUnsuspended();
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
|
||||||
virtual PRBool GetMatrixPropagation();
|
|
||||||
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
||||||
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_TRUE; }
|
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_TRUE; }
|
||||||
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_FALSE; }
|
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_FALSE; }
|
||||||
|
|
|
@ -91,9 +91,8 @@ nsSVGForeignObjectFrame::Init(nsIContent* aContent,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsresult rv = nsSVGForeignObjectFrameBase::Init(aContent, aParent, aPrevInFlow);
|
nsresult rv = nsSVGForeignObjectFrameBase::Init(aContent, aParent, aPrevInFlow);
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM |
|
AddStateBits(aParent->GetStateBits() &
|
||||||
(aParent->GetStateBits() &
|
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
|
||||||
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD)));
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
nsSVGUtils::GetOuterSVGFrame(this)->RegisterForeignObject(this);
|
nsSVGUtils::GetOuterSVGFrame(this)->RegisterForeignObject(this);
|
||||||
}
|
}
|
||||||
|
@ -432,23 +431,6 @@ nsSVGForeignObjectFrame::NotifyRedrawUnsuspended()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsSVGForeignObjectFrame::SetMatrixPropagation(PRBool aPropagate)
|
|
||||||
{
|
|
||||||
if (aPropagate) {
|
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
} else {
|
|
||||||
RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsSVGForeignObjectFrame::GetMatrixPropagation()
|
|
||||||
{
|
|
||||||
return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxRect
|
gfxRect
|
||||||
nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
|
nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,8 +128,6 @@ public:
|
||||||
virtual void NotifySVGChanged(PRUint32 aFlags);
|
virtual void NotifySVGChanged(PRUint32 aFlags);
|
||||||
NS_IMETHOD NotifyRedrawSuspended();
|
NS_IMETHOD NotifyRedrawSuspended();
|
||||||
NS_IMETHOD NotifyRedrawUnsuspended();
|
NS_IMETHOD NotifyRedrawUnsuspended();
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
|
||||||
virtual PRBool GetMatrixPropagation();
|
|
||||||
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
||||||
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_TRUE; }
|
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_TRUE; }
|
||||||
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
||||||
|
|
|
@ -52,9 +52,8 @@ nsSVGGeometryFrame::Init(nsIContent* aContent,
|
||||||
nsIFrame* aParent,
|
nsIFrame* aParent,
|
||||||
nsIFrame* aPrevInFlow)
|
nsIFrame* aPrevInFlow)
|
||||||
{
|
{
|
||||||
AddStateBits((aParent->GetStateBits() &
|
AddStateBits(aParent->GetStateBits() &
|
||||||
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD)) |
|
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
|
||||||
NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
nsresult rv = nsSVGGeometryFrameBase::Init(aContent, aParent, aPrevInFlow);
|
nsresult rv = nsSVGGeometryFrameBase::Init(aContent, aParent, aPrevInFlow);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,11 +491,11 @@ nsSVGGlyphFrame::UpdateCoveredRegion()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMatrixPropagation(PR_FALSE);
|
mPropagateTransform = PR_FALSE;
|
||||||
CharacterIterator iter(this, PR_TRUE);
|
CharacterIterator iter(this, PR_TRUE);
|
||||||
iter.SetInitialMatrix(tmpCtx);
|
iter.SetInitialMatrix(tmpCtx);
|
||||||
AddBoundingBoxesToPath(&iter, tmpCtx);
|
AddBoundingBoxesToPath(&iter, tmpCtx);
|
||||||
SetMatrixPropagation(PR_TRUE);
|
mPropagateTransform = PR_TRUE;
|
||||||
tmpCtx->IdentityMatrix();
|
tmpCtx->IdentityMatrix();
|
||||||
|
|
||||||
// Be careful when replacing the following logic to get the fill and stroke
|
// Be careful when replacing the following logic to get the fill and stroke
|
||||||
|
@ -1479,7 +1479,7 @@ nsSVGGlyphFrame::NotifyGlyphMetricsChange()
|
||||||
PRBool
|
PRBool
|
||||||
nsSVGGlyphFrame::GetGlobalTransform(gfxMatrix *aMatrix)
|
nsSVGGlyphFrame::GetGlobalTransform(gfxMatrix *aMatrix)
|
||||||
{
|
{
|
||||||
if (!GetMatrixPropagation()) {
|
if (!mPropagateTransform) {
|
||||||
aMatrix->Reset();
|
aMatrix->Reset();
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1635,23 +1635,6 @@ nsSVGGlyphFrame::EnsureTextRun(float *aDrawScale, float *aMetricsScale,
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsSVGGlyphFrame::SetMatrixPropagation(PRBool aPropagate)
|
|
||||||
{
|
|
||||||
if (aPropagate) {
|
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
} else {
|
|
||||||
RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsSVGGlyphFrame::GetMatrixPropagation()
|
|
||||||
{
|
|
||||||
return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// helper class
|
// helper class
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,8 @@ protected:
|
||||||
: nsSVGGlyphFrameBase(aContext),
|
: nsSVGGlyphFrameBase(aContext),
|
||||||
mTextRun(nsnull),
|
mTextRun(nsnull),
|
||||||
mStartIndex(0),
|
mStartIndex(0),
|
||||||
mWhitespaceHandling(COMPRESS_WHITESPACE)
|
mWhitespaceHandling(COMPRESS_WHITESPACE),
|
||||||
|
mPropagateTransform(PR_TRUE)
|
||||||
{}
|
{}
|
||||||
~nsSVGGlyphFrame()
|
~nsSVGGlyphFrame()
|
||||||
{
|
{
|
||||||
|
@ -126,8 +127,6 @@ public:
|
||||||
virtual void NotifySVGChanged(PRUint32 aFlags);
|
virtual void NotifySVGChanged(PRUint32 aFlags);
|
||||||
NS_IMETHOD NotifyRedrawSuspended();
|
NS_IMETHOD NotifyRedrawSuspended();
|
||||||
NS_IMETHOD NotifyRedrawUnsuspended();
|
NS_IMETHOD NotifyRedrawUnsuspended();
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
|
||||||
virtual PRBool GetMatrixPropagation();
|
|
||||||
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; }
|
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; }
|
||||||
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
||||||
|
|
||||||
|
@ -229,6 +228,7 @@ protected:
|
||||||
// The start index into the position and rotation data
|
// The start index into the position and rotation data
|
||||||
PRUint32 mStartIndex;
|
PRUint32 mStartIndex;
|
||||||
PRUint8 mWhitespaceHandling;
|
PRUint8 mWhitespaceHandling;
|
||||||
|
PRPackedBool mPropagateTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -335,23 +335,6 @@ nsSVGPathGeometryFrame::NotifyRedrawUnsuspended()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsSVGPathGeometryFrame::SetMatrixPropagation(PRBool aPropagate)
|
|
||||||
{
|
|
||||||
if (aPropagate) {
|
|
||||||
AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
} else {
|
|
||||||
RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsSVGPathGeometryFrame::GetMatrixPropagation()
|
|
||||||
{
|
|
||||||
return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxRect
|
gfxRect
|
||||||
nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
|
nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
|
||||||
{
|
{
|
||||||
|
@ -500,6 +483,12 @@ nsSVGPathGeometryFrame::GeneratePath(gfxContext* aContext,
|
||||||
|
|
||||||
aContext->Multiply(matrix);
|
aContext->Multiply(matrix);
|
||||||
|
|
||||||
|
// Hack to let SVGPathData::ConstructPath know if we have square caps:
|
||||||
|
const nsStyleSVG* style = GetStyleSVG();
|
||||||
|
if (style->mStrokeLinecap == NS_STYLE_STROKE_LINECAP_SQUARE) {
|
||||||
|
aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
|
||||||
|
}
|
||||||
|
|
||||||
aContext->NewPath();
|
aContext->NewPath();
|
||||||
static_cast<nsSVGPathGeometryElement*>(mContent)->ConstructPath(aContext);
|
static_cast<nsSVGPathGeometryElement*>(mContent)->ConstructPath(aContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,6 @@ protected:
|
||||||
virtual void NotifySVGChanged(PRUint32 aFlags);
|
virtual void NotifySVGChanged(PRUint32 aFlags);
|
||||||
NS_IMETHOD NotifyRedrawSuspended();
|
NS_IMETHOD NotifyRedrawSuspended();
|
||||||
NS_IMETHOD NotifyRedrawUnsuspended();
|
NS_IMETHOD NotifyRedrawUnsuspended();
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
|
||||||
virtual PRBool GetMatrixPropagation();
|
|
||||||
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace);
|
||||||
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; }
|
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; }
|
||||||
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
|
||||||
|
|
|
@ -98,10 +98,8 @@ class Element;
|
||||||
/* are we the child of a non-display container? */
|
/* are we the child of a non-display container? */
|
||||||
#define NS_STATE_SVG_NONDISPLAY_CHILD NS_FRAME_STATE_BIT(22)
|
#define NS_STATE_SVG_NONDISPLAY_CHILD NS_FRAME_STATE_BIT(22)
|
||||||
|
|
||||||
#define NS_STATE_SVG_PROPAGATE_TRANSFORM NS_FRAME_STATE_BIT(23)
|
|
||||||
|
|
||||||
// If this bit is set, we are a <clipPath> element or descendant.
|
// If this bit is set, we are a <clipPath> element or descendant.
|
||||||
#define NS_STATE_SVG_CLIPPATH_CHILD NS_FRAME_STATE_BIT(24)
|
#define NS_STATE_SVG_CLIPPATH_CHILD NS_FRAME_STATE_BIT(23)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
|
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
|
||||||
|
|
|
@ -1753,6 +1753,39 @@ pref("gfx.font_rendering.cleartype.use_for_downloadable_fonts", true);
|
||||||
// use cleartype rendering for all fonts always (win xp only)
|
// use cleartype rendering for all fonts always (win xp only)
|
||||||
pref("gfx.font_rendering.cleartype.always_use_for_content", false);
|
pref("gfx.font_rendering.cleartype.always_use_for_content", false);
|
||||||
|
|
||||||
|
// ClearType tuning parameters for directwrite/d2d.
|
||||||
|
//
|
||||||
|
// Allows overriding of underlying registry values in:
|
||||||
|
// HKCU/Software/Microsoft/Avalon.Graphics/<display> (contrast and level)
|
||||||
|
// HKLM/Software/Microsoft/Avalon.Graphics/<display> (gamma, pixel structure)
|
||||||
|
// and selection of the ClearType/antialiasing mode.
|
||||||
|
//
|
||||||
|
// A value of -1 implies use the default value, otherwise value ranges
|
||||||
|
// follow registry settings:
|
||||||
|
// gamma [1000, 2200] default: based on screen, typically 2200 (== 2.2)
|
||||||
|
// enhanced contrast [0, 1000] default: 50
|
||||||
|
// cleartype level [0, 100] default: 100
|
||||||
|
// pixel structure [0, 2] default: 0 (flat/RGB/BGR)
|
||||||
|
// rendering mode [0, 5] default: 0
|
||||||
|
// 0 = use default for font & size;
|
||||||
|
// 1 = aliased;
|
||||||
|
// 2 = GDI Classic;
|
||||||
|
// 3 = GDI Natural Widths;
|
||||||
|
// 4 = Natural;
|
||||||
|
// 5 = Natural Symmetric
|
||||||
|
//
|
||||||
|
// See:
|
||||||
|
// http://msdn.microsoft.com/en-us/library/aa970267.aspx
|
||||||
|
// http://msdn.microsoft.com/en-us/library/dd368190%28v=VS.85%29.aspx
|
||||||
|
// Note: DirectWrite uses the "Enhanced Contrast Level" value rather than the
|
||||||
|
// "Text Contrast Level" value
|
||||||
|
|
||||||
|
pref("gfx.font_rendering.cleartype_params.gamma", -1);
|
||||||
|
pref("gfx.font_rendering.cleartype_params.enhanced_contrast", -1);
|
||||||
|
pref("gfx.font_rendering.cleartype_params.cleartype_level", -1);
|
||||||
|
pref("gfx.font_rendering.cleartype_params.pixel_structure", -1);
|
||||||
|
pref("gfx.font_rendering.cleartype_params.rendering_mode", -1);
|
||||||
|
|
||||||
pref("ui.key.menuAccessKeyFocuses", true);
|
pref("ui.key.menuAccessKeyFocuses", true);
|
||||||
|
|
||||||
// override double-click word selection behavior.
|
// override double-click word selection behavior.
|
||||||
|
|
|
@ -4,13 +4,9 @@
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
|
||||||
|
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
var iframe = document.getElementById('iframe1');
|
|
||||||
|
|
||||||
window.frameLoaded = function frameLoaded_toCrash() {
|
window.frameLoaded = function frameLoaded_toCrash() {
|
||||||
if (!SimpleTest.testPluginIsOOP()) {
|
if (!SimpleTest.testPluginIsOOP()) {
|
||||||
ok(true, "Skipping this test when test plugin is not OOP.");
|
ok(true, "Skipping this test when test plugin is not OOP.");
|
||||||
|
@ -18,6 +14,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iframe = document.getElementById('iframe1');
|
||||||
var p = iframe.contentDocument.getElementById('plugin1');
|
var p = iframe.contentDocument.getElementById('plugin1');
|
||||||
|
|
||||||
// This test is for bug 550026, which is inherently nondeterministic.
|
// This test is for bug 550026, which is inherently nondeterministic.
|
||||||
|
@ -50,3 +47,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
||||||
|
|
|
@ -4,13 +4,9 @@
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
|
||||||
|
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
var iframe = document.getElementById('iframe1');
|
|
||||||
|
|
||||||
window.frameLoaded = function frameLoaded_toCrash() {
|
window.frameLoaded = function frameLoaded_toCrash() {
|
||||||
if (!SimpleTest.testPluginIsOOP()) {
|
if (!SimpleTest.testPluginIsOOP()) {
|
||||||
ok(true, "Skipping this test when test plugin is not OOP.");
|
ok(true, "Skipping this test when test plugin is not OOP.");
|
||||||
|
@ -18,6 +14,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iframe = document.getElementById('iframe1');
|
||||||
var p = iframe.contentDocument.getElementById('plugin1');
|
var p = iframe.contentDocument.getElementById('plugin1');
|
||||||
|
|
||||||
p.setColor("FFFF00FF");
|
p.setColor("FFFF00FF");
|
||||||
|
@ -65,3 +62,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
||||||
|
|
|
@ -4,13 +4,9 @@
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
|
||||||
|
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
var iframe = document.getElementById('iframe1');
|
|
||||||
|
|
||||||
window.frameLoaded = function frameLoaded_toCrash() {
|
window.frameLoaded = function frameLoaded_toCrash() {
|
||||||
if (!SimpleTest.testPluginIsOOP()) {
|
if (!SimpleTest.testPluginIsOOP()) {
|
||||||
ok(true, "Skipping this test when test plugin is not OOP.");
|
ok(true, "Skipping this test when test plugin is not OOP.");
|
||||||
|
@ -26,6 +22,7 @@
|
||||||
var timeoutPref = "dom.ipc.plugins.timeoutSecs";
|
var timeoutPref = "dom.ipc.plugins.timeoutSecs";
|
||||||
prefs.setIntPref(timeoutPref, 5);
|
prefs.setIntPref(timeoutPref, 5);
|
||||||
|
|
||||||
|
var iframe = document.getElementById('iframe1');
|
||||||
var p = iframe.contentDocument.getElementById('plugin1');
|
var p = iframe.contentDocument.getElementById('plugin1');
|
||||||
|
|
||||||
p.setColor("FFFF00FF");
|
p.setColor("FFFF00FF");
|
||||||
|
@ -74,3 +71,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
|
||||||
|
|
|
@ -225,6 +225,13 @@ getClipRegionRectCount(), this will throw an error. The coordinates are
|
||||||
the same as for getEdge. See getClipRegionRectCount() above for
|
the same as for getEdge. See getClipRegionRectCount() above for
|
||||||
notes on platform plugin limitations.
|
notes on platform plugin limitations.
|
||||||
|
|
||||||
|
== Keyboard events ==
|
||||||
|
|
||||||
|
* getLastKeyText()
|
||||||
|
Returns the text which was inputted by last keyboard events. This is cleared at
|
||||||
|
every keydown event.
|
||||||
|
NOTE: Currently, this is implemented only on Windows.
|
||||||
|
|
||||||
== Mouse events ==
|
== Mouse events ==
|
||||||
|
|
||||||
The test plugin supports the following scriptable methods:
|
The test plugin supports the following scriptable methods:
|
||||||
|
|
|
@ -165,6 +165,7 @@ static bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t a
|
||||||
static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
|
static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
|
|
||||||
static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||||
"npnEvaluateTest",
|
"npnEvaluateTest",
|
||||||
|
@ -221,7 +222,8 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||||
"getWindowPosition",
|
"getWindowPosition",
|
||||||
"constructObject",
|
"constructObject",
|
||||||
"setSitesWithData",
|
"setSitesWithData",
|
||||||
"setSitesWithDataCapabilities"
|
"setSitesWithDataCapabilities",
|
||||||
|
"getLastKeyText"
|
||||||
};
|
};
|
||||||
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
|
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
|
||||||
static const ScriptableFunction sPluginMethodFunctions[] = {
|
static const ScriptableFunction sPluginMethodFunctions[] = {
|
||||||
|
@ -279,7 +281,8 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
|
||||||
getWindowPosition,
|
getWindowPosition,
|
||||||
constructObject,
|
constructObject,
|
||||||
setSitesWithData,
|
setSitesWithData,
|
||||||
setSitesWithDataCapabilities
|
setSitesWithDataCapabilities,
|
||||||
|
getLastKeyText
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
|
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
|
||||||
|
@ -3436,3 +3439,15 @@ bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||||
|
NPVariant* result)
|
||||||
|
{
|
||||||
|
if (argCount != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
|
||||||
|
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
|
||||||
|
STRINGZ_TO_NPVARIANT(NPN_StrDup(id->lastKeyText.c_str()), *result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ typedef struct InstanceData {
|
||||||
int32_t focusEventCount;
|
int32_t focusEventCount;
|
||||||
int32_t eventModel;
|
int32_t eventModel;
|
||||||
bool closeStream;
|
bool closeStream;
|
||||||
|
std::string lastKeyText;
|
||||||
} InstanceData;
|
} InstanceData;
|
||||||
|
|
||||||
void notifyDidPaint(InstanceData* instanceData);
|
void notifyDidPaint(InstanceData* instanceData);
|
||||||
|
|
|
@ -458,6 +458,27 @@ handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
instanceData->lastKeyText.erase();
|
||||||
|
*result = 0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case WM_CHAR: {
|
||||||
|
*result = 0;
|
||||||
|
wchar_t uniChar = static_cast<wchar_t>(pe->wParam);
|
||||||
|
if (!uniChar) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char utf8Char[6];
|
||||||
|
int len =
|
||||||
|
::WideCharToMultiByte(CP_UTF8, 0, &uniChar, 1, utf8Char, 6, NULL, NULL);
|
||||||
|
if (len == 0 || len > 6) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
instanceData->lastKeyText.append(utf8Char, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ function makeEngine() {
|
||||||
}
|
}
|
||||||
var syncTesting = new SyncTestingInfrastructure(makeEngine);
|
var syncTesting = new SyncTestingInfrastructure(makeEngine);
|
||||||
|
|
||||||
function test_ID_caching() {
|
add_test(function test_ID_caching() {
|
||||||
|
|
||||||
_("Ensure that Places IDs are not cached.");
|
_("Ensure that Places IDs are not cached.");
|
||||||
let engine = new BookmarksEngine();
|
let engine = new BookmarksEngine();
|
||||||
|
@ -50,12 +50,12 @@ function test_ID_caching() {
|
||||||
do_check_eq(newMobileID, store.idForGUID("mobile", false));
|
do_check_eq(newMobileID, store.idForGUID("mobile", false));
|
||||||
|
|
||||||
do_check_eq(store.GUIDForId(mobileID), "abcdefghijkl");
|
do_check_eq(store.GUIDForId(mobileID), "abcdefghijkl");
|
||||||
}
|
run_next_test();
|
||||||
|
});
|
||||||
|
|
||||||
function test_processIncoming_error_orderChildren() {
|
add_test(function test_processIncoming_error_orderChildren() {
|
||||||
_("Ensure that _orderChildren() is called even when _processIncoming() throws an error.");
|
_("Ensure that _orderChildren() is called even when _processIncoming() throws an error.");
|
||||||
|
|
||||||
do_test_pending();
|
|
||||||
Svc.Prefs.set("clusterURL", "http://localhost:8080/");
|
Svc.Prefs.set("clusterURL", "http://localhost:8080/");
|
||||||
Svc.Prefs.set("username", "foo");
|
Svc.Prefs.set("username", "foo");
|
||||||
|
|
||||||
|
@ -126,16 +126,15 @@ function test_processIncoming_error_orderChildren() {
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
store.wipe();
|
store.wipe();
|
||||||
server.stop(do_test_finished);
|
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
Records.clearCache();
|
Records.clearCache();
|
||||||
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
||||||
|
server.stop(run_next_test);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function test_restorePromptsReupload() {
|
add_test(function test_restorePromptsReupload() {
|
||||||
_("Ensure that restoring from a backup will reupload all records.");
|
_("Ensure that restoring from a backup will reupload all records.");
|
||||||
do_test_pending();
|
|
||||||
Svc.Prefs.set("username", "foo");
|
Svc.Prefs.set("username", "foo");
|
||||||
Service.serverURL = "http://localhost:8080/";
|
Service.serverURL = "http://localhost:8080/";
|
||||||
Service.clusterURL = "http://localhost:8080/";
|
Service.clusterURL = "http://localhost:8080/";
|
||||||
|
@ -266,15 +265,15 @@ function test_restorePromptsReupload() {
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
store.wipe();
|
store.wipe();
|
||||||
server.stop(do_test_finished);
|
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
Records.clearCache();
|
Records.clearCache();
|
||||||
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
||||||
|
server.stop(run_next_test);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Bug 632287.
|
// Bug 632287.
|
||||||
function test_mismatched_types() {
|
add_test(function test_mismatched_types() {
|
||||||
_("Ensure that handling a record that changes type causes deletion " +
|
_("Ensure that handling a record that changes type causes deletion " +
|
||||||
"then re-adding.");
|
"then re-adding.");
|
||||||
|
|
||||||
|
@ -309,7 +308,6 @@ function test_mismatched_types() {
|
||||||
"parentid": "toolbar"
|
"parentid": "toolbar"
|
||||||
};
|
};
|
||||||
|
|
||||||
do_test_pending();
|
|
||||||
Svc.Prefs.set("username", "foo");
|
Svc.Prefs.set("username", "foo");
|
||||||
Service.serverURL = "http://localhost:8080/";
|
Service.serverURL = "http://localhost:8080/";
|
||||||
Service.clusterURL = "http://localhost:8080/";
|
Service.clusterURL = "http://localhost:8080/";
|
||||||
|
@ -351,12 +349,12 @@ function test_mismatched_types() {
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
store.wipe();
|
store.wipe();
|
||||||
server.stop(do_test_finished);
|
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
Records.clearCache();
|
Records.clearCache();
|
||||||
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
syncTesting = new SyncTestingInfrastructure(makeEngine);
|
||||||
|
server.stop(run_next_test);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
initTestLogging("Trace");
|
initTestLogging("Trace");
|
||||||
|
@ -364,8 +362,5 @@ function run_test() {
|
||||||
|
|
||||||
CollectionKeys.generateNewKeys();
|
CollectionKeys.generateNewKeys();
|
||||||
|
|
||||||
test_processIncoming_error_orderChildren();
|
run_next_test();
|
||||||
test_ID_caching();
|
|
||||||
test_mismatched_types();
|
|
||||||
test_restorePromptsReupload();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ Cu.import("resource://services-sync/engines/clients.js");
|
||||||
Cu.import("resource://services-sync/service.js");
|
Cu.import("resource://services-sync/service.js");
|
||||||
|
|
||||||
const MORE_THAN_CLIENTS_TTL_REFRESH = 691200; // 8 days
|
const MORE_THAN_CLIENTS_TTL_REFRESH = 691200; // 8 days
|
||||||
const LESS_THAN_CLIENTS_TTL_REFRESH = 86400; // 1 day
|
const LESS_THAN_CLIENTS_TTL_REFRESH = 86400; // 1 day
|
||||||
|
|
||||||
function test_bad_hmac() {
|
add_test(function test_bad_hmac() {
|
||||||
_("Ensure that Clients engine deletes corrupt records.");
|
_("Ensure that Clients engine deletes corrupt records.");
|
||||||
let global = new ServerWBO('global',
|
let global = new ServerWBO('global',
|
||||||
{engines: {clients: {version: Clients.version,
|
{engines: {clients: {version: Clients.version,
|
||||||
|
@ -41,7 +41,6 @@ function test_bad_hmac() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let server = httpd_setup(handlers);
|
let server = httpd_setup(handlers);
|
||||||
do_test_pending();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
let passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||||
|
@ -133,15 +132,15 @@ function test_bad_hmac() {
|
||||||
do_check_false(oldKey.equals(newKey));
|
do_check_false(oldKey.equals(newKey));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
server.stop(do_test_finished);
|
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
Records.clearCache();
|
Records.clearCache();
|
||||||
|
server.stop(run_next_test);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function test_properties() {
|
add_test(function test_properties() {
|
||||||
|
_("Test lastRecordUpload property");
|
||||||
try {
|
try {
|
||||||
_("Test lastRecordUpload property");
|
|
||||||
do_check_eq(Svc.Prefs.get("clients.lastRecordUpload"), undefined);
|
do_check_eq(Svc.Prefs.get("clients.lastRecordUpload"), undefined);
|
||||||
do_check_eq(Clients.lastRecordUpload, 0);
|
do_check_eq(Clients.lastRecordUpload, 0);
|
||||||
|
|
||||||
|
@ -150,10 +149,11 @@ function test_properties() {
|
||||||
do_check_eq(Clients.lastRecordUpload, Math.floor(now / 1000));
|
do_check_eq(Clients.lastRecordUpload, Math.floor(now / 1000));
|
||||||
} finally {
|
} finally {
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
|
run_next_test();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function test_sync() {
|
add_test(function test_sync() {
|
||||||
_("Ensure that Clients engine uploads a new client record once a week.");
|
_("Ensure that Clients engine uploads a new client record once a week.");
|
||||||
Svc.Prefs.set("clusterURL", "http://localhost:8080/");
|
Svc.Prefs.set("clusterURL", "http://localhost:8080/");
|
||||||
Svc.Prefs.set("username", "foo");
|
Svc.Prefs.set("username", "foo");
|
||||||
|
@ -172,8 +172,6 @@ function test_sync() {
|
||||||
server.registerPathHandler(
|
server.registerPathHandler(
|
||||||
"/1.1/foo/storage/clients/" + Clients.localID, clientwbo.handler());
|
"/1.1/foo/storage/clients/" + Clients.localID, clientwbo.handler());
|
||||||
|
|
||||||
do_test_pending();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
_("First sync, client record is uploaded");
|
_("First sync, client record is uploaded");
|
||||||
|
@ -203,17 +201,14 @@ function test_sync() {
|
||||||
do_check_eq(Clients.lastRecordUpload, yesterday);
|
do_check_eq(Clients.lastRecordUpload, yesterday);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
server.stop(do_test_finished);
|
|
||||||
Svc.Prefs.resetBranch("");
|
Svc.Prefs.resetBranch("");
|
||||||
Records.clearCache();
|
Records.clearCache();
|
||||||
|
server.stop(run_next_test);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
initTestLogging("Trace");
|
initTestLogging("Trace");
|
||||||
Log4Moz.repository.getLogger("Engine.Clients").level = Log4Moz.Level.Trace;
|
Log4Moz.repository.getLogger("Engine.Clients").level = Log4Moz.Level.Trace;
|
||||||
test_bad_hmac();
|
run_next_test();
|
||||||
test_properties();
|
|
||||||
test_sync();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -551,14 +551,23 @@ var gViewController = {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadView: function(aViewId) {
|
loadView: function(aViewId) {
|
||||||
if (aViewId == this.currentViewId)
|
var isRefresh = false;
|
||||||
return;
|
if (aViewId == this.currentViewId) {
|
||||||
|
if (this.isLoading)
|
||||||
|
return;
|
||||||
|
if (!("refresh" in this.currentViewObj))
|
||||||
|
return;
|
||||||
|
if (!this.currentViewObj.canRefresh())
|
||||||
|
return;
|
||||||
|
isRefresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
var state = {
|
var state = {
|
||||||
view: aViewId,
|
view: aViewId,
|
||||||
previousView: this.currentViewId
|
previousView: this.currentViewId
|
||||||
};
|
};
|
||||||
gHistory.pushState(state);
|
if (!isRefresh)
|
||||||
|
gHistory.pushState(state);
|
||||||
this.loadViewInternal(aViewId, this.currentViewId, state);
|
this.loadViewInternal(aViewId, this.currentViewId, state);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -598,7 +607,7 @@ var gViewController = {
|
||||||
if (!viewObj.node)
|
if (!viewObj.node)
|
||||||
throw new Error("Root node doesn't exist for '" + view.type + "' view");
|
throw new Error("Root node doesn't exist for '" + view.type + "' view");
|
||||||
|
|
||||||
if (this.currentViewObj) {
|
if (this.currentViewObj && aViewId != aPreviousView) {
|
||||||
try {
|
try {
|
||||||
let canHide = this.currentViewObj.hide();
|
let canHide = this.currentViewObj.hide();
|
||||||
if (canHide === false)
|
if (canHide === false)
|
||||||
|
@ -617,7 +626,11 @@ var gViewController = {
|
||||||
|
|
||||||
this.viewPort.selectedPanel = this.currentViewObj.node;
|
this.viewPort.selectedPanel = this.currentViewObj.node;
|
||||||
this.viewPort.selectedPanel.setAttribute("loading", "true");
|
this.viewPort.selectedPanel.setAttribute("loading", "true");
|
||||||
this.currentViewObj.show(view.param, ++this.currentViewRequest, aState);
|
|
||||||
|
if (aViewId == aPreviousView)
|
||||||
|
this.currentViewObj.refresh(view.param, ++this.currentViewRequest, aState);
|
||||||
|
else
|
||||||
|
this.currentViewObj.show(view.param, ++this.currentViewRequest, aState);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Moves back in the document history and removes the current history entry
|
// Moves back in the document history and removes the current history entry
|
||||||
|
@ -1655,7 +1668,7 @@ var gDiscoverView = {
|
||||||
Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
||||||
|
|
||||||
if (self.loaded)
|
if (self.loaded)
|
||||||
self._loadURL(self.homepageURL.spec, notifyInitialized);
|
self._loadURL(self.homepageURL.spec, false, notifyInitialized);
|
||||||
else
|
else
|
||||||
notifyInitialized();
|
notifyInitialized();
|
||||||
}
|
}
|
||||||
|
@ -1689,7 +1702,7 @@ var gDiscoverView = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function(aParam, aRequest, aState) {
|
show: function(aParam, aRequest, aState, aIsRefresh) {
|
||||||
gViewController.updateCommands();
|
gViewController.updateCommands();
|
||||||
|
|
||||||
// If we're being told to load a specific URL then just do that
|
// If we're being told to load a specific URL then just do that
|
||||||
|
@ -1698,9 +1711,11 @@ var gDiscoverView = {
|
||||||
this._loadURL(aState.url);
|
this._loadURL(aState.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the view has loaded before and the error page is not visible then
|
// If the view has loaded before and still at the homepage (if refreshing),
|
||||||
// there is nothing else to do
|
// and the error page is not visible then there is nothing else to do
|
||||||
if (this.loaded && this.node.selectedPanel != this._error) {
|
if (this.loaded && this.node.selectedPanel != this._error &&
|
||||||
|
(!aIsRefresh || (this._browser.currentURI &&
|
||||||
|
this._browser.currentURI.spec == this._browser.homePage))) {
|
||||||
gViewController.notifyViewChanged();
|
gViewController.notifyViewChanged();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1714,9 +1729,20 @@ var gDiscoverView = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._loadURL(this.homepageURL.spec,
|
this._loadURL(this.homepageURL.spec, aIsRefresh,
|
||||||
gViewController.notifyViewChanged.bind(gViewController));
|
gViewController.notifyViewChanged.bind(gViewController));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
canRefresh: function() {
|
||||||
|
if (this._browser.currentURI &&
|
||||||
|
this._browser.currentURI.spec == this._browser.homePage)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function(aParam, aRequest, aState) {
|
||||||
|
this.show(aParam, aRequest, aState, true);
|
||||||
|
},
|
||||||
|
|
||||||
hide: function() { },
|
hide: function() { },
|
||||||
|
|
||||||
|
@ -1724,7 +1750,7 @@ var gDiscoverView = {
|
||||||
this.node.selectedPanel = this._error;
|
this.node.selectedPanel = this._error;
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadURL: function(aURL, aCallback) {
|
_loadURL: function(aURL, aKeepHistory, aCallback) {
|
||||||
if (this._browser.currentURI.spec == aURL) {
|
if (this._browser.currentURI.spec == aURL) {
|
||||||
if (aCallback)
|
if (aCallback)
|
||||||
aCallback();
|
aCallback();
|
||||||
|
@ -1734,8 +1760,11 @@ var gDiscoverView = {
|
||||||
if (aCallback)
|
if (aCallback)
|
||||||
this._loadListeners.push(aCallback);
|
this._loadListeners.push(aCallback);
|
||||||
|
|
||||||
this._browser.loadURIWithFlags(aURL,
|
var flags = 0;
|
||||||
Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY);
|
if (!aKeepHistory)
|
||||||
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
|
||||||
|
|
||||||
|
this._browser.loadURIWithFlags(aURL, flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
onLocationChange: function(aWebProgress, aRequest, aLocation) {
|
onLocationChange: function(aWebProgress, aRequest, aLocation) {
|
||||||
|
|
|
@ -844,3 +844,63 @@ add_test(function() {
|
||||||
});
|
});
|
||||||
}, true);
|
}, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Tests that refreshing the disicovery pane integrates properly with history
|
||||||
|
add_test(function() {
|
||||||
|
open_manager("addons://list/plugin", function(aManager) {
|
||||||
|
is_in_list(aManager, "addons://list/plugin", false, false);
|
||||||
|
|
||||||
|
EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager);
|
||||||
|
|
||||||
|
wait_for_view_load(aManager, function(aManager) {
|
||||||
|
is_in_discovery(aManager, MAIN_URL, true, false);
|
||||||
|
|
||||||
|
clickLink(aManager, "link-good", function() {
|
||||||
|
is_in_discovery(aManager, SECOND_URL, true, false);
|
||||||
|
|
||||||
|
EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager);
|
||||||
|
|
||||||
|
waitForLoad(aManager, function() {
|
||||||
|
is_in_discovery(aManager, MAIN_URL, true, false);
|
||||||
|
|
||||||
|
go_back(aManager);
|
||||||
|
|
||||||
|
waitForLoad(aManager, function() {
|
||||||
|
is_in_discovery(aManager, SECOND_URL, true, true);
|
||||||
|
|
||||||
|
go_back(aManager);
|
||||||
|
|
||||||
|
waitForLoad(aManager, function() {
|
||||||
|
is_in_discovery(aManager, MAIN_URL, true, true);
|
||||||
|
|
||||||
|
go_back(aManager);
|
||||||
|
|
||||||
|
wait_for_view_load(aManager, function(aManager) {
|
||||||
|
is_in_list(aManager, "addons://list/plugin", false, true);
|
||||||
|
|
||||||
|
go_forward(aManager);
|
||||||
|
|
||||||
|
wait_for_view_load(aManager, function(aManager) {
|
||||||
|
is_in_discovery(aManager, MAIN_URL, true, true);
|
||||||
|
|
||||||
|
waitForLoad(aManager, function() {
|
||||||
|
is_in_discovery(aManager, SECOND_URL, true, true);
|
||||||
|
|
||||||
|
waitForLoad(aManager, function() {
|
||||||
|
is_in_discovery(aManager, MAIN_URL, true, false);
|
||||||
|
|
||||||
|
close_manager(aManager, run_next_test);
|
||||||
|
});
|
||||||
|
go_forward(aManager);
|
||||||
|
});
|
||||||
|
|
||||||
|
go_forward(aManager);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -410,7 +410,7 @@ add_test(function() {
|
||||||
|
|
||||||
gCategoryUtilities.openType("extension", function() {
|
gCategoryUtilities.openType("extension", function() {
|
||||||
gCategoryUtilities.openType("discover", function() {
|
gCategoryUtilities.openType("discover", function() {
|
||||||
is(getURL(browser), "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml", "Should have loaded the right url");
|
is(getURL(browser), MAIN_URL, "Should have loaded the right url");
|
||||||
|
|
||||||
close_manager(gManagerWindow, run_next_test);
|
close_manager(gManagerWindow, run_next_test);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event loop instrumentation. This code attempts to measure the
|
||||||
|
* latency of the UI-thread event loop by firing native events at it from
|
||||||
|
* a background thread, and measuring how long it takes for them
|
||||||
|
* to be serviced. The measurement interval (kMeasureInterval, below)
|
||||||
|
* is also used as the upper bound of acceptable response time.
|
||||||
|
* When an event takes longer than that interval to be serviced,
|
||||||
|
* a sample will be written to the log.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* Set MOZ_INSTRUMENT_EVENT_LOOP=1 in the environment to enable
|
||||||
|
* this instrumentation. Currently only the UI process is instrumented.
|
||||||
|
*
|
||||||
|
* Set MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT in the environment to a
|
||||||
|
* file path to contain the log output, the default is to log to stdout.
|
||||||
|
*
|
||||||
|
* All logged output lines start with MOZ_EVENT_TRACE. All timestamps
|
||||||
|
* output are milliseconds since the epoch (PRTime / 1000).
|
||||||
|
*
|
||||||
|
* On startup, a line of the form:
|
||||||
|
* MOZ_EVENT_TRACE start <timestamp>
|
||||||
|
* will be output.
|
||||||
|
*
|
||||||
|
* On shutdown, a line of the form:
|
||||||
|
* MOZ_EVENT_TRACE stop <timestamp>
|
||||||
|
* will be output.
|
||||||
|
*
|
||||||
|
* When an event servicing time exceeds the threshold, a line of the form:
|
||||||
|
* MOZ_EVENT_TRACE sample <timestamp> <duration>
|
||||||
|
* will be output, where <duration> is the number of milliseconds that
|
||||||
|
* it took for the event to be serviced.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EventTracer.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "mozilla/WidgetTraceEvent.h"
|
||||||
|
#include <prenv.h>
|
||||||
|
#include <prinrval.h>
|
||||||
|
#include <prthread.h>
|
||||||
|
#include <prtime.h>
|
||||||
|
|
||||||
|
using mozilla::TimeDuration;
|
||||||
|
using mozilla::TimeStamp;
|
||||||
|
using mozilla::FireAndWaitForTracerEvent;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
PRThread* sTracerThread = NULL;
|
||||||
|
bool sExit = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The tracer thread fires events at the native event loop roughly
|
||||||
|
* every kMeasureInterval. It will sleep to attempt not to send them
|
||||||
|
* more quickly, but if the response time is longer than kMeasureInterval
|
||||||
|
* it will not send another event until the previous response is received.
|
||||||
|
*
|
||||||
|
* The output defaults to stdout, but can be redirected to a file by
|
||||||
|
* settting the environment variable MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT
|
||||||
|
* to the name of a file to use.
|
||||||
|
*/
|
||||||
|
void TracerThread(void *arg)
|
||||||
|
{
|
||||||
|
// This should be set to the maximum latency we'd like to allow
|
||||||
|
// for responsiveness.
|
||||||
|
const PRIntervalTime kMeasureInterval = PR_MillisecondsToInterval(50);
|
||||||
|
|
||||||
|
FILE* log = NULL;
|
||||||
|
char* envfile = PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT");
|
||||||
|
if (envfile) {
|
||||||
|
log = fopen(envfile, "w");
|
||||||
|
}
|
||||||
|
if (log == NULL)
|
||||||
|
log = stdout;
|
||||||
|
|
||||||
|
fprintf(log, "MOZ_EVENT_TRACE start %llu\n", PR_Now() / PR_USEC_PER_MSEC);
|
||||||
|
|
||||||
|
while (!sExit) {
|
||||||
|
TimeStamp start(TimeStamp::Now());
|
||||||
|
PRIntervalTime next_sleep = kMeasureInterval;
|
||||||
|
|
||||||
|
//TODO: only wait up to a maximum of kMeasureInterval, return
|
||||||
|
// early if that threshold is exceeded and dump a stack trace
|
||||||
|
// or do something else useful.
|
||||||
|
if (FireAndWaitForTracerEvent()) {
|
||||||
|
TimeDuration duration = TimeStamp::Now() - start;
|
||||||
|
// Only report samples that exceed our measurement interval.
|
||||||
|
if (duration.ToMilliseconds() > kMeasureInterval) {
|
||||||
|
fprintf(log, "MOZ_EVENT_TRACE sample %llu %d\n",
|
||||||
|
PR_Now() / PR_USEC_PER_MSEC,
|
||||||
|
int(duration.ToSecondsSigDigits() * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_sleep > duration.ToMilliseconds()) {
|
||||||
|
next_sleep -= int(duration.ToMilliseconds());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Don't sleep at all if this event took longer than the measure
|
||||||
|
// interval to deliver.
|
||||||
|
next_sleep = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_sleep != 0 && !sExit) {
|
||||||
|
PR_Sleep(next_sleep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(log, "MOZ_EVENT_TRACE stop %llu\n", PR_Now() / PR_USEC_PER_MSEC);
|
||||||
|
|
||||||
|
if (log != stdout)
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
bool InitEventTracing()
|
||||||
|
{
|
||||||
|
// Initialize the widget backend.
|
||||||
|
if (!InitWidgetTracing())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Create a thread that will fire events back at the
|
||||||
|
// main thread to measure responsiveness.
|
||||||
|
NS_ABORT_IF_FALSE(!sTracerThread, "Event tracing already initialized!");
|
||||||
|
sTracerThread = PR_CreateThread(PR_USER_THREAD,
|
||||||
|
TracerThread,
|
||||||
|
NULL,
|
||||||
|
PR_PRIORITY_NORMAL,
|
||||||
|
PR_GLOBAL_THREAD,
|
||||||
|
PR_JOINABLE_THREAD,
|
||||||
|
0);
|
||||||
|
return sTracerThread != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownEventTracing()
|
||||||
|
{
|
||||||
|
sExit = true;
|
||||||
|
if (sTracerThread)
|
||||||
|
PR_JoinThread(sTracerThread);
|
||||||
|
sTracerThread = NULL;
|
||||||
|
|
||||||
|
// Allow the widget backend to clean up.
|
||||||
|
CleanUpWidgetTracing();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef XRE_EVENTTRACER_H_
|
||||||
|
#define XRE_EVENTTRACER_H_
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// Create a thread that will fire events back at the
|
||||||
|
// main thread to measure responsiveness. Return true
|
||||||
|
// if the thread was created successfully.
|
||||||
|
bool InitEventTracing();
|
||||||
|
|
||||||
|
// Signal the background thread to stop, and join it.
|
||||||
|
// Must be called from the same thread that called InitEventTracing.
|
||||||
|
void ShutdownEventTracing();
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif /* XRE_EVENTTRACER_H_ */
|
|
@ -88,6 +88,8 @@ private:
|
||||||
|
|
||||||
static PRBool sProcessedGetURLEvent = PR_FALSE;
|
static PRBool sProcessedGetURLEvent = PR_FALSE;
|
||||||
|
|
||||||
|
@class GeckoNSApplication;
|
||||||
|
|
||||||
// Methods that can be called from non-Objective-C code.
|
// Methods that can be called from non-Objective-C code.
|
||||||
|
|
||||||
// This is needed, on relaunch, to force the OS to use the "Cocoa Dock API"
|
// This is needed, on relaunch, to force the OS to use the "Cocoa Dock API"
|
||||||
|
@ -97,7 +99,7 @@ EnsureUseCocoaDockAPI()
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||||
|
|
||||||
[NSApplication sharedApplication];
|
[GeckoNSApplication sharedApplication];
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +114,7 @@ SetupMacApplicationDelegate()
|
||||||
AutoAutoreleasePool pool;
|
AutoAutoreleasePool pool;
|
||||||
|
|
||||||
// Ensure that ProcessPendingGetURLAppleEvents() doesn't regress bug 377166.
|
// Ensure that ProcessPendingGetURLAppleEvents() doesn't regress bug 377166.
|
||||||
[NSApplication sharedApplication];
|
[GeckoNSApplication sharedApplication];
|
||||||
|
|
||||||
// This call makes it so that application:openFile: doesn't get bogus calls
|
// This call makes it so that application:openFile: doesn't get bogus calls
|
||||||
// from Cocoa doing its own parsing of the argument string. And yes, we need
|
// from Cocoa doing its own parsing of the argument string. And yes, we need
|
||||||
|
|
|
@ -66,6 +66,10 @@ CPPSRCS = \
|
||||||
nsSigHandlers.cpp \
|
nsSigHandlers.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||||
|
CPPSRCS += EventTracer.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef MOZ_SPLASHSCREEN
|
ifdef MOZ_SPLASHSCREEN
|
||||||
ifeq ($(OS_ARCH),WINCE)
|
ifeq ($(OS_ARCH),WINCE)
|
||||||
CPPSRCS += nsSplashScreenWin.cpp
|
CPPSRCS += nsSplashScreenWin.cpp
|
||||||
|
|
|
@ -62,6 +62,10 @@ using mozilla::dom::ContentParent;
|
||||||
#include "nsAppRunner.h"
|
#include "nsAppRunner.h"
|
||||||
#include "nsUpdateDriver.h"
|
#include "nsUpdateDriver.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||||
|
#include "EventTracer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
#include "MacLaunchHelper.h"
|
#include "MacLaunchHelper.h"
|
||||||
#include "MacApplicationDelegate.h"
|
#include "MacApplicationDelegate.h"
|
||||||
|
@ -3744,6 +3748,13 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||||
nativeApp->Enable();
|
nativeApp->Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||||
|
bool event_tracing_running = false;
|
||||||
|
if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
|
||||||
|
event_tracing_running = mozilla::InitEventTracing();
|
||||||
|
}
|
||||||
|
#endif /* MOZ_INSTRUMENT_EVENT_LOOP */
|
||||||
|
|
||||||
NS_TIME_FUNCTION_MARK("Next: Run");
|
NS_TIME_FUNCTION_MARK("Next: Run");
|
||||||
|
|
||||||
NS_TIME_FUNCTION_MARK("appStartup->Run");
|
NS_TIME_FUNCTION_MARK("appStartup->Run");
|
||||||
|
@ -3763,6 +3774,11 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||||
|
|
||||||
NS_TIME_FUNCTION_MARK("appStartup->Run done");
|
NS_TIME_FUNCTION_MARK("appStartup->Run done");
|
||||||
|
|
||||||
|
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||||
|
if (event_tracing_running)
|
||||||
|
mozilla::ShutdownEventTracing();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check for an application initiated restart. This is one that
|
// Check for an application initiated restart. This is one that
|
||||||
// corresponds to nsIAppStartup.quit(eRestart)
|
// corresponds to nsIAppStartup.quit(eRestart)
|
||||||
if (rv == NS_SUCCESS_RESTART_APP)
|
if (rv == NS_SUCCESS_RESTART_APP)
|
||||||
|
|
|
@ -52,6 +52,12 @@ EXPORTS_IPC = \
|
||||||
nsGUIEventIPC.h \
|
nsGUIEventIPC.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||||
|
EXPORTS_NAMESPACES += mozilla
|
||||||
|
EXPORTS_mozilla = \
|
||||||
|
WidgetTraceEvent.h
|
||||||
|
endif
|
||||||
|
|
||||||
EXPORTS = \
|
EXPORTS = \
|
||||||
nsIWidget.h \
|
nsIWidget.h \
|
||||||
nsGUIEvent.h \
|
nsGUIEvent.h \
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
||||||
|
#define WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// Perform any required initialization in the widget backend for
|
||||||
|
// event tracing. Return true if initialization was successful.
|
||||||
|
bool InitWidgetTracing();
|
||||||
|
|
||||||
|
// Perform any required cleanup in the widget backend for event tracing.
|
||||||
|
void CleanUpWidgetTracing();
|
||||||
|
|
||||||
|
// Fire a tracer event at the UI-thread event loop, and block until
|
||||||
|
// the event is processed. This should only be called by
|
||||||
|
// a thread that's not the UI thread.
|
||||||
|
bool FireAndWaitForTracerEvent();
|
||||||
|
|
||||||
|
// Signal that the event has been received by the event loop.
|
||||||
|
void SignalTracerThread();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
|
@ -1826,7 +1826,8 @@ inline PRBool NS_IsEventUsingCoordinates(nsEvent* aEvent)
|
||||||
inline PRBool NS_IsEventTargetedAtFocusedWindow(nsEvent* aEvent)
|
inline PRBool NS_IsEventTargetedAtFocusedWindow(nsEvent* aEvent)
|
||||||
{
|
{
|
||||||
return NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_RELATED_EVENT(aEvent) ||
|
return NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_RELATED_EVENT(aEvent) ||
|
||||||
NS_IS_CONTEXT_MENU_KEY(aEvent) || NS_IS_CONTENT_COMMAND_EVENT(aEvent);
|
NS_IS_CONTEXT_MENU_KEY(aEvent) ||
|
||||||
|
NS_IS_CONTENT_COMMAND_EVENT(aEvent) || NS_IS_PLUGIN_EVENT(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file defines constants to be used in the "subtype" field of
|
||||||
|
* NSApplicationDefined type NSEvents.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
|
||||||
|
#define WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
|
||||||
|
|
||||||
|
// Empty event, just used for prodding the event loop into responding.
|
||||||
|
const short kEventSubtypeNone = 0;
|
||||||
|
// Tracer event, used for timing the event loop responsiveness.
|
||||||
|
const short kEventSubtypeTrace = 1;
|
||||||
|
|
||||||
|
#endif /* WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_ */
|
|
@ -60,40 +60,41 @@ EXPORTS = \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CMMSRCS = \
|
CMMSRCS = \
|
||||||
nsBidiKeyboard.mm \
|
nsBidiKeyboard.mm \
|
||||||
nsClipboard.mm \
|
nsClipboard.mm \
|
||||||
nsMenuX.mm \
|
nsMenuX.mm \
|
||||||
nsMenuBarX.mm \
|
nsMenuBarX.mm \
|
||||||
nsMenuItemX.mm \
|
nsMenuItemX.mm \
|
||||||
nsMenuItemIconX.mm \
|
nsMenuItemIconX.mm \
|
||||||
nsMenuUtilsX.mm \
|
nsMenuUtilsX.mm \
|
||||||
nsMenuGroupOwnerX.mm \
|
nsMenuGroupOwnerX.mm \
|
||||||
nsFilePicker.mm \
|
nsFilePicker.mm \
|
||||||
nsDragService.mm \
|
nsDragService.mm \
|
||||||
nsToolkit.mm \
|
nsToolkit.mm \
|
||||||
nsAppShell.mm \
|
nsAppShell.mm \
|
||||||
nsCocoaUtils.mm \
|
nsCocoaUtils.mm \
|
||||||
nsCocoaWindow.mm \
|
nsCocoaWindow.mm \
|
||||||
nsChildView.mm \
|
nsChildView.mm \
|
||||||
nsWindowMap.mm \
|
nsWindowMap.mm \
|
||||||
nsWidgetFactory.mm \
|
nsWidgetFactory.mm \
|
||||||
nsCursorManager.mm \
|
nsCursorManager.mm \
|
||||||
nsMacCursor.mm \
|
nsMacCursor.mm \
|
||||||
nsScreenCocoa.mm \
|
nsScreenCocoa.mm \
|
||||||
nsScreenManagerCocoa.mm \
|
nsScreenManagerCocoa.mm \
|
||||||
nsSound.mm \
|
nsSound.mm \
|
||||||
nsLookAndFeel.mm \
|
nsLookAndFeel.mm \
|
||||||
nsNativeThemeCocoa.mm \
|
nsNativeThemeCocoa.mm \
|
||||||
nsDeviceContextSpecX.mm \
|
nsDeviceContextSpecX.mm \
|
||||||
nsPrintDialogX.mm \
|
nsPrintDialogX.mm \
|
||||||
nsPrintOptionsX.mm \
|
nsPrintOptionsX.mm \
|
||||||
nsPrintSettingsX.mm \
|
nsPrintSettingsX.mm \
|
||||||
nsIdleServiceX.mm \
|
nsIdleServiceX.mm \
|
||||||
nsCocoaTextInputHandler.mm \
|
nsCocoaTextInputHandler.mm \
|
||||||
nsMacDockSupport.mm \
|
nsMacDockSupport.mm \
|
||||||
nsStandaloneNativeMenu.mm \
|
nsStandaloneNativeMenu.mm \
|
||||||
GfxInfo.mm \
|
GfxInfo.mm \
|
||||||
$(NULL)
|
WidgetTraceEvent.mm \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
ifeq (x86_64,$(TARGET_CPU))
|
ifeq (x86_64,$(TARGET_CPU))
|
||||||
CMMSRCS += ComplexTextInputPanel.mm
|
CMMSRCS += ComplexTextInputPanel.mm
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
#include "CustomCocoaEvents.h"
|
||||||
|
#include <Foundation/NSAutoreleasePool.h>
|
||||||
|
#include <mozilla/CondVar.h>
|
||||||
|
#include <mozilla/Mutex.h>
|
||||||
|
#include "mozilla/WidgetTraceEvent.h"
|
||||||
|
|
||||||
|
using mozilla::CondVar;
|
||||||
|
using mozilla::Mutex;
|
||||||
|
using mozilla::MutexAutoLock;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Mutex* sMutex = NULL;
|
||||||
|
CondVar* sCondVar = NULL;
|
||||||
|
bool sTracerProcessed = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
bool InitWidgetTracing()
|
||||||
|
{
|
||||||
|
sMutex = new Mutex("Event tracer thread mutex");
|
||||||
|
sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
|
||||||
|
return sMutex && sCondVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanUpWidgetTracing()
|
||||||
|
{
|
||||||
|
delete sMutex;
|
||||||
|
delete sCondVar;
|
||||||
|
sMutex = NULL;
|
||||||
|
sCondVar = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called from the main (UI) thread.
|
||||||
|
void SignalTracerThread()
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(*sMutex);
|
||||||
|
NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
|
||||||
|
sTracerProcessed = true;
|
||||||
|
sCondVar->Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called from the background tracer thread.
|
||||||
|
bool FireAndWaitForTracerEvent()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(sMutex && sCondVar, "Tracing not initialized!");
|
||||||
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
MutexAutoLock lock(*sMutex);
|
||||||
|
NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
|
||||||
|
|
||||||
|
// Post an application-defined event to the main thread's event queue
|
||||||
|
// and wait for it to get processed.
|
||||||
|
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
|
||||||
|
location:NSMakePoint(0,0)
|
||||||
|
modifierFlags:0
|
||||||
|
timestamp:0
|
||||||
|
windowNumber:0
|
||||||
|
context:NULL
|
||||||
|
subtype:kEventSubtypeTrace
|
||||||
|
data1:0
|
||||||
|
data2:0]
|
||||||
|
atStart:NO];
|
||||||
|
while (!sTracerProcessed)
|
||||||
|
sCondVar->Wait();
|
||||||
|
sTracerProcessed = false;
|
||||||
|
[pool release];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -43,6 +43,8 @@
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include "CustomCocoaEvents.h"
|
||||||
|
#include "mozilla/WidgetTraceEvent.h"
|
||||||
#include "nsAppShell.h"
|
#include "nsAppShell.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
|
@ -169,6 +171,27 @@ PRBool nsCocoaAppModalWindowList::GeckoModalAboveCocoaModal()
|
||||||
return (topItem.mWidget != nsnull);
|
return (topItem.mWidget != nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GeckoNSApplication
|
||||||
|
//
|
||||||
|
// Subclass of NSApplication for filtering out certain events.
|
||||||
|
@interface GeckoNSApplication : NSApplication
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GeckoNSApplication
|
||||||
|
- (void)sendEvent:(NSEvent *)anEvent
|
||||||
|
{
|
||||||
|
if ([anEvent type] == NSApplicationDefined &&
|
||||||
|
[anEvent subtype] == kEventSubtypeTrace) {
|
||||||
|
mozilla::SignalTracerThread();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[super sendEvent:anEvent];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
// AppShellDelegate
|
// AppShellDelegate
|
||||||
//
|
//
|
||||||
// Cocoa bridge class. An object of this class is registered to receive
|
// Cocoa bridge class. An object of this class is registered to receive
|
||||||
|
@ -286,7 +309,7 @@ nsAppShell::Init()
|
||||||
[NSBundle loadNibFile:
|
[NSBundle loadNibFile:
|
||||||
[NSString stringWithUTF8String:(const char*)nibPath.get()]
|
[NSString stringWithUTF8String:(const char*)nibPath.get()]
|
||||||
externalNameTable:
|
externalNameTable:
|
||||||
[NSDictionary dictionaryWithObject:[NSApplication sharedApplication]
|
[NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
|
||||||
forKey:@"NSOwner"]
|
forKey:@"NSOwner"]
|
||||||
withZone:NSDefaultMallocZone()];
|
withZone:NSDefaultMallocZone()];
|
||||||
|
|
||||||
|
@ -388,7 +411,7 @@ nsAppShell::ProcessGeckoEvents(void* aInfo)
|
||||||
timestamp:0
|
timestamp:0
|
||||||
windowNumber:0
|
windowNumber:0
|
||||||
context:NULL
|
context:NULL
|
||||||
subtype:0
|
subtype:kEventSubtypeNone
|
||||||
data1:0
|
data1:0
|
||||||
data2:0]
|
data2:0]
|
||||||
atStart:NO];
|
atStart:NO];
|
||||||
|
@ -410,7 +433,7 @@ nsAppShell::ProcessGeckoEvents(void* aInfo)
|
||||||
timestamp:0
|
timestamp:0
|
||||||
windowNumber:0
|
windowNumber:0
|
||||||
context:NULL
|
context:NULL
|
||||||
subtype:0
|
subtype:kEventSubtypeNone
|
||||||
data1:0
|
data1:0
|
||||||
data2:0]
|
data2:0]
|
||||||
atStart:NO];
|
atStart:NO];
|
||||||
|
|
|
@ -5649,6 +5649,15 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't send complex text input to a plugin in Cocoa event mode if
|
||||||
|
// either the Control key or the Command key is pressed -- even if the
|
||||||
|
// plugin has requested it, or we are already in IME composition. This
|
||||||
|
// conforms to our behavior in 64-bit mode and fixes bug 619217.
|
||||||
|
NSUInteger modifierFlags = [theEvent modifierFlags];
|
||||||
|
if ((modifierFlags & NSControlKeyMask) || (modifierFlags & NSCommandKeyMask)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will take care of all Carbon plugin events and also send Cocoa plugin
|
// This will take care of all Carbon plugin events and also send Cocoa plugin
|
||||||
|
|
|
@ -62,23 +62,24 @@ ifdef ACCESSIBILITY
|
||||||
CSRCS += maiRedundantObjectFactory.c
|
CSRCS += maiRedundantObjectFactory.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
nsWindow.cpp \
|
nsWindow.cpp \
|
||||||
nsAppShell.cpp \
|
nsAppShell.cpp \
|
||||||
nsWidgetFactory.cpp \
|
nsWidgetFactory.cpp \
|
||||||
nsToolkit.cpp \
|
nsToolkit.cpp \
|
||||||
nsBidiKeyboard.cpp \
|
nsBidiKeyboard.cpp \
|
||||||
nsLookAndFeel.cpp \
|
nsLookAndFeel.cpp \
|
||||||
nsGtkKeyUtils.cpp \
|
nsGtkKeyUtils.cpp \
|
||||||
nsFilePicker.cpp \
|
nsFilePicker.cpp \
|
||||||
nsSound.cpp \
|
nsSound.cpp \
|
||||||
nsNativeKeyBindings.cpp \
|
nsNativeKeyBindings.cpp \
|
||||||
nsScreenGtk.cpp \
|
nsScreenGtk.cpp \
|
||||||
nsScreenManagerGtk.cpp \
|
nsScreenManagerGtk.cpp \
|
||||||
nsImageToPixbuf.cpp \
|
nsImageToPixbuf.cpp \
|
||||||
nsAccessibilityHelper.cpp \
|
nsAccessibilityHelper.cpp \
|
||||||
nsGtkIMModule.cpp \
|
nsGtkIMModule.cpp \
|
||||||
$(NULL)
|
WidgetTraceEvent.cpp \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
ifdef MOZ_X11
|
ifdef MOZ_X11
|
||||||
CPPSRCS += nsIdleServiceGTK.cpp
|
CPPSRCS += nsIdleServiceGTK.cpp
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "mozilla/WidgetTraceEvent.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <mozilla/CondVar.h>
|
||||||
|
#include <mozilla/Mutex.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using mozilla::CondVar;
|
||||||
|
using mozilla::Mutex;
|
||||||
|
using mozilla::MutexAutoLock;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Mutex* sMutex = NULL;
|
||||||
|
CondVar* sCondVar = NULL;
|
||||||
|
bool sTracerProcessed = false;
|
||||||
|
|
||||||
|
// This function is called from the main (UI) thread.
|
||||||
|
gboolean TracerCallback(gpointer data)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(*sMutex);
|
||||||
|
NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
|
||||||
|
sTracerProcessed = true;
|
||||||
|
sCondVar->Notify();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
bool InitWidgetTracing()
|
||||||
|
{
|
||||||
|
sMutex = new Mutex("Event tracer thread mutex");
|
||||||
|
sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
|
||||||
|
return sMutex && sCondVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanUpWidgetTracing()
|
||||||
|
{
|
||||||
|
delete sMutex;
|
||||||
|
delete sCondVar;
|
||||||
|
sMutex = NULL;
|
||||||
|
sCondVar = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called from the background tracer thread.
|
||||||
|
bool FireAndWaitForTracerEvent()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(sMutex && sCondVar, "Tracing not initialized!");
|
||||||
|
|
||||||
|
// Send a default-priority idle event through the
|
||||||
|
// event loop, and wait for it to finish.
|
||||||
|
MutexAutoLock lock(*sMutex);
|
||||||
|
NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
|
||||||
|
g_idle_add_full(G_PRIORITY_DEFAULT,
|
||||||
|
TracerCallback,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
while (!sTracerProcessed)
|
||||||
|
sCondVar->Wait();
|
||||||
|
sTracerProcessed = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче