Skip to content

Optimize dragging performance with requestAnimationFrame#6541

Merged
walterbender merged 4 commits intosugarlabs:masterfrom
Sidharthwin:master
Apr 11, 2026
Merged

Optimize dragging performance with requestAnimationFrame#6541
walterbender merged 4 commits intosugarlabs:masterfrom
Sidharthwin:master

Conversation

@Sidharthwin
Copy link
Copy Markdown
Contributor

Summary

This PR improves performance when resizing dialogs (e.g., JS Editor and resizable widgets) by throttling mousemove-based resize logic using requestAnimationFrame.

Currently, resize logic is executed directly inside a mousemove event handler, which can trigger hundreds of DOM updates per second. This leads to unnecessary layout recalculations and increased CPU usage during drag operations.


Changes

  • Wrapped doResize logic inside a requestAnimationFrame loop

  • Ensured only one resize update runs per frame

  • Reduced excessive DOM writes during continuous mouse movement

  • Applied changes to:

    • js/widgets/jseditor.js
    • js/utils/mb-dialog.js

Before

  • Resize handler executed on every mousemove event
  • Frequent layout recalculations
  • Noticeable lag/jank during resizing
  • Higher CPU usage

After

  • Resize updates aligned with browser render cycle (~60fps)
  • Reduced layout thrashing
  • Smoother resizing experience
  • Lower CPU usage

Implementation Details

A simple RAF-based throttle was introduced:

  • Store latest mouse position
  • Schedule resize using requestAnimationFrame
  • Prevent multiple RAF calls from stacking

This approach is consistent with existing optimizations used for block dragging.


Notes

This change focuses on improving performance without altering existing behavior or UI logic.


Checklist

  • Code follows project guidelines
  • No breaking changes introduced
  • Tested manually for resizing interactions
  • Ready for review

  • Performance

@github-actions github-actions Bot added performance Improves performance (load time, memory, rendering) size/M Medium: 50-249 lines changed area/javascript Changes to JS source files labels Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

✅ All Jest tests passed! This PR is ready to merge.

@github-actions github-actions Bot added the area/core Changes to core app entry files label Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

✅ All Jest tests passed! This PR is ready to merge.

@github-actions
Copy link
Copy Markdown
Contributor

❌ Some Jest tests failed. Please check the logs and fix the issues before merging.

Failed Tests:

help.test.js

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

❌ Some Jest tests failed. Please check the logs and fix the issues before merging.

Failed Tests:

help.test.js

@github-actions github-actions Bot removed the area/core Changes to core app entry files label Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

❌ Some Jest tests failed. Please check the logs and fix the issues before merging.

Failed Tests:

help.test.js

@Sidharthwin
Copy link
Copy Markdown
Contributor Author

@walterbender , @Ashutoshx7 pls review this . Whenever free :) . Checking the jest test case

@github-actions github-actions Bot added the area/tests Changes to test files label Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

✅ All Jest tests passed! This PR is ready to merge.

@Ashutoshx7
Copy link
Copy Markdown
Contributor

Ashutoshx7 commented Apr 11, 2026

@zealot-zew take a look
your thoughts on this
as u are the one who build this

update : i did test it out and did the code review looks goood to me

@Ashutoshx7
Copy link
Copy Markdown
Contributor

Ashutoshx7 commented Apr 11, 2026

@Sidharthwin thanks for working on this

the raf throttle pattern is consistent with our current implementation in widgetwindows
but just minor fix in setupwindowresize() add a null guard for resize direction inside the raf callback to prevent the potential crash id stopresize() between schedulling and excution

resizeRafId = requestAnimationFrame(() => {
    if (!isResizing || !resizeDirection) {
        resizeRafId = null;
        return;
    }
    // ... rest of resize logic
});

@karthik-dev56
Copy link
Copy Markdown
Contributor

Hey @Sidharthwin Using requestAnimationFrame here is absolutely the right call for improving dragging and resizing performance—nice work overall, the code looks really solid.

There’s just one subtle issue with how the coordinates are being captured during the throttling. Right now, clientX and clientY are taken at the moment requestAnimationFrame is triggered, and any subsequent mousemove events get ignored until that frame finishes. Because of this, the UI ends up using the first coordinates within that ~16ms frame instead of the latest ones. The result is a slight lag where the dragged element doesn’t fully keep up with the cursor, especially noticeable when the mouse stops moving.

Suggested fix:
Let’s store latestClientX and latestClientY outside of the requestAnimationFrame. Update these values on every mousemove event, and then read from them inside the requestAnimationFrame callback.

Could you apply this small adjustment in mb-dialog.js and also in both resize handlers within jseditor.js?

@Ashutoshx7
Copy link
Copy Markdown
Contributor

Ashutoshx7 commented Apr 11, 2026

Hey @Sidharthwin Using requestAnimationFrame here is absolutely the right call for improving dragging and resizing performance—nice work overall, the code looks really solid.

There’s just one subtle issue with how the coordinates are being captured during the throttling. Right now, clientX and clientY are taken at the moment requestAnimationFrame is triggered, and any subsequent mousemove events get ignored until that frame finishes. Because of this, the UI ends up using the first coordinates within that ~16ms frame instead of the latest ones. The result is a slight lag where the dragged element doesn’t fully keep up with the cursor, especially noticeable when the mouse stops moving.

Suggested fix: Let’s store latestClientX and latestClientY outside of the requestAnimationFrame. Update these values on every mousemove event, and then read from them inside the requestAnimationFrame callback.

Could you apply this small adjustment in mb-dialog.js and also in both resize handlers within jseditor.js?

hy i don't think so current implmentation is already good enough
i tried out locally i didn't notice any delay and also performance is up to the mark

@karthik-dev56
Copy link
Copy Markdown
Contributor

karthik-dev56 commented Apr 11, 2026

Hey @Ashutoshx7, you won't notice it on a fast laptop, but on lower-end devices it causes jitter. The current logic ignores the newest mouse movements during frame drops. It's only a 2-line change to make it completely bulletproof for all devices, let's just get it right!"

@Ashutoshx7
Copy link
Copy Markdown
Contributor

Ashutoshx7 commented Apr 11, 2026

Hey @Ashutoshx7, you won't notice it on a fast laptop, but on lower-end devices it causes jitter. The current logic ignores the newest mouse movements during frame drops. It's only a 2-line change to make it completely bulletproof for all devices, let's just get it right!"

but still i think having this as a addition is great ( just acts as a fallback or gaurdrail)

Copy link
Copy Markdown
Contributor

@Ashutoshx7 Ashutoshx7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zealot-zew whenever u get time take a look
i am approving look good to me

Copy link
Copy Markdown
Contributor

@Chaitu7032 Chaitu7032 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Sidharthwin
Copy link
Copy Markdown
Contributor Author

@Ashutoshx7 and @karthik-dev56 , Thanks for the feedback and suggestions . I will look into both the things , and get back to you with the best possible outcome

@github-actions
Copy link
Copy Markdown
Contributor

✅ All Jest tests passed! This PR is ready to merge.

@Sidharthwin
Copy link
Copy Markdown
Contributor Author

Sidharthwin commented Apr 11, 2026

@Ashutoshx7 and @karthik-dev56 , I agree with both of your feedbacks

I've updated the implementation :

  • Now it tracks the latest mouse coordinates outside the RAF callback and use them inside it
  • And added a guard inside the RAF callback to handle cases where dragging stops before execution

This should improve smoothness and avoid stale coordinate issues, especially on lower-end devices.

@Sidharthwin
Copy link
Copy Markdown
Contributor Author

@walterbender please you also give it a look , and tell me if any change is required

@Ashutoshx7
Copy link
Copy Markdown
Contributor

@walterbender ready for the merge

@walterbender walterbender merged commit 78c60df into sugarlabs:master Apr 11, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/javascript Changes to JS source files area/tests Changes to test files performance Improves performance (load time, memory, rendering) size/M Medium: 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants