Bug 1370034 - Add nsIWidget::SetWindowTransform and implement it on Mac. r?spohl
MozReview-Commit-ID: 6tghHjKe6pb
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -311,16 +311,17 @@ public:
virtual void CaptureRollupEvents(nsIRollupListener * aListener,
bool aDoCapture) override;
virtual MOZ_MUST_USE nsresult GetAttention(int32_t aCycleCount) override;
virtual bool HasPendingInputEvent() override;
virtual nsTransparencyMode GetTransparencyMode() override;
virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
virtual void SetWindowShadowStyle(int32_t aStyle) override;
virtual void SetWindowOpacity(float aOpacity) override;
+ virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override;
virtual void SetShowsToolbarButton(bool aShow) override;
virtual void SetShowsFullScreenButton(bool aShow) override;
virtual void SetWindowAnimationType(WindowAnimationType aType) override;
virtual void SetDrawsTitle(bool aDrawTitle) override;
virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override;
virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
virtual void SetWindowTitlebarColor(nscolor aColor, bool aActive) override;
virtual void SetDrawsInTitlebar(bool aState) override;
@@ -414,14 +415,15 @@ protected:
// Whether we are currently using native fullscreen. It could be false because
// we are in the DOM fullscreen where we do not use the native fullscreen.
bool mInNativeFullScreenMode;
bool mIsAnimationSuppressed;
bool mInReportMoveEvent; // true if in a call to ReportMoveEvent().
bool mInResize; // true if in a call to DoResize().
+ bool mWindowTransformIsIdentity;
int32_t mNumModalDescendents;
InputContext mInputContext;
};
#endif // nsCocoaWindow_h_
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -79,16 +79,17 @@ extern BOOL gSomeMenuBarP
extern "C" {
// CGSPrivate.h
typedef NSInteger CGSConnection;
typedef NSInteger CGSWindow;
typedef NSUInteger CGSWindowFilterRef;
extern CGSConnection _CGSDefaultConnection(void);
extern CGError CGSSetWindowShadowAndRimParameters(const CGSConnection cid, CGSWindow wid, float standardDeviation, float density, int offsetX, int offsetY, unsigned int flags);
extern CGError CGSSetWindowBackgroundBlurRadius(CGSConnection cid, CGSWindow wid, NSUInteger blur);
+ extern CGError CGSSetWindowTransform(CGSConnection cid, CGSWindow wid, CGAffineTransform transform);
}
#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1"
NS_IMPL_ISUPPORTS_INHERITED(nsCocoaWindow, Inherited, nsPIWidgetCocoa)
// A note on testing to see if your object is a sheet...
// |mWindowType == eWindowType_sheet| is true if your gecko nsIWidget is a sheet
@@ -122,16 +123,17 @@ nsCocoaWindow::nsCocoaWindow()
, mInFullScreenTransition(false)
, mModal(false)
, mFakeModal(false)
, mSupportsNativeFullScreen(false)
, mInNativeFullScreenMode(false)
, mIsAnimationSuppressed(false)
, mInReportMoveEvent(false)
, mInResize(false)
+, mWindowTransformIsIdentity(true)
, mNumModalDescendents(0)
{
if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) {
// Disable automatic tabbing on 10.12. We need to do this before we
// orderFront any of our windows.
[NSWindow setAllowsAutomaticWindowTabbing:NO];
}
}
@@ -2173,16 +2175,78 @@ nsCocoaWindow::SetWindowOpacity(float aO
return;
}
[mWindow setAlphaValue:(CGFloat)aOpacity];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
+static inline CGAffineTransform
+GfxMatrixToCGAffineTransform(const gfx::Matrix& m)
+{
+ CGAffineTransform t;
+ t.a = m._11;
+ t.b = m._12;
+ t.c = m._21;
+ t.d = m._22;
+ t.tx = m._31;
+ t.ty = m._32;
+ return t;
+}
+
+void
+nsCocoaWindow::SetWindowTransform(const gfx::Matrix& aTransform)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+ if (!mWindow) {
+ return;
+ }
+
+ gfx::Matrix transform = aTransform;
+
+ // aTransform is a transform that should be applied to the window relative
+ // to its regular position: If aTransform._31 is 100, then we want the
+ // window to be displayed 100 pixels to the right of its regular position.
+ // The transform that CGSSetWindowTransform accepts has a different meaning:
+ // It's used to answer the question "For the screen pixel at x,y (with the
+ // origin at the top left), what pixel in the window's buffer (again with
+ // origin top left) should be displayed at that position?"
+ // In the example above, this means that we need to call
+ // CGSSetWindowTransform with a horizontal translation of -windowPos.x - 100.
+ // So we need to invert the transform and adjust it by the window's position.
+ if (!transform.Invert()) {
+ // Treat non-invertible transforms as the identity transform.
+ transform = gfx::Matrix();
+ }
+
+ bool isIdentity = transform.IsIdentity();
+ if (isIdentity && mWindowTransformIsIdentity) {
+ return;
+ }
+
+ transform.PreTranslate(-mBounds.x, -mBounds.y);
+
+ // We also need to account for the backing scale factor: aTransform is given
+ // in device pixels, but CGSSetWindowTransform works with logical display
+ // pixels.
+ CGFloat backingScale = BackingScaleFactor();
+ transform.PreScale(backingScale, backingScale);
+ transform.PostScale(1 / backingScale, 1 / backingScale);
+
+ CGSConnection cid = _CGSDefaultConnection();
+ CGSSetWindowTransform(cid, [mWindow windowNumber],
+ GfxMatrixToCGAffineTransform(transform));
+
+ mWindowTransformIsIdentity = isIdentity;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK;
+}
+
void nsCocoaWindow::SetShowsToolbarButton(bool aShow)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mWindow)
[mWindow setShowsToolbarButton:aShow];
NS_OBJC_END_TRY_ABORT_BLOCK;
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1108,16 +1108,24 @@ class nsIWidget : public nsISupports
/**
* Set the opacity of the window.
* Values need to be between 0.0f (invisible) and 1.0f (fully opaque).
*
* Ignored on child widgets and on non-Mac platforms.
*/
virtual void SetWindowOpacity(float aOpacity) {}
+ /**
+ * Set the transform of the window. Values are in device pixels,
+ * the origin is the top left corner of the window.
+ *
+ * Ignored on child widgets and on non-Mac platforms.
+ */
+ virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) {}
+
/*
* On Mac OS X, this method shows or hides the pill button in the titlebar
* that's used to collapse the toolbar.
*
* Ignored on child widgets and on non-Mac platforms.
*/
virtual void SetShowsToolbarButton(bool aShow) = 0;