Closed lc-soft closed 1 year ago
@lc-soft has funded $2.00 to this issue.
@lc-soft win上 一些组合键输入乱码 例如:ctrl+v ctrl+n 等。 顺便附上 ctrl+v win32实现
static void OnKeyup(LCUI_Widget w, LCUI_WidgetEvent e, void *arg)
{
if (e->key.code == 229 || e->key.code == 86)
{
if (LCUIKeyboard_IsHit(17))
{
OpenClipboard(NULL);
HGLOBAL hGlobal = NULL;
hGlobal = GetClipboardData(CF_UNICODETEXT);
wchar_t *pGlobal = (wchar_t *)GlobalLock(hGlobal);
CloseClipboard();
TextEdit_InsertTextW(w, pGlobal);
}
}
}
@tangxg 这方式获取到的是纯文本吗?如果剪切板里有图片或富文本内容,那 GlobalLock()
获取到的是什么内容?
@lc-soft 目前只是在win10上测试过 获取(word,网页,VS编辑器,富文本编辑器等等)是纯文本,其他未测试过。 我看了下WIN32API 复制文件时应该可以取到 路径 测试发现内存地址都没得 是个NULL。
@lc-soft How would you expect the feature to be implemented? I assume the approach would be adding clipboard.c to platform (and equivalent linux_x11clipboard.c)
But then, how would the copy event be handled, It doesn't seem synchronous. The linked SDL approach seems to have a blocking while loop, however, I've seen another implementation, which can be found here. The explanation I've found was
As you ask another application to prepare the buffer, and that may take some time, the request is asynchronous: the owner prepares the buffer, saves it in a specified location (window property is used as a temporary storage) and notifies you with SelectionNotify event when it's done.
So I'm not certain you can just request XNextEvent
and guarantee that next event will be SelectionNotify
.
@WhoAteDaCake I expect the feature to be implemented as follows:
src/clipboard.c
.LCUI_BindSysEvent()
to bind the SelectionNotify
event handler.SelectionNotify
event and store the clipboard content, only after calling the constructor function (for example: clipboard_create()
).Wouldn't it have to know which widget is currently in focus, so it knows where to send the data once SelectionNotify
is retrieved.
Since SelectionNotify is triggered after XConvertSelection
is called, we should know where the event originated from.
Also, from what I understand we need to track the variables passed down to XConvertSelection
, so there would need to be some sort of state
My idea is to separate into something like:
Though I can image you'd want to avoid using things like LCUIMutex_Init
within platform specific code, so not really sure what's the best approach here :thinking:
Any thoughts
Wouldn't it have to know which widget is currently in focus, so it knows where to send the data once
SelectionNotify
is retrieved. Since SelectionNotify is triggered afterXConvertSelection
is called, we should know where the event originated from. Also, from what I understand we need to track the variables passed down toXConvertSelection
, so there would need to be some sort of stateMy idea is to separate into something like:
Though I can image you'd want to avoid using things like
LCUIMutex_Init
within platform specific code, so not really sure what's the best approach here thinkingAny thoughts
@WhoAteDaCake Why call the new ReigsterPaste()
function instead of the existing BindEvent()
function?
I expected the clipboard event processing flow to be as follows:
LCUI_PASTE
eventLCUIWIdget_OnPaste()
event handlerLCUIWidget_GetFocus()
to get focus widget (we assume TextEdit widget is the focus)LCUI_WEVENT_PASTE
event for focus widgetTextEdit_OnPaste()
event handlerClipboard_GetText()
TextEdit_InsertTextW()
@lc-soft
The problem is at the step:
Clipboard text can't be retrieved synchronously, we need to ask for it, by calling XConvertSelection
with some variables (which we need to store and reference when copying the clipboard after SelectionNotify is received). Now we have to wait until SelectionNotify
is received from the system and only then can we get the actual text.
I need to try and implement first I think, rather than guessing, but I think it we would wan't to let each platform handle the initial bit, so:
SelectionNotify
OnSelectionNotifyLCUI_PASTE_READY
event LCUI_PASTE_READY
LCUI_PASTE
*SOME SORT OF INTERNAL EVENT - Not sure what's the best one to use here
Now we can continue with the steps you've mentioned.
I guess the biggest concern is how to communicate for the Widget -> System
flow and Widget -> System -> Platform
, since for Copy
event, I think we will need to store the copied text on the platform level (linux_x11clipboard.c) due to the SelectionRequest
event being called.
If we choose to do that, we could skip the last step I've mentioned and have clipboard.c
call platform specific implementation to retrieve the pasted text.
I hope I'm making sense, let me know if any of my assumptions are wrong, I'm still trying to wrap my head around the codebase :)
Clipboard text can't be retrieved synchronously, we need to ask for it
Yes, I know. My idea is to asynchronously process SelectionNotify
event and store clipboard data, and when the data is ready, trigger the LCUI_PASTE
event to tell TextEdit widget, This makes the call to 'Clipboard_GetText()' synchronous for TextEdit.
I need to try and implement first I think, rather than guessing, but I think it we would wan't to let each platform handle the initial bit, so: ...
I think LCUI_PASTE_READY
and LCUI_PASTE
should be merged.
I guess the biggest concern is how to communicate for the Widget -> System flow and Widget -> System -> Platform, since for Copy event, I think we will need to store the copied text on the platform level (linux_x11clipboard.c) due to the SelectionRequest event being called.
I agree.
@lc-soft Few questions
LCUI_RegisterPaste
event to be called directly from OnKeyboardMessage
or should it trigger a custom event? @WhoAteDaCake
Sorry, there are some problems with my comments above, the idea described in my comment is only suitable for read clipboard content when CTRL+V is pressed, not for read clipboard content at any time.
I redesigned the usage of the Clipboard API. The example pseudo code is as follows:
typedef struct LCUI_TextEditRec_ {
// ...
LCUI_Clipboard clipboard;
};
void TextEdit_OnInit(LCUI_Widget w)
{
// ...
// Create a clipboard object for storing clipboard data
textedit->clipboard = LCUI_CreateClipboard();
// ...
}
void TextEdit_OnDestroy(LCUI_Widget w)
{
// ...
LCUI_DestroyClipboard(textedit->clipboard);
textedit->clipboard = NULL;
// ...
}
void TextEdit_OnPaste(LCUI_Widget w, LCUI_WidgetEvent e, void *arg)
{
const char *text;
const wchar_t *wtext;
LCUI_Clipboard cb = arg;
if (Clipboard_HasText(cb)) {
text = Clipboard_GetText(cb);
// Convert to unicode string
// ...
TextEdit_InsertTextW(w, wtext);
}
}
// In Linux x11, this function will be called when SelectionNotify event is received
void TextEdit_OnClipboardReady(LCUI_Clipboard clipboard, void *arg)
{
LCUI_Widget w = arg;
LCUI_WidgetEventRec e = { 0 };
LCUI_InitWidgetEvent(&e, "paste");
Widget_TriggerEvent(w, &e, clipboard);
}
void TextEdit_OnKeyDown(LCUI_Widget w, LCUI_WidgetEvent e, void *arg)
{
LCUI_Clipboard clipboard;
LCUI_TextEdit textedit;
// ...
if (is pressed Ctrl+V) {
// Asynchronously preparing clipboard data
// In linux x11, it will call XConvertSelection()
LCUI_UseClipboard(textedit->clipboard, TextEdit_OnClipboardReady, w);
}
}
Note:
LCUI_PASTE
and LCUI_PASTE_READY
events@lc-soft
Wouldn't storing clipboard at widget, rather than system level cause problems? If we wan't to support CTRL+C feature, we'd need to support SelectionRequest
event (It would come if some other window asks for the the text we copied), meaning we need access to clipboard selected text from within linux_x11clipboard.c
.
I'd propose, we keep the clipboard
data as part of each system file linux_x11clipboard.c
, windows_clipboard.c
etc. Other than that, I think your suggestion is the right approach!
@WhoAteDaCake
Well, storing the clipboard in widgets would increase the cost and implementation complexity of the clipboard API, so I think we can choose to store the clipboard at the system level.
@lc-soft has rewarded $1.80 to @whoatedacake. See it on IssueHunt
Is your feature request related to a problem? Please describe.
Sometimes we need to paste some content into the input box, but LCUI does not support it.
Describe the solution you'd like
Add clipboard support to meet the following requirements:
Describe alternatives you've considered
None.
Additional context
You can refer to the source code of SDL:
Note: If you think you can do it, please request a bounty on issuehunt.io to tell everyone how much bounty you need. If you think this feature is necessary, you can also fund this issue on issuehunt.io.
IssueHunt Summary
#### [ whoatedacake](https://issuehunt.io/u/whoatedacake) has been rewarded. ### Backers (Total: $2.00) - [ lc-soft](https://issuehunt.io/u/lc-soft) ($2.00) ### Submitted pull Requests - [#271 feat(platform): add clipboard support](https://issuehunt.io/r/lc-soft/LCUI/pull/271) --- ### Tips - Checkout the [Issuehunt explorer](https://issuehunt.io/r/lc-soft/LCUI/) to discover more funded issues. - Need some help from other developers? [Add your repositories](https://issuehunt.io/r/new) on IssueHunt to raise funds.