feat: clipboard support #61
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
mupen64/ugui!61
Loading…
Reference in a new issue
No description provided.
Delete branch "clipboard-support"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds the concept of
STATIC_ENV, which houses platform interfaces (only aclipboardAPI for now) that are provided by the user.Providing these is optional; default stub implementations are provided.
This new concept is leveraged to provide copy/paste functionality for certain controls:
textbox - Supports copy and paste
numberbox - Supports copy and paste (even pasting multiple numbers)
spinner - Supports copy and paste (inherits from textbox)
listbox - Supports copying (selected item)
Adoption
If you're running under a Mupen64 Lua environment, update your code like this:
Pull request overview
Introduces a
STATIC_ENVconcept to let host scripts optionally provide platform integrations (starting with clipboard), and wires that into input processing to enable copy/paste behaviors in several controls.Changes:
ugui.STATIC_ENVand new environment-related type definitions (Environment,UguiStaticEnvironment,UguiClipboard).textevents duringbegin_frame.Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.
Show a summary per file
STATIC_ENVto the public ugui table.Environmenttype block.UguiStaticEnvironmenttype definition.Environmenttype definition.begin_frameusing the clipboard provider.e.textinsertion.ugui.STATIC_ENV.clipboardto Mupen clipboard APIs.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
@ -64,1 +64,4 @@endif e.keycode == ugui.keycodes.VK_C and e.ctrl and data.selected_index ~= nil thenlocal item = control.items[data.selected_index]ugui.STATIC_ENV.clipboard.set(item)control.items[data.selected_index]can be nil ifselected_indexis out of range (the validator only checks type). Pressing Ctrl+C would then callclipboard.set(nil)and likely error. Clampdata.selected_indexto[1, #control.items]before indexing and/or guard against nil items before copying.@ -77,15 +77,31 @@ ugui.registry.numberbox = {if e.keycode == ugui.keycodes.VK_DOWN thentonumber(e.text)is too permissive for digit insertion/paste: it accepts strings like "1.2", "1e3", or "-1", which will makeset_digit_rangebehave incorrectly (non-digit chars change#e.text, can drive negative exponents, and produce non-integer results). Validate pasted input as digits-only (e.g.^%d+$) and truncate/clamp the digit count sodata.caret_index + #digits - 1never exceedscontrol.places.@ -95,0 +96,4 @@if e.keycode == ugui.keycodes.VK_C and e.ctrl and has_selection thenlocal selected_text = data.text:sub(lower_selection, higher_selection - 1)ugui.STATIC_ENV.clipboard.set(selected_text)endTextBox selection indices are caret positions (end is exclusive), as shown by the selection rendering in
styler.lua(text:sub(..., selection_end - 1)) and byremove_range’s implementation. Usingdata.text:sub(lower_selection, higher_selection)will copy one extra character; this should slice tohigher_selection - 1.@ -43,12 +43,34 @@ ugui.begin_frame = function(environment)if not ugui.internal.environment thenugui.begin_frameunconditionally callsugui.STATIC_ENV.clipboard.get(). If the clipboard provider is not configured (which the PR description says is optional), this will throw (attempt to index field 'clipboard' (a nil value)orattempt to call a nil value). Guard the call (checkugui.STATIC_ENV.clipboardand.get) and/or rely on a guaranteed default stub implementation.Typo in comment: "synthethic" should be "synthetic".
New clipboard/paste behavior is introduced here (transforming Ctrl+V into a synthetic
textevent). The repo has a fairly extensivetest/core.lua, but there are no tests covering this translation or the “clipboard provider optional” behavior; adding coverage would help prevent regressions (e.g., missing provider, multiple Ctrl+V events, empty clipboard).set_digit_rangebreaks ifindex + #digits - 1 > length(it computesinsert_powwith a negative exponent, leading to fractional powers and incorrect digit extraction/replacement). Add bounds handling (truncate digits to remaining length or early-return) and consider rejecting non-digitdigitsexplicitly so the function always returns an integer in[0, 10^length).@ -10,6 +10,7 @@ local ugui = {_DESCRIPTION = 'Flexible immediate-mode GUI library for Mupen Lua',_LICENSE = 'GPL-3',DEBUG = false,STATIC_ENV = {},STATIC_ENVis initialized as an empty table, but the rest of the changes assumeugui.STATIC_ENV.clipboard.get/setalways exist. With the default{}this will crash on the firstbegin_frame()or on Ctrl+C in controls. Provide a default stub clipboard provider here (e.g.,getreturning nil andsetas a no-op), or ensureSTATIC_ENV.clipboardis always populated during initialization.Pull request overview
Adds a configurable “static environment” surface (currently clipboard) and wires it into input handling to enable copy/paste for text-like controls, while also fixing/adding helper routines to support multi-character insertion.
Changes:
ugui.STATIC_ENV(with default stub clipboard provider) and new environment type definitions undersrc/ugui/environment/.textevents atbegin_frame, and adds Ctrl+C copy support in textbox/numberbox/listbox.insert_atsemantics and addsset_digit_rangeto support multi-digit insertion/paste innumberbox.Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
STATIC_ENVfield to the top-leveluguitable.Environmenttype doc (moved to dedicated file).insert_atand addsset_digit_rangefor multi-digit number edits.UguiStaticEnvironmentand installs default stub clipboard provider.Environmenttype documentation in a dedicated file.textevent translation using clipboard provider.insert_atbehavior.set_digit_range.ugui.STATIC_ENV.clipboardto Mupen’s clipboard API.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
@ -95,0 +96,4 @@if e.keycode == ugui.keycodes.VK_C and e.ctrl and has_selection thenlocal selected_text = data.text:sub(lower_selection, higher_selection - 1)ugui.STATIC_ENV.clipboard.set(selected_text)endClipboard copy/paste is new behavior (Ctrl+C here, Ctrl+V via
begin_framesynthetic text events), but there are no tests asserting that clipboard.set is called with the selected text and that a Ctrl+V key event results in inserting clipboard text. Adding unit tests (e.g., stubbingugui.STATIC_ENV.clipboardintest/textbox.lua) would help prevent regressions.@ -43,12 +43,34 @@ ugui.begin_frame = function(environment)if not ugui.internal.environment thenbegin_framecallsugui.STATIC_ENV.clipboard.get()every frame even when there is no Ctrl+V event. If clipboard access is expensive or has side effects on some platforms, this adds unnecessary overhead. Consider first scanningenvironment.key_eventsfor a Ctrl+V press and only then fetching the clipboard text (or fetch lazily inside the loop).This paste handling rewrites entries in the caller-provided
environment.key_eventstable in-place. That mutation can be surprising if the host app reuses the same events table elsewhere (e.g., for non-ugui hotkeys or logging). Consider applying the transformation to a copy that is only used forugui.internal.environment(leave the inputenvironmentuntouched).ugui.STATIC_ENV.clipboardis treated as always present here, butUguiStaticEnvironment.clipboardis annotated as optional and the PR description says providers are optional. If a consumer setsugui.STATIC_ENVwithout aclipboardfield (or sets it to nil), this will throw. Consider guarding the call (and treating missing clipboard as "no paste available").