Bug 1478576 - A mochitest for system font change notification. r?karlt,froydnj,jimm
The test case in this patch fails without the proper fix in the first patch
in this patch series.
In this patch two new nsIDOMWindowUtils APIs are introduced to change the
system font settins in tests. Currently the APIs work only on GTK+ platform.
Also to work the test case properly we need to open a new XUL window because we
don't propagate font changes into descendant documents yet (
bug 1478212).
MozReview-Commit-ID: 4OLxEkEuF8d
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4402,8 +4402,35 @@ nsTranslationNodeList::GetLength(uint32_
NS_IMETHODIMP
nsDOMWindowUtils::WrCapture()
{
if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
wrbc->Capture();
}
return NS_OK;
}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::SetSystemFont(const nsACString& aFontName)
+{
+ nsIWidget* widget = GetWidget();
+ if (!widget) {
+ return NS_OK;
+ }
+
+ nsAutoCString fontName(aFontName);
+ return widget->SetSystemFont(fontName);
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetSystemFont(nsACString& aFontName)
+{
+ nsIWidget* widget = GetWidget();
+ if (!widget) {
+ return NS_OK;
+ }
+
+ nsAutoCString fontName;
+ widget->GetSystemFont(fontName);
+ aFontName.Assign(fontName);
+ return NS_OK;
+}
+
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1926,16 +1926,21 @@ interface nsIDOMWindowUtils : nsISupport
void ensureDirtyRootFrame();
/**
* Capture the contents of the current WebRender frame and
* save them to a folder relative to the current working directory.
*/
void wrCapture();
+ /**
+ * NOTE: Currently works only on GTK+.
+ */
+ attribute ACString systemFont;
+
// These consts are only for testing purposes.
const long DEFAULT_MOUSE_POINTER_ID = 0;
const long DEFAULT_PEN_POINTER_ID = 1;
const long DEFAULT_TOUCH_POINTER_ID = 2;
// Match WidgetMouseEventBase::buttonType.
const long MOUSE_BUTTON_LEFT_BUTTON = 0;
const long MOUSE_BUTTON_MIDDLE_BUTTON = 1;
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -571,16 +571,19 @@ parent:
/**
* This function is used to notify the parent that it should display a
* canvas permission prompt.
*
* @param aFirstPartyURI first party of the tab that is requesting access.
*/
async ShowCanvasPermissionPrompt(nsCString aFirstPartyURI);
+ sync SetSystemFont(nsCString aFontName);
+ sync GetSystemFont() returns (nsCString retval);
+
child:
/**
* Notify the remote browser that it has been Show()n on this
* side, with the given |visibleRect|. This message is expected
* to trigger creation of the remote browser's "widget".
*
* |Show()| and |Move()| take IntSizes rather than Rects because
* content processes always render to a virtual <0, 0> top-left
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3601,16 +3601,36 @@ void
TabParent::SetIsActiveRecordReplayTab(bool aIsActive)
{
if (aIsActive != mIsActiveRecordReplayTab) {
gNumActiveRecordReplayTabs += aIsActive ? 1 : -1;
mIsActiveRecordReplayTab = aIsActive;
}
}
+mozilla::ipc::IPCResult
+TabParent::RecvSetSystemFont(const nsCString& aFontName)
+{
+ nsCOMPtr<nsIWidget> widget = GetWidget();
+ if (widget) {
+ widget->SetSystemFont(aFontName);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+TabParent::RecvGetSystemFont(nsCString* aFontName)
+{
+ nsCOMPtr<nsIWidget> widget = GetWidget();
+ if (widget) {
+ widget->GetSystemFont(*aFontName);
+ }
+ return IPC_OK();
+}
+
NS_IMETHODIMP
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
{
nsAuthInformationHolder* holder =
static_cast<nsAuthInformationHolder*>(aAuthInfo);
if (!net::gNeckoChild->SendOnAuthAvailable(mCallbackId,
holder->User(),
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -623,16 +623,21 @@ protected:
virtual mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch) override;
virtual mozilla::ipc::IPCResult RecvSetDimensions(const uint32_t& aFlags,
const int32_t& aX, const int32_t& aY,
const int32_t& aCx, const int32_t& aCy) override;
virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) override;
+ mozilla::ipc::IPCResult
+ RecvSetSystemFont(const nsCString& aFontName) override;
+ mozilla::ipc::IPCResult
+ RecvGetSystemFont(nsCString* aFontName) override;
+
ContentCacheInParent mContentCache;
nsIntRect mRect;
ScreenIntSize mDimensions;
ScreenOrientationInternal mOrientation;
float mDPI;
int32_t mRounding;
CSSToLayoutDeviceScale mDefaultScale;
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -833,16 +833,20 @@ description =
[PBrowser::DispatchWheelEvent]
description =
[PBrowser::DispatchMouseEvent]
description =
[PBrowser::DispatchKeyboardEvent]
description =
[PBrowser::EnsureLayersConnected]
description =
+[PBrowser::SetSystemFont]
+description = test only
+[PBrowser::GetSystemFont]
+description = test only
[PContent::SyncMessage]
description =
[PContent::CreateChildProcess]
description =
[PContent::BridgeToChildProcess]
description =
[PContent::OpenRecordReplayChannel]
description = bug 1475898 this could be async
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -1567,10 +1567,31 @@ PuppetWidget::WillDispatchKeyboardEvent(
TextEventDispatcher* aTextEventDispatcher,
WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndexOfKeypress,
void* aData)
{
MOZ_ASSERT(aTextEventDispatcher == mTextEventDispatcher);
}
+nsresult
+PuppetWidget::SetSystemFont(const nsCString& aFontName)
+{
+ if (!mTabChild) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mTabChild->SendSetSystemFont(aFontName);
+ return NS_OK;
+}
+
+nsresult
+PuppetWidget::GetSystemFont(nsCString& aFontName)
+{
+ if (!mTabChild) {
+ return NS_ERROR_FAILURE;
+ }
+ mTabChild->SendGetSystemFont(&aFontName);
+ return NS_OK;
+}
+
} // namespace widget
} // namespace mozilla
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -304,16 +304,19 @@ public:
nsIKeyEventInPluginCallback* aCallback) override;
virtual void LookUpDictionary(
const nsAString& aText,
const nsTArray<mozilla::FontRange>& aFontRangeArray,
const bool aIsVertical,
const LayoutDeviceIntPoint& aPoint) override;
+ nsresult SetSystemFont(const nsCString& aFontName) override;
+ nsresult GetSystemFont(nsCString& aFontName) override;
+
// TextEventDispatcherListener
using nsBaseWidget::NotifyIME;
NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
const IMENotification& aNotification) override;
NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override;
NS_IMETHOD_(void) OnRemovedFrom(
TextEventDispatcher* aTextEventDispatcher) override;
NS_IMETHOD_(void) WillDispatchKeyboardEvent(
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -7312,8 +7312,32 @@ nsWindow::SetCompositorHint(WindowCompos
cardinal_atom,
32, // format
GDK_PROP_MODE_REPLACE,
(guchar*)&value,
1);
}
}
#endif
+
+nsresult
+nsWindow::SetSystemFont(const nsCString& aFontName)
+{
+ GtkSettings* settings = gtk_settings_get_default();
+ g_object_set(settings, "gtk-font-name", aFontName.get(), nullptr);
+ return NS_OK;
+}
+
+nsresult
+nsWindow::GetSystemFont(nsCString& aFontName)
+{
+ GtkSettings* settings = gtk_settings_get_default();
+ gchar* fontName = nullptr;
+ g_object_get(settings,
+ "gtk-font-name", &fontName,
+ nullptr);
+ if (fontName) {
+ aFontName.Assign(fontName);
+ g_free(fontName);
+ }
+ return NS_OK;
+}
+
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -409,16 +409,19 @@ public:
// From GDK
int GdkCoordToDevicePixels(gint coord);
LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point);
LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y);
LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
virtual bool WidgetTypeSupportsAcceleration() override;
+ nsresult SetSystemFont(const nsCString& aFontName) override;
+ nsresult GetSystemFont(nsCString& aFontName) override;
+
typedef enum { CSD_SUPPORT_SYSTEM, // CSD including shadows
CSD_SUPPORT_CLIENT, // CSD without shadows
CSD_SUPPORT_NONE, // WM does not support CSD at all
CSD_SUPPORT_UNKNOWN
} CSDSupportLevel;
/**
* Get the support of Client Side Decoration by checking
* the XDG_CURRENT_DESKTOP environment variable.
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1691,16 +1691,28 @@ class nsIWidget : public nsISupports
*/
virtual void StopAsyncAutoscroll(const ScrollableLayerGuid& aGuid) = 0;
// If this widget supports out-of-process compositing, it can override
// this method to provide additional information to the compositor.
virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
{}
+ /**
+ * Setter/Getter of the system font setting for testing.
+ */
+ virtual nsresult SetSystemFont(const nsCString& aFontName)
+ {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ virtual nsresult GetSystemFont(nsCString& aFontName)
+ {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
private:
class LongTapInfo
{
public:
LongTapInfo(int32_t aPointerId, LayoutDeviceIntPoint& aPoint,
mozilla::TimeDuration aDuration,
nsIObserver* aObserver) :
mPointerId(aPointerId),
--- a/widget/tests/chrome.ini
+++ b/widget/tests/chrome.ini
@@ -85,16 +85,20 @@ skip-if = toolkit != "cocoa"
[test_secure_input.html]
support-files = file_secure_input.html
skip-if = toolkit != "cocoa"
[test_native_key_bindings_mac.html]
skip-if = toolkit != "cocoa" || verify
[test_system_status_bar.xul]
skip-if = toolkit != "cocoa"
+[test_system_font_changes.xul]
+support-files = system_font_changes.xul
+run-if = toolkit == 'gtk3' # Currently the test works on only gtk3
+
# Windows
# taskbar_previews.xul
# window_state_windows.xul
[test_chrome_context_menus_win.xul]
skip-if = toolkit != "windows"
support-files = chrome_context_menus_win.xul
[test_plugin_input_event.html]
skip-if = toolkit != "windows"
new file mode 100644
--- /dev/null
+++ b/widget/tests/system_font_changes.xul
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="system_font_changes_window"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="300"
+ height="300"
+ onload="start();">
+
+<span id="target" style="font:menu">Hello world</span>
+
+<script type="application/javascript"><![CDATA[
+ function is(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.is(condition, message);
+ }
+ function registerCleanupFunction(func) {
+ window.opener.wrappedJSObject.SimpleTest.registerCleanupFunction(func);
+ }
+
+ async function waitForFrame() {
+ return new Promise(resolve => {
+ requestAnimationFrame(resolve);
+ });
+ }
+
+ async function start() {
+ await waitForFrame();
+
+ const originalSystemFont = windowUtils.systemFont;
+ registerCleanupFunction(() => {
+ windowUtils.systemFont = originalSystemFont;
+ });
+
+ windowUtils.systemFont = 'Sans 11';
+ is(windowUtils.systemFont, 'Sans 11');
+
+ // Wait for two frames for the safety since the notification for system
+ // font changes is asynchronously processed.
+ await waitForFrame();
+ await waitForFrame();
+
+ const target = document.getElementById('target');
+ is(getComputedStyle(target).fontFamily, 'Sans');
+
+ windowUtils.systemFont = 'Serif 11';
+ is(windowUtils.systemFont, 'Serif 11');
+
+ await waitForFrame();
+ await waitForFrame();
+
+ is(getComputedStyle(target).fontFamily, 'Serif');
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+]]></script>
+</window>
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_system_font_changes.xul
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window title="Native menu system tests"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+SimpleTest.waitForExplicitFinish();
+window.open("system_font_changes.xul", "system_font_changes_window",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>