remove fast scroll

This commit is contained in:
nakst 2021-10-15 13:55:16 +01:00
parent 20a9aecae0
commit 97f308e0a7
7 changed files with 76 additions and 120 deletions

View File

@ -2896,9 +2896,6 @@ void ScrollPane::SetPosition(int axis, double newScroll, bool sendMovedMessage)
else if (newScroll > limit[axis]) newScroll = limit[axis];
if (newScroll == position[axis]) return;
// Since we might be about to fast scroll, make sure the bits we are scrolling are valid.
UIWindowPaintNow(parent->window, nullptr, false);
double previous = position[axis];
position[axis] = newScroll;
if (bar[axis]) ScrollbarSetPosition(bar[axis], position[axis], false, false);
@ -6500,28 +6497,16 @@ void EsElementRepaint(EsElement *element, const EsRectangle *region) {
}
void EsElementRepaintForScroll(EsElement *element, EsMessage *message, EsRectangle border) {
EsRectangle content = ES_RECT_4(border.l, element->width - border.r, border.t, element->height - border.b);
EsRectangle repaint = content;
int64_t delta = message->scrollbarMoved.scroll - message->scrollbarMoved.previous;
// TODO Improved fast scroll:
// - Set a scroll rectangle in the window.
// - If one is already marked, then don't attempt a fast scroll.
// - When painting, exclude anything containing in the scroll rectangle.
// - When sending bits to the WM, give it the scroll rectangle to apply first.
if (message->type == ES_MSG_SCROLL_Y) {
if (delta > 0) repaint.t = element->height - delta - border.b;
else repaint.b = border.t - delta;
} else if (message->type == ES_MSG_SCROLL_X) {
if (delta > 0) repaint.l = element->width - delta - border.r;
else repaint.r = border.l - delta;
} else {
EsAssert(false);
}
EsElementRepaint(element);
EsRectangle rectangle = element->GetWindowBounds(false);
EsRectangle scrollBits = Translate(content, rectangle.l, rectangle.t);
EsSyscall(ES_SYSCALL_WINDOW_SET_BITS, element->window->handle, (uintptr_t) &scrollBits, delta,
message->type == ES_MSG_SCROLL_Y ? WINDOW_SET_BITS_SCROLL_VERTICAL : WINDOW_SET_BITS_SCROLL_HORIZONTAL);
repaint = EsRectangleIntersection(repaint, content);
EsElementRepaint(element, &repaint);
UIWindowPaintNow(element->window, nullptr, false);
(void) message;
(void) border;
}
bool EsElementStartAnimating(EsElement *element) {

View File

@ -1257,7 +1257,7 @@ struct EsProcessState {
struct EsPainter {
EsRectangle clip;
int offsetX, offsetY, width, height;
int32_t offsetX, offsetY, width, height;
void *style;
EsPaintTarget *target;
}
@ -2119,6 +2119,7 @@ function EsRectangle EsRectangleSubtract(EsRectangle a, EsRectangle b);
function EsRectangle EsRectangleTranslate(EsRectangle a, EsRectangle b);
function bool EsRectangleEquals(EsRectangle a, EsRectangle b);
function bool EsRectangleContains(EsRectangle a, int32_t x, int32_t y);
function bool EsRectangleContainsAll(EsRectangle parent, EsRectangle child); // Returns true iff the child rectangle is entirely contained within parent.
function void EsSort(void *_base, size_t nmemb, size_t size, EsComparisonCallback compar, EsGeneric argument);
function void EsSortWithSwapCallback(void *_base, size_t nmemb, size_t size, EsComparisonCallback compar, EsGeneric argument, EsSwapCallback swap);

View File

@ -304,9 +304,11 @@ struct GlobalData {
#define K_SYSTEM_CONFIGURATION K_SYSTEM_FOLDER "/Default.ini"
#define WINDOW_SET_BITS_NORMAL (0)
#define WINDOW_SET_BITS_SCROLL_HORIZONTAL (1)
#define WINDOW_SET_BITS_SCROLL_VERTICAL (2)
#define WINDOW_SET_BITS_AFTER_RESIZE (3)
#define WINDOW_SET_BITS_AFTER_RESIZE (1)
#define FAST_SCROLL_HORIZONTAL (1)
#define FAST_SCROLL_VERTICAL (2)
#define FAST_SCROLL_DO_NOT_ATTEMPT (3)
#define CURSOR_USE_ACCELERATION (1 << 0)
#define CURSOR_USE_ALT_SLOW (1 << 1)

View File

@ -500,7 +500,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_BITS) {
bool isEmbed = _window.type == KERNEL_OBJECT_EMBEDDED_WINDOW;
Window *window = isEmbed ? ((EmbeddedWindow *) _window.object)->container : ((Window *) _window.object);
if (!window || (isEmbed && currentProcess != ((EmbeddedWindow *) _window.object)->owner)) {
if (!window || (isEmbed && currentProcess != ((EmbeddedWindow *) _window.object)->owner) || window->closed) {
SYSCALL_RETURN(ES_SUCCESS, false);
}
@ -511,109 +511,73 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_BITS) {
region = Translate(region, insets.l, insets.t);
}
if (argument3 == WINDOW_SET_BITS_SCROLL_VERTICAL || argument3 == WINDOW_SET_BITS_SCROLL_HORIZONTAL) {
ptrdiff_t scrollDelta = argument2;
bool scrollVertical = argument3 == WINDOW_SET_BITS_SCROLL_VERTICAL;
EsRectangle originalRegion = region;
SYSCALL_BUFFER(argument2, Width(region) * Height(region) * 4, 1, false);
KMutexAcquire(&windowManager.mutex);
if (scrollVertical) {
if (scrollDelta < 0) region.b += scrollDelta;
else region.t += scrollDelta;
} else {
if (scrollDelta < 0) region.r += scrollDelta;
else region.l += scrollDelta;
bool resizeQueued = false;
if (argument3 == WINDOW_SET_BITS_AFTER_RESIZE && windowManager.resizeWindow == window) {
if (isEmbed) windowManager.resizeReceivedBitsFromEmbed = true;
else windowManager.resizeReceivedBitsFromContainer = true;
if (windowManager.resizeReceivedBitsFromContainer && windowManager.resizeReceivedBitsFromEmbed) {
// Resize complete.
resizeQueued = windowManager.resizeQueued;
windowManager.resizeQueued = false;
windowManager.resizeWindow = nullptr;
windowManager.resizeSlow = KGetTimeInMs() - windowManager.resizeStartTimeStampMs >= RESIZE_SLOW_THRESHOLD
|| windowManager.inspectorWindowCount /* HACK anti-flicker logic interfers with the inspector's logging */;
// EsPrint("Resize complete in %dms%z.\n", KGetTimeInMs() - windowManager.resizeStartTimeStampMs, windowManager.resizeSlow ? " (slow)" : "");
}
}
KMutexAcquire(&windowManager.mutex);
uintptr_t stride = Width(region) * 4;
EsRectangle clippedRegion = EsRectangleIntersection(region, ES_RECT_2S(surface->width, surface->height));
if (window->closed
|| region.l < 0 || region.r > (int32_t) surface->width
|| region.t < 0 || region.b > (int32_t) surface->height
|| region.l >= region.r || region.t >= region.b) {
} else {
surface->Scroll(region, scrollDelta, scrollVertical);
window->Update(&originalRegion, true);
window->queuedScrollUpdate = true;
// Don't update the screen until the rest of the window is painted.
}
EsRectangle directUpdateSubRegion;
KMutexRelease(&windowManager.mutex);
if (window->style == ES_WINDOW_CONTAINER && !isEmbed) {
directUpdateSubRegion = ES_RECT_4(0, window->width, 0, insets.t);
} else if (window->style == ES_WINDOW_CONTAINER && isEmbed) {
directUpdateSubRegion = ES_RECT_4(insets.l, window->width - insets.r, insets.t, window->height - insets.b);
} else {
bool skipUpdate = false;
SYSCALL_BUFFER(argument2, Width(region) * Height(region) * 4, 1, false);
KMutexAcquire(&windowManager.mutex);
directUpdateSubRegion = ES_RECT_4(0, window->width, 0, window->height);
}
bool resizeQueued = false;
bool didDirectUpdate = false;
if (argument3 == WINDOW_SET_BITS_AFTER_RESIZE && windowManager.resizeWindow == window) {
if (isEmbed) windowManager.resizeReceivedBitsFromEmbed = true;
else windowManager.resizeReceivedBitsFromContainer = true;
if (windowManager.resizeReceivedBitsFromContainer && windowManager.resizeReceivedBitsFromEmbed) {
// Resize complete.
resizeQueued = windowManager.resizeQueued;
windowManager.resizeQueued = false;
windowManager.resizeWindow = nullptr;
windowManager.resizeSlow = KGetTimeInMs() - windowManager.resizeStartTimeStampMs >= RESIZE_SLOW_THRESHOLD
|| windowManager.inspectorWindowCount /* HACK anti-flicker logic interfers with the inspector's logging */;
#if 0
EsPrint("Resize complete in %dms%z.\n", KGetTimeInMs() - windowManager.resizeStartTimeStampMs, windowManager.resizeSlow ? " (slow)" : "");
#endif
}
}
if (window->closed) {
skipUpdate = true;
} else {
uintptr_t stride = Width(region) * 4;
EsRectangle clippedRegion = EsRectangleIntersection(region, ES_RECT_2S(surface->width, surface->height));
EsRectangle directUpdateSubRegion;
if (window->style == ES_WINDOW_CONTAINER && !isEmbed) {
directUpdateSubRegion = ES_RECT_4(0, window->width, 0, insets.t);
} else if (window->style == ES_WINDOW_CONTAINER && isEmbed) {
directUpdateSubRegion = ES_RECT_4(insets.l, window->width - insets.r, insets.t, window->height - insets.b);
} else {
directUpdateSubRegion = ES_RECT_4(0, window->width, 0, window->height);
}
if (argument3 != WINDOW_SET_BITS_AFTER_RESIZE && EsRectangleEquals(region, EsRectangleIntersection(region, directUpdateSubRegion))) {
skipUpdate = window->UpdateDirect((K_USER_BUFFER uint32_t *) argument2, stride, clippedRegion);
}
if (argument3 != WINDOW_SET_BITS_AFTER_RESIZE && EsRectangleEquals(region, EsRectangleIntersection(region, directUpdateSubRegion))) {
didDirectUpdate = window->UpdateDirect((K_USER_BUFFER uint32_t *) argument2, stride, clippedRegion);
}
#define SET_BITS_REGION(...) { \
EsRectangle subRegion = EsRectangleIntersection(clippedRegion, ES_RECT_4(__VA_ARGS__)); \
if (ES_RECT_VALID(subRegion)) { surface->SetBits((K_USER_BUFFER const uint8_t *) argument2 \
+ stride * (subRegion.t - clippedRegion.t) + 4 * (subRegion.l - clippedRegion.l), stride, subRegion); } }
EsRectangle subRegion = EsRectangleIntersection(clippedRegion, ES_RECT_4(__VA_ARGS__)); \
if (ES_RECT_VALID(subRegion)) { surface->SetBits((K_USER_BUFFER const uint8_t *) argument2 \
+ stride * (subRegion.t - clippedRegion.t) + 4 * (subRegion.l - clippedRegion.l), stride, subRegion); } }
if (window->style == ES_WINDOW_CONTAINER && !isEmbed) {
SET_BITS_REGION(0, window->width, 0, insets.t);
SET_BITS_REGION(0, insets.l, insets.t, window->height - insets.b);
SET_BITS_REGION(window->width - insets.r, window->width, insets.t, window->height - insets.b);
SET_BITS_REGION(0, window->width, window->height - insets.b, window->height);
} else if (window->style == ES_WINDOW_CONTAINER && isEmbed) {
SET_BITS_REGION(insets.l, window->width - insets.r, insets.t, window->height - insets.b);
} else {
SET_BITS_REGION(0, window->width, 0, window->height);
}
}
window->Update(&region, !skipUpdate);
if (!skipUpdate || window->queuedScrollUpdate) {
window->queuedScrollUpdate = false;
GraphicsUpdateScreen();
}
if (resizeQueued) {
window->Move(windowManager.resizeQueuedRectangle, ES_WINDOW_MOVE_DYNAMIC);
}
KMutexRelease(&windowManager.mutex);
if (window->style == ES_WINDOW_CONTAINER && !isEmbed) {
SET_BITS_REGION(0, window->width, 0, insets.t);
SET_BITS_REGION(0, insets.l, insets.t, window->height - insets.b);
SET_BITS_REGION(window->width - insets.r, window->width, insets.t, window->height - insets.b);
SET_BITS_REGION(0, window->width, window->height - insets.b, window->height);
} else if (window->style == ES_WINDOW_CONTAINER && isEmbed) {
SET_BITS_REGION(insets.l, window->width - insets.r, insets.t, window->height - insets.b);
} else {
SET_BITS_REGION(0, window->width, 0, window->height);
}
window->Update(&region, !didDirectUpdate);
if (!didDirectUpdate) {
GraphicsUpdateScreen();
}
if (resizeQueued) {
window->Move(windowManager.resizeQueuedRectangle, ES_WINDOW_MOVE_DYNAMIC);
}
KMutexRelease(&windowManager.mutex);
SYSCALL_RETURN(ES_SUCCESS, false);
}

View File

@ -7,7 +7,6 @@
// Terminology:
// Dynamic resize - flicker-free resizing in container windows with an embedded window owned by a separate process.
// Direct update - paint first onto the video card's framebuffer, then onto the window manager's; used to reduce latency.
// Fast scroll - scrolling by shifting the bits in the window's surface, rather than repainting the entire area.
struct EmbeddedWindow {
void Destroy();
@ -35,7 +34,7 @@ struct Window {
// State:
EsWindowStyle style;
EsRectangle solidOffsets, embedInsets;
bool solid, noClickActivate, hidden, isMaximised, alwaysOnTop, hoveringOverEmbed, queuedScrollUpdate, activationClick, noBringToFront;
bool solid, noClickActivate, hidden, isMaximised, alwaysOnTop, hoveringOverEmbed, activationClick, noBringToFront;
volatile bool closed;
// Appearance:

View File

@ -134,6 +134,10 @@ bool EsRectangleContains(EsRectangle a, int32_t x, int32_t y) {
return ES_RECT_VALID(a) && a.l <= x && a.r > x && a.t <= y && a.b > y;
}
bool EsRectangleContainsAll(EsRectangle parent, EsRectangle child) {
return ES_RECT_VALID(parent) && child.l >= parent.l && child.r <= parent.r && child.t >= parent.t && child.b <= parent.b;
}
EsRectangle EsRectangleSplit(EsRectangle *a, int32_t amount, char side, int32_t gap) {
EsRectangle b = *a;
if (side == 'l') a->l += amount + gap, b.r = a->l - gap;

View File

@ -491,3 +491,4 @@ _EsOpenDocumentEnumerate=489
EsDialogGetContentArea=490
_EsDebugCommand=491
DateToLinear=492
EsRectangleContainsAll=493