Bug 1097897 - Add HiDPI support (scale) for Gtk2 and update and fix calculation of scaled screen borders. r=karlt

This commit is contained in:
Martin Stransky 2015-02-10 02:14:00 -05:00
Родитель 38b5ac26d2
Коммит d975c07099
7 изменённых файлов: 145 добавлений и 30 удалений

Просмотреть файл

@ -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;
}