diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 9efae7a..2fe3265 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -29,6 +29,9 @@ void handler(MwWidget handle, void* user_data, void* call_data) { (void)handle; (void)user_data; (void)call_data; + + /* nishi: please rewrite this part */ + /* char* clipboard; clipboard = MwLLGetClipboard(handle->lowlevel); @@ -37,6 +40,7 @@ void handler(MwWidget handle, void* user_data, void* call_data) { MwVaApply(text, MwNtext, clipboard); MwForceRender(text); } + */ resize(window, NULL, NULL); } diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 0b0357d..24418ec 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -147,6 +147,7 @@ struct _MwLLHandler { void (*key_released)(MwLL handle, void* data); void (*focus_in)(MwLL handle, void* data); void (*focus_out)(MwLL handle, void* data); + void (*clipboard_received)(MwLL handle, void* data); }; #ifdef __cplusplus @@ -203,7 +204,7 @@ MWDECL void (*MwLLFocus)(MwLL handle); MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle); MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text); -MWDECL char* (*MwLLGetClipboard)(MwLL handle); +MWDECL void (*MwLLGetClipboard)(MwLL handle); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index 9fee9ac..1bf997c 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -21,6 +21,7 @@ struct _MwLLGDI { int grabbed; int force_render; + int get_clipboard; }; struct _MwLLGDIColor { diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 3275096..de97cd9 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -39,6 +39,7 @@ typedef void (*MwHandlerChildrenProp)(MwWidget handle, MwWidget child, const cha typedef void (*MwHandlerKey)(MwWidget handle, int key); typedef void (*MwHandlerMouse)(MwWidget handle, void* ptr); typedef void (*MwHandlerExecute)(MwWidget handle, const char* name, void* out, va_list args); +typedef void (*MwHandlerClipboardReceived)(MwWidget handle, const char* data); typedef void (*MwUserHandler)(MwWidget handle, void* user_data, void* call_data); typedef void (*MwErrorHandler)(int code, const char* message, void* user_data); @@ -211,11 +212,11 @@ struct _MwClass { MwHandler resize; MwHandler children_update; MwHandlerChildrenProp children_prop_change; + MwHandlerClipboardReceived clipboard_received; void* reserved1; void* reserved2; void* reserved3; void* reserved4; - void* reserved5; }; #endif diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 85f8fcb..f027fe0 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -237,6 +237,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.copy_buffer = 1; r->common.type = MwLLBackendGDI; + r->gdi.get_clipboard = 1; r->gdi.force_render = 0; r->gdi.grabbed = 0; r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL); @@ -383,6 +384,7 @@ static int MwLLPendingImpl(MwLL handle) { (void)handle; + if(handle->gdi.get_clipboard) return 1; return PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE) ? 1 : 0; } @@ -391,6 +393,24 @@ static void MwLLNextEventImpl(MwLL handle) { (void)handle; + if(handle->gdi.get_clipboard){ + HGLOBAL hg; + if(OpenClipboard(handle->gdi.hWnd) != 0 && (hg = GetClipboardData(CF_TEXT)) != NULL){ + char* txt = malloc(GlobalSize(hg)); + char* clp = GlobalLock(hg); + + strcpy(txt, clp); + + GlobalUnlock(hg); + CloseClipboard(); + + MwLLDispatch(handle, clipboard_received, txt); + + free(txt); + } + + handle->gdi.get_clipboard = 0; + } while(PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE)) { GetMessage(&msg, handle->gdi.hWnd, 0, 0); TranslateMessage(&msg); @@ -697,21 +717,8 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) { } } -static char* MwLLGetClipboardImpl(MwLL handle) { - HGLOBAL hg; - char* r = NULL; - if(OpenClipboard(handle->gdi.hWnd) != 0 && (hg = GetClipboardData(CF_TEXT)) != NULL) { - char* lock; - - r = malloc(GlobalSize(hg)); - - lock = GlobalLock(hg); - strcpy(r, lock); - GlobalUnlock(hg); - - CloseClipboard(); - } - return r; +static void MwLLGetClipboardImpl(MwLL handle) { + handle->gdi.get_clipboard = 1; /* nishi: we do this to make clipboard api work similar to other backends */ } static void MwLLMakeToolWindowImpl(MwLL handle) { diff --git a/src/backend/x11.c b/src/backend/x11.c index 0353a24..8ece5d8 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -957,45 +957,10 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) { (void)text; } -static char* MwLLGetClipboardImpl(MwLL handle) { - Atom clip, target, prop; - XEvent ev; - XEvent* queue = NULL; - char* r = NULL; +static void MwLLGetClipboardImpl(MwLL handle) { + /* TODO */ - clip = XInternAtom(handle->x11.display, "CLIPBOARD", 0); - target = XA_STRING; - prop = XInternAtom(handle->x11.display, "XSEL_DATA", 0); - - XConvertSelection(handle->x11.display, clip, target, prop, handle->x11.window, CurrentTime); - - while(1) { - XNextEvent(handle->x11.display, &ev); - if(ev.type == SelectionNotify) { - if(ev.xselection.selection == clip && ev.xselection.property != 0) { - Atom t; - unsigned long size, N; - char* data; - int format; - - XGetWindowProperty(ev.xselection.display, ev.xselection.requestor, ev.xselection.property, 0, (~0L), 0, AnyPropertyType, &t, &format, &size, &N, (unsigned char**)&data); - if(t == target) { - r = MwStringDuplicate(data); - XFree(data); - } - XDeleteProperty(ev.xselection.display, ev.xselection.requestor, ev.xselection.property); - } - break; - } - } - - while(arrlen(queue) > 0) { - XPutBackEvent(handle->x11.display, &queue[0]); - arrdel(queue, 0); - } - arrfree(queue); - - return r; + (void)handle; } static void MwLLMakeToolWindowImpl(MwLL handle) { diff --git a/src/core.c b/src/core.c index 6566990..f44a9f8 100644 --- a/src/core.c +++ b/src/core.c @@ -107,6 +107,12 @@ static void llfocusouthandler(MwLL handle, void* data) { MwDispatchUserHandler(h, MwNfocusOutHandler, data); } +static void llclipboardreceivedhandler(MwLL handle, void* data){ + MwWidget h = (MwWidget)handle->common.user; + + MwDispatch3(h, clipboard_received, data); +} + MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) { MwWidget h = malloc(sizeof(*h)); @@ -148,6 +154,7 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->lowlevel->common.handler->key_released = llkeyrelhandler; h->lowlevel->common.handler->focus_in = llfocusinhandler; h->lowlevel->common.handler->focus_out = llfocusouthandler; + h->lowlevel->common.handler->clipboard_received = llclipboardreceivedhandler; } if(parent != NULL) arrput(parent->children, h); diff --git a/src/lowlevel.c b/src/lowlevel.c index 96f6196..30037c8 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -46,7 +46,7 @@ void (*MwLLFocus)(MwLL handle); void (*MwLLGrabPointer)(MwLL handle, int toggle); void (*MwLLSetClipboard)(MwLL handle, const char* text); -char* (*MwLLGetClipboard)(MwLL handle); +void (*MwLLGetClipboard)(MwLL handle); void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); diff --git a/src/widget/box.c b/src/widget/box.c index 3bf7528..c38a377 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -114,7 +114,7 @@ MwClassRec MwBoxClassRec = { resize, /* resize */ children_update, /* children_update */ children_prop_change, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/button.c b/src/widget/button.c index 885ff9d..296a14d 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -107,7 +107,7 @@ MwClassRec MwButtonClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 8a42b89..390b656 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -53,7 +53,7 @@ MwClassRec MwCheckBoxClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 156242e..0cdd629 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -204,7 +204,7 @@ MwClassRec MwComboBoxClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/entry.c b/src/widget/entry.c index 85f9a86..790586a 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -109,20 +109,7 @@ static void key(MwWidget handle, int code) { } else if(code == MwLLKeyEnter) { MwDispatchUserHandler(handle, MwNactivateHandler, NULL); } else if(code == (MwLLControlMask | 'v')) { - char* c = MwLLGetClipboard(handle->lowlevel); - if(c != NULL) { - char* out = malloc(strlen(str) + strlen(c) + 1); - - MwUTF8Copy(str, 0, out, 0, t->cursor); - MwUTF8Copy(c, 0, out, t->cursor, MwUTF8Length(c)); - MwUTF8Copy(str, t->cursor, out, t->cursor + MwUTF8Length(c), MwUTF8Length(str) - t->cursor); - - t->cursor += MwUTF8Length(c); - - MwSetText(handle, MwNtext, out); - free(out); - free(c); - } + MwLLGetClipboard(handle->lowlevel); } else if(!(code & MwLLKeyMask)) { int incr = 0; out = malloc(strlen(str) + 5 + 1); @@ -157,6 +144,23 @@ static void prop_change(MwWidget handle, const char* prop) { } } +static void clipboard_received(MwWidget handle, const char* data){ + MwEntry t = handle->internal; + const char* str = MwGetText(handle, MwNtext); + char* out = malloc(strlen(str) + strlen(data) + 1); + + if(str == NULL) str = ""; + + MwUTF8Copy(str, 0, out, 0, t->cursor); + MwUTF8Copy(data, 0, out, t->cursor, MwUTF8Length(data)); + MwUTF8Copy(str, t->cursor, out, t->cursor + MwUTF8Length(data), MwUTF8Length(str) - t->cursor); + + t->cursor += MwUTF8Length(data); + + MwSetText(handle, MwNtext, out); + free(out); +} + MwClassRec MwEntryClassRec = { create, /* create */ destroy, /* destroy */ @@ -173,7 +177,7 @@ MwClassRec MwEntryClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + clipboard_received, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/frame.c b/src/widget/frame.c index d48c287..869f604 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -61,7 +61,7 @@ MwClassRec MwFrameClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/image.c b/src/widget/image.c index 4995568..a9c0c26 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -57,7 +57,7 @@ MwClassRec MwImageClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/label.c b/src/widget/label.c index 792d009..570dc10 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -375,7 +375,7 @@ MwClassRec MwLabelClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 785468d..5c741ff 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -608,7 +608,7 @@ MwClassRec MwListBoxClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/menu.c b/src/widget/menu.c index 327d6f5..6dba8a1 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -204,7 +204,7 @@ MwClassRec MwMenuClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index ccbdf14..cb8d6a2 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -143,7 +143,7 @@ MwClassRec MwNumberEntryClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 19a7c4d..20b51f2 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -244,7 +244,7 @@ MwClassRec MwOpenGLClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index bd036dd..7ab3274 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -61,7 +61,7 @@ MwClassRec MwProgressBarClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index a6f78f9..063c09d 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -62,7 +62,7 @@ MwClassRec MwRadioBoxClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index ff42d3a..eaa87ae 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -272,7 +272,7 @@ MwClassRec MwScrollBarClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/separator.c b/src/widget/separator.c index 5800ba3..424305e 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -50,7 +50,7 @@ MwClassRec MwSeparatorClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 6b97934..3b5553e 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -253,7 +253,7 @@ MwClassRec MwSubMenuClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 27607ce..7dad52b 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -496,7 +496,7 @@ MwClassRec MwTreeViewClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 9bdf860..5b66b6e 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -191,7 +191,7 @@ MwClassRec MwViewportClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index bda24bf..15039f7 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -524,7 +524,7 @@ MwClassRec MwVulkanClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL, diff --git a/src/widget/window.c b/src/widget/window.c index 98a128f..84c7140 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -59,7 +59,7 @@ MwClassRec MwWindowClassRec = { NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ - NULL, + NULL, /* clipboard_received */ NULL, NULL, NULL,