mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 13:57:32 +00:00
Bug 1717182 - Make nsWindows::mIsRTL dynamic on Windows r=jrmuizel,gfx-reviewers
When high contrast mode is enabled, 2 caption buttons are painted on top of each other like Bug 1715990. Normally we did not notice 2 caption buttons, since they are painted on same position. One is drawn by DWM, another is drawn by gecko. But when RTL is changed after window creation, we notice 2 caption buttons. See Bug 1715990. One button exists on window's top left, another button exists on window's top right. This happens since position of button by DWM is not updated for RTL change. This bug is for fixing position of button by DWM when RTL is updated. It is not simple to remove button by gecko or button by DWM. Then this bug just fixes position of the button by DWM. Differential Revision: https://phabricator.services.mozilla.com/D118257
This commit is contained in:
parent
736c489d2a
commit
ed470f4001
@ -255,10 +255,85 @@ void WidgetShutdownObserver::Unregister() {
|
||||
}
|
||||
}
|
||||
|
||||
#define INTL_APP_LOCALES_CHANGED "intl:app-locales-changed"
|
||||
#define L10N_PSEUDO_PREF "intl.l10n.pseudo"
|
||||
|
||||
static const char* kObservedPrefs[] = {L10N_PSEUDO_PREF, nullptr};
|
||||
|
||||
NS_IMPL_ISUPPORTS(LocalesChangedObserver, nsIObserver)
|
||||
|
||||
LocalesChangedObserver::LocalesChangedObserver(nsBaseWidget* aWidget)
|
||||
: mWidget(aWidget), mRegistered(false) {
|
||||
Register();
|
||||
}
|
||||
|
||||
LocalesChangedObserver::~LocalesChangedObserver() {
|
||||
// No need to call Unregister(), we can't be destroyed until nsBaseWidget
|
||||
// gets torn down. The observer service and nsBaseWidget have a ref on us
|
||||
// so nsBaseWidget has to call Unregister and then clear its ref.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LocalesChangedObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
if (!mWidget) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!strcmp(aTopic, INTL_APP_LOCALES_CHANGED)) {
|
||||
RefPtr<nsBaseWidget> widget(mWidget);
|
||||
widget->LocalesChanged();
|
||||
} else {
|
||||
MOZ_ASSERT(!strcmp("nsPref:changed", aTopic));
|
||||
nsDependentString pref(aData);
|
||||
if (pref.EqualsLiteral(L10N_PSEUDO_PREF)) {
|
||||
RefPtr<nsBaseWidget> widget(mWidget);
|
||||
widget->LocalesChanged();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void LocalesChangedObserver::Register() {
|
||||
if (mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv =
|
||||
Preferences::AddStrongObservers(this, kObservedPrefs);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Adding observers failed.");
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, INTL_APP_LOCALES_CHANGED, true);
|
||||
}
|
||||
|
||||
// Locale might be update before registering
|
||||
RefPtr<nsBaseWidget> widget(mWidget);
|
||||
widget->LocalesChanged();
|
||||
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
void LocalesChangedObserver::Unregister() {
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, INTL_APP_LOCALES_CHANGED);
|
||||
}
|
||||
Preferences::RemoveObservers(this, kObservedPrefs);
|
||||
|
||||
mWidget = nullptr;
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
void nsBaseWidget::Shutdown() {
|
||||
NotifyLiveResizeStopped();
|
||||
RevokeTransactionIdAllocator();
|
||||
DestroyCompositor();
|
||||
FreeLocalesChangedObserver();
|
||||
FreeShutdownObserver();
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||
if (sPluginWidgetList) {
|
||||
@ -345,6 +420,13 @@ void nsBaseWidget::FreeShutdownObserver() {
|
||||
mShutdownObserver = nullptr;
|
||||
}
|
||||
|
||||
void nsBaseWidget::FreeLocalesChangedObserver() {
|
||||
if (mLocalesChangedObserver) {
|
||||
mLocalesChangedObserver->Unregister();
|
||||
}
|
||||
mLocalesChangedObserver = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsBaseWidget destructor
|
||||
@ -360,6 +442,7 @@ nsBaseWidget::~nsBaseWidget() {
|
||||
}
|
||||
}
|
||||
|
||||
FreeLocalesChangedObserver();
|
||||
FreeShutdownObserver();
|
||||
RevokeTransactionIdAllocator();
|
||||
DestroyLayerManager();
|
||||
|
@ -106,6 +106,23 @@ class WidgetShutdownObserver final : public nsIObserver {
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
// Helper class used for observing locales change.
|
||||
class LocalesChangedObserver final : public nsIObserver {
|
||||
~LocalesChangedObserver();
|
||||
|
||||
public:
|
||||
explicit LocalesChangedObserver(nsBaseWidget* aWidget);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void Register();
|
||||
void Unregister();
|
||||
|
||||
nsBaseWidget* mWidget;
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
/**
|
||||
* Common widget implementation used as base class for native
|
||||
* or crossplatform implementations of Widgets.
|
||||
@ -419,6 +436,8 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
bool aNeedsYFlip) override{};
|
||||
#endif
|
||||
|
||||
virtual void LocalesChanged() {}
|
||||
|
||||
protected:
|
||||
// These are methods for CompositorWidgetWrapper, and should only be
|
||||
// accessed from that class. Derived widgets can choose which methods to
|
||||
@ -679,6 +698,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
void RevokeTransactionIdAllocator();
|
||||
|
||||
void FreeShutdownObserver();
|
||||
void FreeLocalesChangedObserver();
|
||||
|
||||
nsIWidgetListener* mWidgetListener;
|
||||
nsIWidgetListener* mAttachedWidgetListener;
|
||||
@ -695,6 +715,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
RefPtr<APZEventState> mAPZEventState;
|
||||
SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
|
||||
RefPtr<WidgetShutdownObserver> mShutdownObserver;
|
||||
RefPtr<LocalesChangedObserver> mLocalesChangedObserver;
|
||||
RefPtr<TextEventDispatcher> mTextEventDispatcher;
|
||||
Cursor mCursor;
|
||||
nsBorderStyle mBorderStyle;
|
||||
|
@ -135,6 +135,7 @@
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/GPUProcessManager.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "mozilla/TextEvents.h" // For WidgetKeyboardEvent
|
||||
#include "mozilla/TextEventDispatcherListener.h"
|
||||
@ -1107,6 +1108,16 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsWindow::LocalesChanged() {
|
||||
bool isRTL = intl::LocaleService::GetInstance()->IsAppLocaleRTL();
|
||||
if (mIsRTL != isRTL) {
|
||||
DWORD dwAttribute = isRTL;
|
||||
DwmSetWindowAttribute(mWnd, DWMWA_NONCLIENT_RTL_LAYOUT, &dwAttribute,
|
||||
sizeof dwAttribute);
|
||||
mIsRTL = isRTL;
|
||||
}
|
||||
}
|
||||
|
||||
// Close this nsWindow
|
||||
void nsWindow::Destroy() {
|
||||
// WM_DESTROY has already fired, avoid calling it twice
|
||||
@ -4076,6 +4087,10 @@ LayerManager* nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
||||
return mLayerManager;
|
||||
}
|
||||
|
||||
if (!mLocalesChangedObserver) {
|
||||
mLocalesChangedObserver = new LocalesChangedObserver(this);
|
||||
}
|
||||
|
||||
RECT windowRect;
|
||||
::GetClientRect(mWnd, &windowRect);
|
||||
|
||||
|
@ -357,6 +357,8 @@ class nsWindow final : public nsWindowBase {
|
||||
bool SynchronouslyRepaintOnResize() override;
|
||||
virtual void MaybeDispatchInitialFocusEvent() override;
|
||||
|
||||
virtual void LocalesChanged() override;
|
||||
|
||||
protected:
|
||||
virtual ~nsWindow();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user