better wayland clipboard, initial xdnd support
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
This commit is contained in:
parent
e5255bcbfa
commit
fdbdc83527
6 changed files with 321 additions and 57 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
#include <Mw/Milsko.h>
|
#include <Mw/Milsko.h>
|
||||||
|
|
||||||
MwWidget window, instructions, text1, cur_text;
|
MwWidget window, box, instructions, cur_text, text_listbox;
|
||||||
|
|
||||||
static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) {
|
static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) {
|
||||||
unsigned int w, h;
|
unsigned int w, h;
|
||||||
|
|
@ -11,17 +11,7 @@ static void MWAPI resize(MwWidget handle, void* user_data, void* call_data) {
|
||||||
w = MwGetInteger(handle, MwNwidth);
|
w = MwGetInteger(handle, MwNwidth);
|
||||||
h = MwGetInteger(handle, MwNheight);
|
h = MwGetInteger(handle, MwNheight);
|
||||||
|
|
||||||
MwVaApply(instructions,
|
MwVaApply(box, MwNwidth, w, MwNheight, h, NULL);
|
||||||
MwNy, 50,
|
|
||||||
MwNwidth, w - 50 * 2,
|
|
||||||
MwNheight, h - 125 - 50 * 3,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
MwVaApply(text1,
|
|
||||||
MwNy, 150,
|
|
||||||
MwNwidth, w - 25 * 2,
|
|
||||||
MwNheight, h - 125 - 50 * 3,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) {
|
static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) {
|
||||||
char* filename = call_data;
|
char* filename = call_data;
|
||||||
|
|
@ -30,29 +20,35 @@ static void MWAPI dnd(MwWidget handle, void* user_data, void* call_data) {
|
||||||
(void)user_data;
|
(void)user_data;
|
||||||
|
|
||||||
if(filename != NULL) {
|
if(filename != NULL) {
|
||||||
MwVaApply(cur_text, MwNtext, filename, NULL);
|
MwListBoxSet(text_listbox, -1, -1, filename);
|
||||||
MwForceRender(cur_text);
|
MwForceRender(text_listbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
MwLibraryInit();
|
MwSizeHints hints;
|
||||||
|
|
||||||
window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 400, 400,
|
MwLibraryInit();
|
||||||
MwNtitle, "dnd",
|
hints.min_width = hints.min_height = 600;
|
||||||
|
|
||||||
|
window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 600, 600,
|
||||||
|
MwNtitle, "dnd",
|
||||||
|
MwNsizeHints, &hints,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
box = MwVaCreateWidget(MwBoxClass, NULL, window, 0, 0, 800, 800, MwNorientation, MwVERTICAL, MwNpadding, 25, NULL);
|
||||||
|
|
||||||
|
instructions = MwVaCreateWidget(MwLabelClass, "button", box, 50, 50, 750, 50,
|
||||||
|
MwNtext, "drag files onto this text box, and their names will show up below.",
|
||||||
MwNacceptsDnD, 1,
|
MwNacceptsDnD, 1,
|
||||||
NULL);
|
NULL);
|
||||||
instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125,
|
text_listbox = MwVaCreateWidget(MwListBoxClass, "label", box, 25, 150, 750, 700,
|
||||||
MwNtext, "drag a file and its name will show up below.",
|
|
||||||
NULL);
|
|
||||||
text1 = MwVaCreateWidget(MwLabelClass, "label", window, 25, 150, 300, 75,
|
|
||||||
MwNtext, "",
|
MwNtext, "",
|
||||||
|
MwNacceptsDnD, 1,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
cur_text = text1;
|
|
||||||
|
|
||||||
MwAddUserHandler(window, MwNresizeHandler, resize, NULL);
|
MwAddUserHandler(window, MwNresizeHandler, resize, NULL);
|
||||||
MwAddUserHandler(window, MwNdragAndDropHandler, dnd, NULL);
|
MwAddUserHandler(instructions, MwNdragAndDropHandler, dnd, NULL);
|
||||||
|
|
||||||
resize(window, NULL, NULL);
|
resize(window, NULL, NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,8 @@ struct _MwLLWayland {
|
||||||
MwU64 next_elapsed;
|
MwU64 next_elapsed;
|
||||||
long start_time;
|
long start_time;
|
||||||
long end_time;
|
long end_time;
|
||||||
|
|
||||||
|
MwBool accepts_dnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MwLLWaylandColor {
|
struct _MwLLWaylandColor {
|
||||||
|
|
|
||||||
|
|
@ -27,20 +27,36 @@ struct _MwLLX11 {
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
|
||||||
Display* display;
|
Display* display;
|
||||||
Window window;
|
Window window;
|
||||||
Pixmap pixmap;
|
Pixmap pixmap;
|
||||||
GC gc;
|
GC gc;
|
||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
Atom wm_delete;
|
Atom wm_delete;
|
||||||
Atom wm_protocols;
|
Atom wm_protocols;
|
||||||
Atom utf8_string;
|
Atom utf8_string;
|
||||||
Atom compound_text;
|
Atom compound_text;
|
||||||
Atom text;
|
Atom text;
|
||||||
Atom clipboard;
|
Atom clipboard;
|
||||||
Atom selection;
|
Atom selection;
|
||||||
XIM xim;
|
Atom xdnd_type_list;
|
||||||
XIC xic;
|
Atom xdnd_selection;
|
||||||
|
Atom xdnd_enter;
|
||||||
|
Atom xdnd_position;
|
||||||
|
Atom xdnd_status;
|
||||||
|
Atom xdnd_leave;
|
||||||
|
Atom xdnd_drop;
|
||||||
|
Atom xdnd_finished;
|
||||||
|
Atom xdnd_action_copy;
|
||||||
|
Atom xdnd_text_uri_list;
|
||||||
|
Atom xdnd_text_plain;
|
||||||
|
Atom xdnd_aware;
|
||||||
|
int xdnd_source;
|
||||||
|
unsigned char xdnd_version;
|
||||||
|
int xdnd_format;
|
||||||
|
|
||||||
|
XIM xim;
|
||||||
|
XIC xic;
|
||||||
|
|
||||||
long clipboard_time;
|
long clipboard_time;
|
||||||
int clipboard_pending; /* 1 if UTF8_STRING, 2 if COMPOUND_TEXT, 3 if TEXT, 4 if STRING, otherwise 0 */
|
int clipboard_pending; /* 1 if UTF8_STRING, 2 if COMPOUND_TEXT, 3 if TEXT, 4 if STRING, otherwise 0 */
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat);
|
||||||
|
|
||||||
static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat);
|
static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat);
|
||||||
static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat);
|
static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat);
|
||||||
|
static bool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos);
|
||||||
|
|
||||||
/* Recursively dispatch a key event to a widget and its children */
|
/* Recursively dispatch a key event to a widget and its children */
|
||||||
static void recursive_dispatch_key(MwLL handle, int* k) {
|
static void recursive_dispatch_key(MwLL handle, int* k) {
|
||||||
|
|
@ -168,6 +169,57 @@ static void wl_data_device_leave(void* data,
|
||||||
self->offer.wl = NULL;
|
self->offer.wl = NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx) {
|
||||||
|
if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) {
|
||||||
|
return MwTRUE;
|
||||||
|
} else if(self->common.user) {
|
||||||
|
MwWidget w = self->common.user;
|
||||||
|
int i, n;
|
||||||
|
for(i = 0; i < arrlen(w->children); i++) {
|
||||||
|
if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
|
||||||
|
MwLL child = w->children[i]->lowlevel;
|
||||||
|
MwLL topmost_parent = child;
|
||||||
|
MwPoint point;
|
||||||
|
MwPoint relative_mouse_pos;
|
||||||
|
MwPoint absolute_pos;
|
||||||
|
|
||||||
|
if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos)) {
|
||||||
|
return MwTRUE;
|
||||||
|
} else {
|
||||||
|
return motion_cursor_change(child, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clipboard_dispatch(MwLL self, char* buf) {
|
||||||
|
if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) {
|
||||||
|
MwLLDispatch(self, drag_and_drop, buf);
|
||||||
|
} else if(self->common.user) {
|
||||||
|
MwWidget w = self->common.user;
|
||||||
|
int i, n;
|
||||||
|
for(i = 0; i < arrlen(w->children); i++) {
|
||||||
|
if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
|
||||||
|
MwLL child = w->children[i]->lowlevel;
|
||||||
|
MwLL topmost_parent = child;
|
||||||
|
MwPoint point;
|
||||||
|
MwPoint relative_mouse_pos;
|
||||||
|
MwPoint absolute_pos;
|
||||||
|
|
||||||
|
if(hit_detect(child, &topmost_parent, &point, &relative_mouse_pos, &absolute_pos) && child->wayland.accepts_dnd) {
|
||||||
|
MwLLDispatch(child, drag_and_drop, buf);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
clipboard_dispatch(child, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void wl_data_device_motion(void* data,
|
static void wl_data_device_motion(void* data,
|
||||||
struct wl_data_device* wl_data_device,
|
struct wl_data_device* wl_data_device,
|
||||||
uint32_t time,
|
uint32_t time,
|
||||||
|
|
@ -179,8 +231,15 @@ static void wl_data_device_motion(void* data,
|
||||||
(void)y;
|
(void)y;
|
||||||
wl_clipboard_device_context_t* self = data;
|
wl_clipboard_device_context_t* self = data;
|
||||||
|
|
||||||
|
self->ll->wayland.cur_mouse_pos.x = wl_fixed_to_int(x);
|
||||||
|
self->ll->wayland.cur_mouse_pos.y = wl_fixed_to_int(y);
|
||||||
|
|
||||||
if(self->selected_mime_type[0] != '\0' && self->offer.wl) {
|
if(self->selected_mime_type[0] != '\0' && self->offer.wl) {
|
||||||
wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
if(motion_cursor_change(self->ll, self)) {
|
||||||
|
wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
||||||
|
} else {
|
||||||
|
wl_data_offer_set_actions(self->offer.wl, WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE, WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static void wl_data_device_drop(void* data,
|
static void wl_data_device_drop(void* data,
|
||||||
|
|
@ -193,7 +252,6 @@ static void wl_data_device_drop(void* data,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if(pipe(fds) != 0) {
|
if(pipe(fds) != 0) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,10 +284,20 @@ static void wl_data_device_drop(void* data,
|
||||||
|
|
||||||
setup_clipboard(self->ll, self->ll->wayland.pointer_seat);
|
setup_clipboard(self->ll, self->ll->wayland.pointer_seat);
|
||||||
|
|
||||||
if(strstr(buf, "file://")) {
|
char* buf_ptr = buf;
|
||||||
MwLLDispatch(self->ll, drag_and_drop, buf + sizeof("file://") - 1);
|
while(buf_ptr) {
|
||||||
} else {
|
char* next = strstr(buf_ptr, "\n");
|
||||||
MwLLDispatch(self->ll, drag_and_drop, buf);
|
if(next) {
|
||||||
|
*next = '\0';
|
||||||
|
if(strstr(buf_ptr, "file://")) {
|
||||||
|
clipboard_dispatch(self->ll, buf_ptr + sizeof("file://") - 1);
|
||||||
|
} else {
|
||||||
|
clipboard_dispatch(self->ll, buf_ptr);
|
||||||
|
}
|
||||||
|
buf_ptr = next + 1;
|
||||||
|
} else {
|
||||||
|
buf_ptr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arrfree(buf);
|
arrfree(buf);
|
||||||
|
|
|
||||||
|
|
@ -1794,7 +1794,6 @@ static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
|
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
|
||||||
|
|
||||||
rect->x = 0;
|
rect->x = 0;
|
||||||
rect->y = 0;
|
rect->y = 0;
|
||||||
rect->width = handle->wayland.mw;
|
rect->width = handle->wayland.mw;
|
||||||
|
|
@ -1803,6 +1802,7 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
|
||||||
|
|
||||||
static void MwLLSetupDragAndDropImpl(MwLL handle) {
|
static void MwLLSetupDragAndDropImpl(MwLL handle) {
|
||||||
(void)handle;
|
(void)handle;
|
||||||
|
handle->wayland.accepts_dnd = MwTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLBeginStateChangeImpl(MwLL handle) {
|
static void MwLLBeginStateChangeImpl(MwLL handle) {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ static struct symtbl {
|
||||||
void (*XSetICFocus)(XIC);
|
void (*XSetICFocus)(XIC);
|
||||||
XImage* (*XGetImage)(Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int);
|
XImage* (*XGetImage)(Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int);
|
||||||
int (*XRaiseWindow)(Display*, Window);
|
int (*XRaiseWindow)(Display*, Window);
|
||||||
|
int (*XFlush)(Display*);
|
||||||
|
char* (*XGetAtomName)(Display*, Atom);
|
||||||
|
|
||||||
XSizeHints* (*XAllocSizeHints)(void);
|
XSizeHints* (*XAllocSizeHints)(void);
|
||||||
XVisualInfo* (*XGetVisualInfo)(Display*, long, XVisualInfo*, int*);
|
XVisualInfo* (*XGetVisualInfo)(Display*, long, XVisualInfo*, int*);
|
||||||
|
|
@ -186,6 +188,8 @@ static struct symtbl {
|
||||||
#define XChangeWindowAttributes xsymtbl.XChangeWindowAttributes
|
#define XChangeWindowAttributes xsymtbl.XChangeWindowAttributes
|
||||||
#define XGetImage xsymtbl.XGetImage
|
#define XGetImage xsymtbl.XGetImage
|
||||||
#define XRaiseWindow xsymtbl.XRaiseWindow
|
#define XRaiseWindow xsymtbl.XRaiseWindow
|
||||||
|
#define XFlush xsymtbl.XFlush
|
||||||
|
#define XGetAtomName xsymtbl.XGetAtomName
|
||||||
|
|
||||||
#if USE_XRENDER
|
#if USE_XRENDER
|
||||||
#define XRenderFindStandardFormat xsymtbl.XRenderFindStandardFormat
|
#define XRenderFindStandardFormat xsymtbl.XRenderFindStandardFormat
|
||||||
|
|
@ -425,6 +429,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
|
||||||
r->x11.colormap = DefaultColormap(r->x11.display, XDefaultScreen(r->x11.display));
|
r->x11.colormap = DefaultColormap(r->x11.display, XDefaultScreen(r->x11.display));
|
||||||
r->x11.wm_delete = XInternAtom(r->x11.display, "WM_DELETE_WINDOW", False);
|
r->x11.wm_delete = XInternAtom(r->x11.display, "WM_DELETE_WINDOW", False);
|
||||||
r->x11.wm_protocols = XInternAtom(r->x11.display, "WM_PROTOCOLS", False);
|
r->x11.wm_protocols = XInternAtom(r->x11.display, "WM_PROTOCOLS", False);
|
||||||
|
|
||||||
XSetWMProtocols(r->x11.display, r->x11.window, &r->x11.wm_delete, 1);
|
XSetWMProtocols(r->x11.display, r->x11.window, &r->x11.wm_delete, 1);
|
||||||
|
|
||||||
r->x11.utf8_string = XInternAtom(r->x11.display, "UTF8_STRING", False);
|
r->x11.utf8_string = XInternAtom(r->x11.display, "UTF8_STRING", False);
|
||||||
|
|
@ -433,6 +438,21 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
|
||||||
r->x11.clipboard = XInternAtom(r->x11.display, "CLIPBOARD", False);
|
r->x11.clipboard = XInternAtom(r->x11.display, "CLIPBOARD", False);
|
||||||
r->x11.selection = XInternAtom(r->x11.display, "_MILSKO_SELECTION_", False);
|
r->x11.selection = XInternAtom(r->x11.display, "_MILSKO_SELECTION_", False);
|
||||||
|
|
||||||
|
r->x11.xdnd_type_list = XInternAtom(r->x11.display, "XdndTypeList", False);
|
||||||
|
r->x11.xdnd_selection = XInternAtom(r->x11.display, "XdndSelection", False);
|
||||||
|
r->x11.xdnd_enter = XInternAtom(r->x11.display, "XdndEnter", False);
|
||||||
|
r->x11.xdnd_position = XInternAtom(r->x11.display, "XdndPosition", False);
|
||||||
|
r->x11.xdnd_status = XInternAtom(r->x11.display, "XdndStatus", False);
|
||||||
|
r->x11.xdnd_leave = XInternAtom(r->x11.display, "XdndLeave", False);
|
||||||
|
r->x11.xdnd_drop = XInternAtom(r->x11.display, "XdndDrop", False);
|
||||||
|
r->x11.xdnd_finished = XInternAtom(r->x11.display, "XdndFinished", False);
|
||||||
|
r->x11.xdnd_action_copy = XInternAtom(r->x11.display, "XdndActionCopy", False);
|
||||||
|
r->x11.xdnd_text_uri_list = XInternAtom(r->x11.display, "text/uri-list", False);
|
||||||
|
r->x11.xdnd_text_plain = XInternAtom(r->x11.display, "text/plain", False);
|
||||||
|
r->x11.xdnd_aware = XInternAtom(r->x11.display, "XdndAware", False);
|
||||||
|
r->x11.xdnd_version = 5;
|
||||||
|
r->x11.xdnd_format = None;
|
||||||
|
|
||||||
r->x11.clipboard_pending = 0;
|
r->x11.clipboard_pending = 0;
|
||||||
|
|
||||||
r->x11.gc = XCreateGC(r->x11.display, r->x11.window, 0, NULL);
|
r->x11.gc = XCreateGC(r->x11.display, r->x11.window, 0, NULL);
|
||||||
|
|
@ -704,10 +724,15 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
|
|
||||||
while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, SelectionNotify, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
|
while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, SelectionNotify, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
|
||||||
int render = 0;
|
int render = 0;
|
||||||
if(ev.type == Expose) {
|
switch(ev.type) {
|
||||||
|
case Expose:
|
||||||
|
{
|
||||||
handle->x11.force_render = 0;
|
handle->x11.force_render = 0;
|
||||||
render = 1;
|
render = 1;
|
||||||
} else if(ev.type == ButtonPress) {
|
break;
|
||||||
|
};
|
||||||
|
case ButtonPress:
|
||||||
|
{
|
||||||
MwMouse p;
|
MwMouse p;
|
||||||
p.point.x = ev.xbutton.x;
|
p.point.x = ev.xbutton.x;
|
||||||
p.point.y = ev.xbutton.y;
|
p.point.y = ev.xbutton.y;
|
||||||
|
|
@ -728,7 +753,10 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MwLLDispatch(handle, down, &p);
|
MwLLDispatch(handle, down, &p);
|
||||||
} else if(ev.type == ButtonRelease) {
|
break;
|
||||||
|
};
|
||||||
|
case ButtonRelease:
|
||||||
|
{
|
||||||
MwMouse p;
|
MwMouse p;
|
||||||
p.point.x = ev.xbutton.x;
|
p.point.x = ev.xbutton.x;
|
||||||
p.point.y = ev.xbutton.y;
|
p.point.y = ev.xbutton.y;
|
||||||
|
|
@ -745,24 +773,122 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MwLLDispatch(handle, up, &p);
|
MwLLDispatch(handle, up, &p);
|
||||||
} else if(ev.type == ConfigureNotify) {
|
break;
|
||||||
|
};
|
||||||
|
case ConfigureNotify:
|
||||||
|
{
|
||||||
if(handle->x11.width != (unsigned int)ev.xconfigure.width || handle->x11.height != (unsigned int)ev.xconfigure.height) {
|
if(handle->x11.width != (unsigned int)ev.xconfigure.width || handle->x11.height != (unsigned int)ev.xconfigure.height) {
|
||||||
MwLLDispatch(handle, resize, NULL);
|
MwLLDispatch(handle, resize, NULL);
|
||||||
destroy_pixmap(handle);
|
destroy_pixmap(handle);
|
||||||
create_pixmap(handle);
|
create_pixmap(handle);
|
||||||
render = 1;
|
render = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
handle->x11.width = ev.xconfigure.width;
|
handle->x11.width = ev.xconfigure.width;
|
||||||
handle->x11.height = ev.xconfigure.height;
|
handle->x11.height = ev.xconfigure.height;
|
||||||
} else if(ev.type == ClientMessage) {
|
};
|
||||||
|
case ClientMessage:
|
||||||
|
{
|
||||||
|
|
||||||
if(ev.xclient.message_type == handle->x11.wm_protocols && ev.xclient.data.l[0] == (long)handle->x11.wm_delete) {
|
if(ev.xclient.message_type == handle->x11.wm_protocols && ev.xclient.data.l[0] == (long)handle->x11.wm_delete) {
|
||||||
MwLLDispatch(handle, close, NULL);
|
MwLLDispatch(handle, close, NULL);
|
||||||
}
|
}
|
||||||
} else if(ev.type == FocusIn) {
|
|
||||||
|
if(
|
||||||
|
ev.xclient.message_type == handle->x11.xdnd_enter ||
|
||||||
|
ev.xclient.message_type == handle->x11.xdnd_position ||
|
||||||
|
ev.xclient.message_type == handle->x11.xdnd_drop) {
|
||||||
|
char* name = XGetAtomName(handle->x11.display, ev.xclient.message_type);
|
||||||
|
|
||||||
|
if(ev.xclient.message_type == handle->x11.xdnd_enter) {
|
||||||
|
Bool list = ev.xclient.data.l[1] & 1;
|
||||||
|
int version = ev.xclient.data.l[1] >> 24;
|
||||||
|
unsigned long count = 0;
|
||||||
|
unsigned char* formats = NULL;
|
||||||
|
unsigned long i;
|
||||||
|
handle->x11.xdnd_source = ev.xclient.data.l[0];
|
||||||
|
if(list) {
|
||||||
|
Atom actualType;
|
||||||
|
int32_t actualFormat;
|
||||||
|
unsigned long bytesAfter;
|
||||||
|
|
||||||
|
XGetWindowProperty((Display*)handle->x11.display,
|
||||||
|
handle->x11.xdnd_source,
|
||||||
|
handle->x11.xdnd_type_list,
|
||||||
|
0,
|
||||||
|
LONG_MAX,
|
||||||
|
False,
|
||||||
|
4,
|
||||||
|
&actualType,
|
||||||
|
&actualFormat,
|
||||||
|
&count,
|
||||||
|
&bytesAfter,
|
||||||
|
(unsigned char**)&formats);
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
if(ev.xclient.data.l[2] != None)
|
||||||
|
formats[count++] = ev.xclient.data.l[2];
|
||||||
|
if(ev.xclient.data.l[3] != None)
|
||||||
|
formats[count++] = ev.xclient.data.l[3];
|
||||||
|
if(ev.xclient.data.l[4] != None)
|
||||||
|
formats[count++] = ev.xclient.data.l[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < count; i++) {
|
||||||
|
if(formats[i] == handle->x11.xdnd_text_uri_list || formats[i] == handle->x11.xdnd_text_plain) {
|
||||||
|
handle->x11.xdnd_format = formats[i];
|
||||||
|
printf("format %d\n", handle->x11.xdnd_format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(list) {
|
||||||
|
XFree(formats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ev.xclient.message_type == handle->x11.xdnd_position && handle->x11.xdnd_version >= 5) {
|
||||||
|
XEvent reply;
|
||||||
|
reply.xclient.message_type = handle->x11.xdnd_status;
|
||||||
|
|
||||||
|
if(handle->x11.xdnd_format) {
|
||||||
|
reply.xclient.data.l[1] = 1;
|
||||||
|
if(handle->x11.xdnd_version >= 2) reply.xclient.data.l[4] = handle->x11.xdnd_action_copy;
|
||||||
|
}
|
||||||
|
XSendEvent(handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply);
|
||||||
|
XFlush(handle->x11.display);
|
||||||
|
}
|
||||||
|
if(ev.xclient.message_type == handle->x11.xdnd_drop && handle->x11.xdnd_version >= 5) {
|
||||||
|
Time time = CurrentTime;
|
||||||
|
if(handle->x11.xdnd_version >= 1)
|
||||||
|
time = ev.xclient.data.l[2];
|
||||||
|
|
||||||
|
if(handle->x11.xdnd_format) {
|
||||||
|
XConvertSelection((Display*)handle->x11.display,
|
||||||
|
handle->x11.xdnd_selection,
|
||||||
|
handle->x11.xdnd_format,
|
||||||
|
handle->x11.xdnd_selection,
|
||||||
|
(Window)handle->x11.window,
|
||||||
|
time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case FocusIn:
|
||||||
|
{
|
||||||
MwLLDispatch(handle, focus_in, NULL);
|
MwLLDispatch(handle, focus_in, NULL);
|
||||||
} else if(ev.type == FocusOut) {
|
break;
|
||||||
|
};
|
||||||
|
case FocusOut:
|
||||||
|
{
|
||||||
MwLLDispatch(handle, focus_out, NULL);
|
MwLLDispatch(handle, focus_out, NULL);
|
||||||
} else if(ev.type == MotionNotify) {
|
break;
|
||||||
|
};
|
||||||
|
case MotionNotify:
|
||||||
|
{
|
||||||
MwPoint p;
|
MwPoint p;
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
|
|
||||||
|
|
@ -780,7 +906,11 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
if(handle->x11.grabbed && (p.x != 0 || p.y != 0)) {
|
if(handle->x11.grabbed && (p.x != 0 || p.y != 0)) {
|
||||||
XWarpPointer(handle->x11.display, None, handle->x11.window, 0, 0, 0, 0, attr.width / 2, attr.height / 2);
|
XWarpPointer(handle->x11.display, None, handle->x11.window, 0, 0, 0, 0, attr.width / 2, attr.height / 2);
|
||||||
}
|
}
|
||||||
} else if(ev.type == KeyPress || ev.type == KeyRelease) {
|
break;
|
||||||
|
};
|
||||||
|
case KeyPress:
|
||||||
|
case KeyRelease:
|
||||||
|
{
|
||||||
int n = -1;
|
int n = -1;
|
||||||
char str[512];
|
char str[512];
|
||||||
KeySym sym;
|
KeySym sym;
|
||||||
|
|
@ -844,10 +974,60 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
MwLLDispatch(handle, key_released, &n);
|
MwLLDispatch(handle, key_released, &n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(ev.type == SelectionNotify) {
|
break;
|
||||||
|
};
|
||||||
|
case SelectionNotify:
|
||||||
|
{
|
||||||
handle->x11.clipboard_pending = 0;
|
handle->x11.clipboard_pending = 0;
|
||||||
|
|
||||||
if(ev.xselection.property != None) {
|
if(ev.xselection.property == handle->x11.xdnd_selection) {
|
||||||
|
XEvent reply;
|
||||||
|
char* data;
|
||||||
|
unsigned long result;
|
||||||
|
Atom actualType;
|
||||||
|
int32_t actualFormat;
|
||||||
|
unsigned long bytesAfter;
|
||||||
|
|
||||||
|
XGetWindowProperty(handle->x11.display,
|
||||||
|
ev.xselection.requestor, ev.xselection.property,
|
||||||
|
0, LONG_MAX, False, ev.xselection.target,
|
||||||
|
&actualType, &actualFormat, &result, &bytesAfter,
|
||||||
|
(unsigned char**)&data);
|
||||||
|
|
||||||
|
if(result == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* !! untested lmao !! */
|
||||||
|
printf("File(s) dropped: %s\n", data);
|
||||||
|
char* data_ptr = data;
|
||||||
|
while(data_ptr) {
|
||||||
|
char* next = strstr(data, "\n");
|
||||||
|
if(next) *next = '\0';
|
||||||
|
|
||||||
|
printf("%s\n", data_ptr);
|
||||||
|
|
||||||
|
if(strstr(data_ptr, "file://")) {
|
||||||
|
MwLLDispatch(handle, drag_and_drop, data_ptr + sizeof("file://") - 1);
|
||||||
|
} else {
|
||||||
|
MwLLDispatch(handle, drag_and_drop, data_ptr);
|
||||||
|
}
|
||||||
|
if(next) data_ptr = next + 1;
|
||||||
|
else
|
||||||
|
data_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data)
|
||||||
|
XFree(data);
|
||||||
|
|
||||||
|
if(handle->x11.xdnd_version >= 2) {
|
||||||
|
reply.xclient.message_type = handle->x11.xdnd_finished;
|
||||||
|
reply.xclient.data.l[1] = result;
|
||||||
|
reply.xclient.data.l[2] = handle->x11.xdnd_action_copy;
|
||||||
|
|
||||||
|
XSendEvent((Display*)handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply);
|
||||||
|
XFlush((Display*)handle->x11.display);
|
||||||
|
}
|
||||||
|
} else if(ev.xselection.property != None) {
|
||||||
Atom type;
|
Atom type;
|
||||||
int format;
|
int format;
|
||||||
unsigned long nitems, after, size;
|
unsigned long nitems, after, size;
|
||||||
|
|
@ -884,9 +1064,9 @@ static void MwLLNextEventImpl(MwLL handle) {
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection);
|
XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection);
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
if(render) {
|
if(render) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
@ -1365,7 +1545,7 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLSetupDragAndDropImpl(MwLL handle) {
|
static void MwLLSetupDragAndDropImpl(MwLL handle) {
|
||||||
(void)handle;
|
XChangeProperty(handle->x11.display, handle->x11.window, handle->x11.xdnd_aware, 4, 32, PropModeReplace, &handle->x11.xdnd_version, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLBeginStateChangeImpl(MwLL handle) {
|
static void MwLLBeginStateChangeImpl(MwLL handle) {
|
||||||
|
|
@ -1512,6 +1692,8 @@ static int MwLLX11CallInitImpl(void) {
|
||||||
X11_FUNC_LOAD(XSetICFocus);
|
X11_FUNC_LOAD(XSetICFocus);
|
||||||
X11_FUNC_LOAD(XGetImage);
|
X11_FUNC_LOAD(XGetImage);
|
||||||
X11_FUNC_LOAD(XRaiseWindow);
|
X11_FUNC_LOAD(XRaiseWindow);
|
||||||
|
X11_FUNC_LOAD(XFlush);
|
||||||
|
X11_FUNC_LOAD(XGetAtomName);
|
||||||
|
|
||||||
X11_FUNC_LOAD(XAllocSizeHints);
|
X11_FUNC_LOAD(XAllocSizeHints);
|
||||||
X11_FUNC_LOAD(XGetVisualInfo);
|
X11_FUNC_LOAD(XGetVisualInfo);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue