Fix imageRect not being correctly set for fullscreen UI modes.

- This caused incorrectly positioning for ContextMenu
- With this fix, the positioning code in ContextMenu and related dialogs becomes a lot less complex
This commit is contained in:
Stephen Anthony 2019-05-12 19:12:30 -02:30
parent 9aa75502b2
commit 087dd1dbb9
7 changed files with 53 additions and 40 deletions

View File

@ -95,7 +95,7 @@ struct Size
Another very wide spread approach to rectangle classes treats (bottom,right)
also as a part of the rectangle.
Coneptually, both are sound, but the approach we use saves many intermediate
Conceptually, both are sound, but the approach we use saves many intermediate
computations (like computing the height in our case is done by doing this:
height = bottom - top;
while in the alternate system, it would be
@ -158,6 +158,18 @@ struct Rect
return x >= left && y >= top && x < right && y < bottom;
}
// Tests whether 'r' is completely contained within this rectangle.
// If it isn't, then set 'x' and 'y' such that moving 'r' to this
// position will make it be contained.
bool contains(uInt32& x, uInt32& y, const Rect& r) const {
if(r.left < left) x = left;
else if(r.right > right) x = r.left - (r.right - right);
if(r.top < top) y = top;
else if(r.bottom > bottom) y = r.top - (r.bottom - bottom);
return r.left != x || r.top != y;
}
friend ostream& operator<<(ostream& os, const Rect& r) {
os << r.point() << "," << r.size();
return os;

View File

@ -88,30 +88,31 @@ RomListSettings::RomListSettings(GuiObject* boss, const GUI::Font& font)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListSettings::show(uInt32 x, uInt32 y, int data)
void RomListSettings::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int data)
{
_xorig = x * instance().frameBuffer().hidpiScaleFactor();
_yorig = y * instance().frameBuffer().hidpiScaleFactor();
_item = data;
uInt32 scale = instance().frameBuffer().hidpiScaleFactor();
_xorig = bossRect.x() + x * scale;
_yorig = bossRect.y() + y * scale;
// Only show if we're inside the visible area
if(!bossRect.contains(_xorig, _yorig))
return;
_item = data;
open();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListSettings::center()
{
// Make sure the menu is exactly where it should be, in case the image
// offset has changed
const Common::Rect& image = instance().frameBuffer().imageRect();
const uInt32 scale = instance().frameBuffer().hidpiScaleFactor();
uInt32 x = image.x() + _xorig;
uInt32 y = image.y() + _yorig;
uInt32 tx = image.x() + image.width();
uInt32 ty = image.y() + image.height();
if(x + _w*scale > tx) x -= (x + _w*scale - tx);
if(y + _h*scale > ty) y -= (y + _h*scale - ty);
// First set position according to original coordinates
surface().setDstPos(_xorig, _yorig);
surface().setDstPos(x, y);
// Now make sure that the entire menu can fit inside the image bounds
// If not, we reset its position
if(!instance().frameBuffer().imageRect().contains(
_xorig, _yorig, surface().dstRect()))
surface().setDstPos(_xorig, _yorig);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -36,7 +36,7 @@ class RomListSettings : public Dialog, public CommandSender
/** Show dialog onscreen at the specified coordinates
('data' will be the currently selected line number in RomListWidget) */
void show(uInt32 x, uInt32 y, int data = -1);
void show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int data = -1);
/** This dialog uses its own positioning, so we override Dialog::center() */
void center() override;

View File

@ -248,7 +248,8 @@ void RomListWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
// Set selected and add menu at current x,y mouse location
_selectedItem = findItem(x, y);
scrollToSelected();
myMenu->show(x + getAbsX(), y + getAbsY(), _selectedItem);
myMenu->show(x + getAbsX(), y + getAbsY(),
dialog().surface().dstRect(), _selectedItem);
}
else
{

View File

@ -926,13 +926,13 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
{
// Windowed and fullscreen mode differ only in screen size
myWindowedModeList.add(
VideoMode(baseWidth, baseHeight, baseWidth, baseHeight, VideoMode::Stretch::Fill)
VideoMode(baseWidth, baseHeight, baseWidth, baseHeight, VideoMode::Stretch::None)
);
for(uInt32 i = 0; i < myFullscreenDisplays.size(); ++i)
{
myFullscreenModeLists[i].add(
VideoMode(baseWidth, baseHeight, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
VideoMode::Stretch::Fill, "", 1, i)
VideoMode::Stretch::None, "", 1, i)
);
}
}
@ -941,8 +941,6 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
{
EventHandlerState state = myOSystem.eventHandler().state();
if(fullscreen)
{
Int32 i = getCurrentDisplayIndex();
@ -959,6 +957,7 @@ const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
// Now select the best resolution depending on the state
// UI modes (launcher and debugger) have only one supported resolution
// so the 'current' one is the only valid one
EventHandlerState state = myOSystem.eventHandler().state();
if(state == EventHandlerState::DEBUGGER || state == EventHandlerState::LAUNCHER)
myCurrentModeList->setByZoom(1);
else // TIA mode
@ -979,7 +978,7 @@ const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::VideoMode::VideoMode()
: stretch(VideoMode::Stretch::Fill),
: stretch(VideoMode::Stretch::None),
description(""),
zoom(1),
fsIndex(-1)
@ -1035,6 +1034,10 @@ FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
iw = screen.w;
ih = screen.h;
break;
case Stretch::None:
// Don't do any scaling at all
break;
}
}
else
@ -1045,6 +1048,7 @@ FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
{
case Stretch::Preserve:
case Stretch::Fill:
case Stretch::None:
screen.w = iw;
screen.h = ih;
break;

View File

@ -57,7 +57,7 @@ class FrameBuffer
// 'screen' are the dimensions of the screen itself
struct VideoMode
{
enum class Stretch { Preserve, Fill };
enum class Stretch { Preserve, Fill, None };
Common::Rect image;
Common::Size screen;

View File

@ -68,14 +68,13 @@ void ContextMenu::addItems(const VariantList& items)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int item)
void ContextMenu::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int item)
{
const Common::Rect& image = instance().frameBuffer().imageRect();
uInt32 scale = instance().frameBuffer().hidpiScaleFactor();
_xorig = bossRect.x() + scale * x - image.x();
_yorig = bossRect.y() + scale * y - image.y();
_xorig = bossRect.x() + x * scale;
_yorig = bossRect.y() + y * scale;
// Only show if we're inside the visible area
// Only show menu if we're inside the visible area
if(!bossRect.contains(_xorig, _yorig))
return;
@ -88,18 +87,14 @@ void ContextMenu::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int it
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::center()
{
// Make sure the menu is exactly where it should be, in case the image
// offset has changed
const Common::Rect& image = instance().frameBuffer().imageRect();
recalc(image);
uInt32 x = image.x() + _xorig;
uInt32 y = image.y() + _yorig;
uInt32 tx = image.x() + image.width();
uInt32 ty = image.y() + image.height();
if(x + _w > tx) x -= (x + _w - tx);
if(y + _h > ty) y -= (y + _h - ty);
// First set position according to original coordinates
surface().setDstPos(_xorig, _yorig);
surface().setDstPos(x, y);
// Now make sure that the entire menu can fit inside the image bounds
// If not, we reset its position
if(!instance().frameBuffer().imageRect().contains(
_xorig, _yorig, surface().dstRect()))
surface().setDstPos(_xorig, _yorig);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -