зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1097897 - Add HiDPI support (scale) for Gtk2 and update and fix calculation of scaled screen borders. r=karlt
This commit is contained in:
Родитель
38b5ac26d2
Коммит
d975c07099
|
@ -229,6 +229,16 @@ gfxPlatformGtk::GetDPI()
|
|||
return sDPI;
|
||||
}
|
||||
|
||||
double
|
||||
gfxPlatformGtk::GetDPIScale()
|
||||
{
|
||||
// We want to set the default CSS to device pixel ratio as the
|
||||
// closest _integer_ multiple, so round the ratio of actual dpi
|
||||
// to CSS dpi (96)
|
||||
int32_t dpi = GetDPI();
|
||||
return (dpi > 96) ? round(dpi/96.0) : 1.0;
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
gfxPlatformGtk::GetOffscreenFormat()
|
||||
{
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
#endif
|
||||
|
||||
static int32_t GetDPI();
|
||||
static double GetDPIScale();
|
||||
|
||||
bool UseXRender() {
|
||||
#if defined(MOZ_X11)
|
||||
|
|
|
@ -63,6 +63,47 @@ nsScreenGtk :: GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth
|
|||
|
||||
} // GetAvailRect
|
||||
|
||||
double
|
||||
nsScreenGtk :: GetDPIScale()
|
||||
{
|
||||
double dpiScale = nsIWidget::DefaultScaleOverride();
|
||||
if (dpiScale <= 0.0) {
|
||||
dpiScale = gfxPlatformGtk::GetDPIScale();
|
||||
}
|
||||
return dpiScale;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScreenGtk :: GetRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
|
||||
{
|
||||
int32_t left, top, width, height;
|
||||
|
||||
GetRect(&left, &top, &width, &height);
|
||||
|
||||
double scaleFactor = 1.0 / GetDPIScale();
|
||||
*outLeft = NSToIntRound(left * scaleFactor);
|
||||
*outTop = NSToIntRound(top * scaleFactor);
|
||||
*outWidth = NSToIntRound(width * scaleFactor);
|
||||
*outHeight = NSToIntRound(height * scaleFactor);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScreenGtk :: GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
|
||||
{
|
||||
int32_t left, top, width, height;
|
||||
|
||||
GetAvailRect(&left, &top, &width, &height);
|
||||
|
||||
double scaleFactor = 1.0 / GetDPIScale();
|
||||
*outLeft = NSToIntRound(left * scaleFactor);
|
||||
*outTop = NSToIntRound(top * scaleFactor);
|
||||
*outWidth = NSToIntRound(width * scaleFactor);
|
||||
*outHeight = NSToIntRound(height * scaleFactor);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScreenGtk :: GetPixelDepth(int32_t *aPixelDepth)
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
NS_IMETHOD GetId(uint32_t* aId);
|
||||
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
|
||||
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
|
||||
NS_IMETHOD GetRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight);
|
||||
NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight);
|
||||
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);
|
||||
NS_IMETHOD GetColorDepth(int32_t* aColorDepth);
|
||||
|
||||
|
@ -41,6 +43,8 @@ public:
|
|||
void Init(XineramaScreenInfo *aScreenInfo);
|
||||
#endif /* MOZ_X11 */
|
||||
|
||||
static double GetDPIScale();
|
||||
|
||||
private:
|
||||
uint32_t mScreenNum;
|
||||
nsIntRect mRect;
|
||||
|
@ -48,4 +52,4 @@ private:
|
|||
uint32_t mId;
|
||||
};
|
||||
|
||||
#endif // nsScreenGtk_h___
|
||||
#endif // nsScreenGtk_h___
|
||||
|
|
|
@ -219,12 +219,30 @@ nsScreenManagerGtk :: ScreenForId ( uint32_t aId, nsIScreen **outScreen )
|
|||
// Returns the screen that contains the rectangle. If the rect overlaps
|
||||
// multiple screens, it picks the screen with the greatest area of intersection.
|
||||
//
|
||||
// The coordinates are in pixels (not app units) and in screen coordinates.
|
||||
// The coordinates are in CSS pixels (not app units) and in screen coordinates.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsScreenManagerGtk :: ScreenForRect ( int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
nsIScreen **aOutScreen )
|
||||
nsScreenManagerGtk :: ScreenForRect( int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
nsIScreen **aOutScreen )
|
||||
{
|
||||
uint32_t scale = nsScreenGtk::GetDPIScale();
|
||||
return ScreenForRectPix(aX*scale, aY*scale, aWidth*scale, aHeight*scale,
|
||||
aOutScreen);
|
||||
}
|
||||
|
||||
//
|
||||
// ScreenForRectPix
|
||||
//
|
||||
// Returns the screen that contains the rectangle. If the rect overlaps
|
||||
// multiple screens, it picks the screen with the greatest area of intersection.
|
||||
//
|
||||
// The coordinates are in device (X11) pixels.
|
||||
//
|
||||
nsresult
|
||||
nsScreenManagerGtk :: ScreenForRectPix( int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
nsIScreen **aOutScreen )
|
||||
{
|
||||
nsresult rv;
|
||||
rv = EnsureInit();
|
||||
|
@ -232,6 +250,7 @@ nsScreenManagerGtk :: ScreenForRect ( int32_t aX, int32_t aY,
|
|||
NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForRect");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// which screen ( index from zero ) should we return?
|
||||
uint32_t which = 0;
|
||||
// Optimize for the common case. If the number of screens is only
|
||||
|
@ -307,7 +326,7 @@ nsScreenManagerGtk :: GetNumberOfScreens(uint32_t *aNumberOfScreens)
|
|||
NS_IMETHODIMP
|
||||
nsScreenManagerGtk::GetSystemDefaultScale(float *aDefaultScale)
|
||||
{
|
||||
*aDefaultScale = 1.0f;
|
||||
*aDefaultScale = nsScreenGtk::GetDPIScale();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -337,7 +356,7 @@ nsScreenManagerGtk :: ScreenForNativeWidget (void *aWidget, nsIScreen **outScree
|
|||
gdk_window_get_geometry(GDK_WINDOW(aWidget), &x, &y, &width, &height);
|
||||
#endif
|
||||
gdk_window_get_origin(GDK_WINDOW(aWidget), &x, &y);
|
||||
rv = ScreenForRect(x, y, width, height, outScreen);
|
||||
rv = ScreenForRectPix(x, y, width, height, outScreen);
|
||||
} else {
|
||||
rv = GetPrimaryScreen(outScreen);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ private:
|
|||
virtual ~nsScreenManagerGtk();
|
||||
|
||||
nsresult EnsureInit();
|
||||
nsresult ScreenForRectPix(int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
nsIScreen **aOutScreen);
|
||||
|
||||
// Cached screen array. Its length is the number of screens we have.
|
||||
nsCOMArray<nsIScreen> mCachedScreenArray;
|
||||
|
@ -49,4 +52,4 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
#endif // nsScreenManagerGtk_h___
|
||||
#endif // nsScreenManagerGtk_h___
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsWidgetsCID.h"
|
||||
#include "nsDragService.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
#include "nsGtkKeyUtils.h"
|
||||
#include "nsGtkCursors.h"
|
||||
|
@ -741,7 +742,11 @@ nsWindow::GetDPI()
|
|||
double
|
||||
nsWindow::GetDefaultScaleInternal()
|
||||
{
|
||||
#if (MOZ_WIDGET_GTK == 3)
|
||||
return GdkScaleFactor();
|
||||
#else
|
||||
return gfxPlatformGtk::GetDPIScale();
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -878,29 +883,61 @@ nsWindow::IsVisible() const
|
|||
NS_IMETHODIMP
|
||||
nsWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
|
||||
{
|
||||
if (mIsTopLevel && mShell) {
|
||||
int width = GdkCoordToDevicePixels(gdk_screen_width());
|
||||
int height = GdkCoordToDevicePixels(gdk_screen_height());
|
||||
if (aAllowSlop) {
|
||||
if (*aX < (kWindowPositionSlop - mBounds.width))
|
||||
*aX = kWindowPositionSlop - mBounds.width;
|
||||
if (*aX > (width - kWindowPositionSlop))
|
||||
*aX = width - kWindowPositionSlop;
|
||||
if (*aY < (kWindowPositionSlop - mBounds.height))
|
||||
*aY = kWindowPositionSlop - mBounds.height;
|
||||
if (*aY > (height - kWindowPositionSlop))
|
||||
*aY = height - kWindowPositionSlop;
|
||||
} else {
|
||||
if (*aX < 0)
|
||||
*aX = 0;
|
||||
if (*aX > (width - mBounds.width))
|
||||
*aX = width - mBounds.width;
|
||||
if (*aY < 0)
|
||||
*aY = 0;
|
||||
if (*aY > (height - mBounds.height))
|
||||
*aY = height - mBounds.height;
|
||||
}
|
||||
if (!mIsTopLevel || !mShell)
|
||||
return NS_OK;
|
||||
|
||||
double dpiScale = GetDefaultScale().scale;
|
||||
|
||||
// we need to use the window size in logical screen pixels
|
||||
int32_t logWidth = std::max(NSToIntRound(mBounds.width / dpiScale), 1);
|
||||
int32_t logHeight = std::max(NSToIntRound(mBounds.height / dpiScale), 1);
|
||||
|
||||
/* get our playing field. use the current screen, or failing that
|
||||
for any reason, use device caps for the default screen. */
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
|
||||
if (screenmgr) {
|
||||
screenmgr->ScreenForRect(*aX, *aY, logWidth, logHeight,
|
||||
getter_AddRefs(screen));
|
||||
}
|
||||
|
||||
// We don't have any screen so leave the coordinates as is
|
||||
if (!screen)
|
||||
return NS_OK;
|
||||
|
||||
nsIntRect screenRect;
|
||||
if (mSizeMode != nsSizeMode_Fullscreen) {
|
||||
// For normalized windows, use the desktop work area.
|
||||
screen->GetAvailRectDisplayPix(&screenRect.x, &screenRect.y,
|
||||
&screenRect.width, &screenRect.height);
|
||||
} else {
|
||||
// For full screen windows, use the desktop.
|
||||
screen->GetRectDisplayPix(&screenRect.x, &screenRect.y,
|
||||
&screenRect.width, &screenRect.height);
|
||||
}
|
||||
|
||||
if (aAllowSlop) {
|
||||
if (*aX < screenRect.x - logWidth + kWindowPositionSlop)
|
||||
*aX = screenRect.x - logWidth + kWindowPositionSlop;
|
||||
else if (*aX >= screenRect.XMost() - kWindowPositionSlop)
|
||||
*aX = screenRect.XMost() - kWindowPositionSlop;
|
||||
|
||||
if (*aY < screenRect.y - logHeight + kWindowPositionSlop)
|
||||
*aY = screenRect.y - logHeight + kWindowPositionSlop;
|
||||
else if (*aY >= screenRect.YMost() - kWindowPositionSlop)
|
||||
*aY = screenRect.YMost() - kWindowPositionSlop;
|
||||
} else {
|
||||
if (*aX < screenRect.x)
|
||||
*aX = screenRect.x;
|
||||
else if (*aX >= screenRect.XMost() - logWidth)
|
||||
*aX = screenRect.XMost() - logWidth;
|
||||
|
||||
if (*aY < screenRect.y)
|
||||
*aY = screenRect.y;
|
||||
else if (*aY >= screenRect.YMost() - logHeight)
|
||||
*aY = screenRect.YMost() - logHeight;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче