Skip to content

Commit

Permalink
SCUMM: Fix dragging the mouse out of the Mac slider's control
Browse files Browse the repository at this point in the history
The ghost of the drag handle wasn't erased. Now it is.
  • Loading branch information
Torbjörn Andersson committed Nov 8, 2023
1 parent a4b8277 commit f995f56
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 25 deletions.
61 changes: 38 additions & 23 deletions engines/scumm/gfx_mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,11 +1023,14 @@ bool MacGui::MacSlider::findWidget(int x, int y) const {

Common::Rect bounds = _bounds;

// While dragging the handle, you'r allowed to go outside the slider.
// While dragging the handle, you're allowed to go outside the slider.
// I don't know by how much, though.

if (_grabOffset >= 0) {
bounds.left -= 25;
bounds.right += 25;
bounds.top -= 50;
bounds.bottom += 50;
}

return bounds.contains(x, y);
Expand Down Expand Up @@ -1158,6 +1161,12 @@ void MacGui::MacSlider::drawArrow(Common::Rect r, const uint16 *bitmap, bool mar
_window->markRectAsDirty(r);
}

void MacGui::MacSlider::eraseDragHandle() {
Common::Rect r(_boundsBody.left + 1, _handlePos, _boundsBody.right - 1, _handlePos + 16);
fill(r);
_window->markRectAsDirty(r);
}

void MacGui::MacSlider::drawHandle(Common::Rect r) {
debug(2, "MacGui::MacSlider::drawHandle(%d)", r.top);

Expand Down Expand Up @@ -1230,11 +1239,9 @@ void MacGui::MacSlider::handleMouseUp(Common::Event &event) {
_downArrowPressed = false;
drawDownArrow(true);
} else if (_grabOffset >= 0) {
// Erase the drag rect, since the handle might not end up in
// Erase the drag handle, since the handle might not end up in
// the exact same spot.
Common::Rect r(_boundsBody.left + 1, _handlePos, _boundsBody.right - 1, _handlePos + 16);
fill(r);
_window->markRectAsDirty(r);
eraseDragHandle();

// Calculate new value and move the handle there
int newValue = calculateValueFromPos();
Expand All @@ -1255,38 +1262,46 @@ void MacGui::MacSlider::handleMouseMove(Common::Event &event) {
int y = event.mouse.y;

if (_grabOffset >= 0) {
Common::Rect r;
if (!findWidget(x, y)) {
eraseDragHandle();
drawHandle(getHandleRect(_value));
return;
}

r.left = _boundsBody.left + 1;
r.top = _handlePos;
r.right = _boundsBody.right - 1;
r.bottom = _handlePos + 16;
int newHandlePos = CLIP<int>(y - _grabOffset, _boundsBody.top, _boundsBody.bottom - 16);

fill(r);
_window->markRectAsDirty(r);
// Theoretically, we could end here if the handle position has
// not changed. However, we currently don't keep track of if
// the handle is hidden because the mouse has moved out of the
// widget's control.

eraseDragHandle();

_handlePos = newHandlePos;

Common::Rect handleRect = getHandleRect(_value);

if (r.intersects(handleRect)) {
if (ABS(_handlePos - handleRect.top) <= handleRect.height()) {
drawHandle(handleRect);
_window->markRectAsDirty(handleRect);
}

_handlePos = CLIP<int>(y - _grabOffset, _boundsBody.top, _boundsBody.bottom - 16);

r.moveTo(_boundsBody.left + 1, _handlePos);
int x0 = _boundsBody.left + 1;
int x1 = _boundsBody.right - 1;
int y0 = _handlePos;
int y1 = _handlePos + 16;

// Drawing a solid rectangle would be easier, and probably look
// better. But it seems the orginal Mac widget would draw the
// frame as an inverted slider background, even when drawing it
// on top of the slider handle.

fill(Common::Rect(r.left, r.top, r.right, r.top + 1), true);
fill(Common::Rect(r.left, r.bottom - 1, r.right, r.bottom), true);
fill(Common::Rect(r.left, r.top + 1, r.left + 1, r.bottom - 1), true);
fill(Common::Rect(r.right - 1, r.top + 1, r.right, r.bottom - 1), true);
fill(Common::Rect(x0, y0, x1, y0 + 1), true);
fill(Common::Rect(x0, y1 - 1, x1, y1), true);
fill(Common::Rect(x0, y0 + 1, x0 + 1, y1 - 1), true);
fill(Common::Rect(x1 - 1, y0 + 1, x1, y1 - 1), true);

_window->markRectAsDirty(r);
_window->markRectAsDirty(Common::Rect(x0, y0, x1, y1));
} else {
if (!_boundsButtonUp.contains(x, y)) {
if (_upArrowPressed) {
Expand Down Expand Up @@ -1338,8 +1353,8 @@ void MacGui::MacSlider::handleMouseHeld() {
if (_paging) {
Common::Rect r = getHandleRect(_value);

// Keep paging until at least half the scroll handle has gone past the
// mouse cursor. This may have to be tuned.
// Keep paging until at least half the scroll handle has gone
// past the mouse cursor. This may have to be tuned.

if (_paging == -1) {
if (p.y < r.top + r.height() / 2 && _value > _minValue) {
Expand Down
6 changes: 4 additions & 2 deletions engines/scumm/gfx_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ class MacGui {
MacButton(MacGui::MacDialogWindow *window, Common::Rect bounds, Common::String text, bool enabled) : MacWidget(window, bounds, text, enabled) {}

void draw(bool drawFocused = false);

void drawCorners(Common::Rect r, CornerLine *corner);
};

Expand All @@ -237,7 +236,6 @@ class MacGui {
MacStaticText(MacGui::MacDialogWindow *window, Common::Rect bounds, Common::String text, bool enabled) : MacWidget(window, bounds, text, true) {}

bool findWidget(int x, int y) const { return false; }

void draw(bool drawFocused = false);
};

Expand Down Expand Up @@ -314,6 +312,9 @@ class MacGui {
_minValue(minValue), _maxValue(maxValue),
_minPos(minPos), _maxPos(maxPos) {}

void getFocus() {}
void loseFocus() {}

void setValue(int value);
};

Expand All @@ -340,6 +341,7 @@ class MacGui {
void drawDownArrow(bool markAsDirty);
void drawArrow(Common::Rect r, const uint16 *bitmap, bool markAsDirty);

void eraseDragHandle();
void drawHandle(Common::Rect r);
void redrawHandle(int oldValue, int newValue);

Expand Down

0 comments on commit f995f56

Please sign in to comment.