summaryrefslogtreecommitdiff
path: root/reduced_system_layer.c
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-01-16 14:36:33 +0100
committerMitya Selivanov <automainint@guattari.tech>2025-01-16 14:36:33 +0100
commit906c7a102aebcf5e985c20dbca7af155718304dd (patch)
tree9ca07449125f544f56813c184e8e4e11f1ded784 /reduced_system_layer.c
parentc7e2625ed73d07ba9fd0ace798311bf0eed8111a (diff)
downloadreduced_system_layer-906c7a102aebcf5e985c20dbca7af155718304dd.zip
Drag and drop cleanup
Diffstat (limited to 'reduced_system_layer.c')
-rw-r--r--reduced_system_layer.c316
1 files changed, 120 insertions, 196 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index b128f1b..634b13e 100644
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -53,6 +53,7 @@
// - Networking
// - Windows sockets
// - TCP
+// - Switching canvases - Web
// - Long term
// - Allocator
// - Parsing
@@ -519,6 +520,7 @@ typedef struct {
b8 done;
b8 has_focus;
b8 has_cursor;
+ b8 files_dragged;
b8 files_dropped;
i32 real_width;
i32 real_height;
@@ -740,6 +742,7 @@ static i64 sound_samples_elapsed_(void) {
}
static void drop_files_clean_(void) {
+ g_platform.files_dragged = 0;
g_platform.files_dropped = 0;
g_platform.num_drop_files = 0;
g_platform.drop_files = NULL;
@@ -1347,38 +1350,30 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
#define FILE_PATH_PREFIX_ "file://"
#define FILE_PATH_PREFIX_LEN_ ((sizeof FILE_PATH_PREFIX_) - 1)
-static i64 _frame_time = 0;
-static XImage _image = {0};
-static Display *_display = NULL;
-static GC _gc = NULL;
-static XIM _im = NULL;
-static XIC _ic = NULL;
-static Window _window = 0;
-static Window _drop_source = 0;
-static Atom _wm_delete_window = 0;
-static Atom _clipboard = 0;
-static Atom _targets = 0;
-static Atom _utf8_string = 0;
-static Atom _target = 0;
-static Atom _dnd_type_list = 0;
-static Atom _dnd_selection = 0;
-static Atom _dnd_enter = 0;
-static Atom _dnd_position = 0;
-static Atom _dnd_status = 0;
-static Atom _dnd_leave = 0;
-static Atom _dnd_drop = 0;
-static Atom _dnd_finished = 0;
-static Atom _dnd_action_copy = 0;
-static Atom _dnd_action_move = 0;
-static Atom _dnd_action_link = 0;
-static Atom _dnd_action_ask = 0;
-static Atom _dnd_action_private = 0;
-static Atom _text_uri_list = 0;
-static Atom _text_plain = 0;
-static Atom _dnd_aware = 0;
-static Window _dnd_source = 0;
-static Atom _dnd_format = 0;
-static u32 _dnd_version = 0;
+static i64 _frame_time = 0;
+static XImage _image = {0};
+static Display *_display = NULL;
+static GC _gc = NULL;
+static XIM _im = NULL;
+static XIC _ic = NULL;
+static Window _window = 0;
+static Window _drop_source = 0;
+static Atom _wm_delete_window = 0;
+static Atom _clipboard = 0;
+static Atom _targets = 0;
+static Atom _utf8_string = 0;
+static Atom _target = 0;
+static Atom _dnd_aware = 0;
+static Atom _dnd_enter = 0;
+static Atom _dnd_position = 0;
+static Atom _dnd_status = 0;
+static Atom _dnd_leave = 0;
+static Atom _dnd_drop = 0;
+static Atom _dnd_finished = 0;
+static Atom _dnd_action_copy = 0;
+static Atom _dnd_selection = 0;
+static Atom _text_uri_list = 0;
+static Window _dnd_source = 0;
static i16 _key_table [MAX_NUM_KEYS] = {0};
static b8 _key_repeat [MAX_NUM_KEYS] = {0};
@@ -1587,24 +1582,16 @@ void p_init(void) {
if (g_platform.title != NULL)
XStoreName(_display, _window, g_platform.title);
- _dnd_type_list = XInternAtom(_display, "XdndTypeList", False);
- _dnd_selection = XInternAtom(_display, "XdndSelection", False);
- _dnd_enter = XInternAtom(_display, "XdndEnter", False);
- _dnd_position = XInternAtom(_display, "XdndPosition", False);
- _dnd_status = XInternAtom(_display, "XdndStatus", False);
- _dnd_leave = XInternAtom(_display, "XdndLeave", False);
- _dnd_drop = XInternAtom(_display, "XdndDrop", False);
- _dnd_finished = XInternAtom(_display, "XdndFinished", False);
- _dnd_action_copy = XInternAtom(_display, "XdndActionCopy", False);
- _dnd_action_move = XInternAtom(_display, "XdndActionMove", False);
- _dnd_action_link = XInternAtom(_display, "XdndActionLink", False);
- _dnd_action_ask = XInternAtom(_display, "XdndActionAsk", False);
- _dnd_action_private = XInternAtom(_display, "XdndActionPrivate", False);
- _text_uri_list = XInternAtom(_display, "text/uri-list", False);
- _text_plain = XInternAtom(_display, "text/plain", False);
- _dnd_aware = XInternAtom(_display, "XdndAware", False);
-
- _dnd_format = None;
+ _dnd_aware = XInternAtom(_display, "XdndAware", False);
+ _dnd_enter = XInternAtom(_display, "XdndEnter", False);
+ _dnd_position = XInternAtom(_display, "XdndPosition", False);
+ _dnd_status = XInternAtom(_display, "XdndStatus", False);
+ _dnd_leave = XInternAtom(_display, "XdndLeave", False);
+ _dnd_drop = XInternAtom(_display, "XdndDrop", False);
+ _dnd_finished = XInternAtom(_display, "XdndFinished", False);
+ _dnd_action_copy = XInternAtom(_display, "XdndActionCopy", False);
+ _dnd_selection = XInternAtom(_display, "XdndSelection", False);
+ _text_uri_list = XInternAtom(_display, "text/uri-list", False);
XChangeProperty(_display, _window, _dnd_aware, 4, 32, PropModeReplace, &(u8) {5}, 1);
@@ -1846,8 +1833,10 @@ i32 p_handle_events(void) {
&data
);
- if (len == 0)
+ if (len == 0) {
+ LOG_ERROR("Unable to retrieve drag and drop info.");
break;
+ }
if (data) {
i64 num = 0;
@@ -1880,61 +1869,6 @@ i32 p_handle_events(void) {
XFree(data);
}
-
- g_platform.files_dropped = 1;
-
- if (g_platform.drop_files == NULL)
- LOG_ERROR("No drop files.");
- else
- for (i64 i = 0; i < g_platform.num_drop_files; ++i) {
- FILE *f = fopen(g_platform.drop_files[i].name, "rb");
-
- if (f != NULL) {
- i64 size = 0;
- struct stat info;
- if (fstat(fileno(f), &info) == 0 && S_ISREG(info.st_mode))
- size = (i64) info.st_size;
- else
- LOG_ERROR("Unable to get the file info: %s", g_platform.drop_files[i].name);
-
- drop_files_set_data_(i, size);
-
- i64 num = (i64) fread(g_platform.drop_files[i].data, 1, g_platform.drop_files[i].data_size + 1, f);
- fclose(f);
-
- if (num != g_platform.drop_files[i].data_size) {
- LOG_ERROR("Unable to read: %s", g_platform.drop_files[i].name);
- drop_files_set_data_(i, 0);
- }
- } else
- LOG_ERROR("Unable to open: %s", g_platform.drop_files[i].name);
- }
-
- if (_dnd_version >= 2) {
- XSendEvent(
- _display,
- _dnd_source,
- False,
- NoEventMask,
- &(XEvent) {
- .xclient = {
- .type = ClientMessage,
- .message_type = _dnd_finished,
- .window = _drop_source,
- .format = 32,
- .data = {
- .l = {
- _window,
- len,
- _dnd_action_copy,
- },
- },
- },
- }
- );
-
- XFlush(_display);
- }
} else if (ev.xselection.property != None) {
i64 len = 0;
u8 *data = NULL;
@@ -1955,10 +1889,11 @@ i32 p_handle_events(void) {
);
if (ev.xselection.target == _targets) {
- _target = None;
Atom *list = (Atom *) data;
+ _target = None;
+ len /= 4;
- for (i64 i = 0; i < len / 4; i++)
+ for (i64 i = 0; i < len; i++)
if (list[i] == XA_STRING)
_target = XA_STRING;
else if (list[i] == _utf8_string) {
@@ -2002,63 +1937,9 @@ i32 p_handle_events(void) {
if ((Atom) ev.xclient.data.l[0] == _wm_delete_window)
g_platform.done = 1;
else {
- if (ev.xclient.message_type == _dnd_enter) {
- i64 count;
- Atom *formats;
- Atom real_formats[6];
-
- u32 list = ev.xclient.data.l[1] & 1;
-
- _dnd_source = ev.xclient.data.l[0];
- _dnd_format = None;
- _dnd_version = ev.xclient.data.l[1] >> 24;
-
- if (_dnd_version > 5) {
- LOG_ERROR("X client message version not supported: %d.", _dnd_version);
- break;
- }
-
- if (list)
- XGetWindowProperty(
- _display,
- _dnd_source,
- _dnd_type_list,
- 0,
- DROP_FILES_BUFFER_SIZE / 4,
- False,
- 4,
- &(Atom) {0},
- &(i32) {0},
- (void *) &count,
- &(unsigned long) {0},
- (void *) &formats
- );
- else {
- count = 0;
-
- if (ev.xclient.data.l[2] != None) real_formats[count++] = ev.xclient.data.l[2];
- if (ev.xclient.data.l[3] != None) real_formats[count++] = ev.xclient.data.l[3];
- if (ev.xclient.data.l[4] != None) real_formats[count++] = ev.xclient.data.l[4];
-
- formats = real_formats;
- }
-
- for (i64 i = 0; i < count; ++i)
- if (formats[i] == _text_uri_list || formats[i] == _text_plain) {
- _dnd_format = formats[i];
- break;
- }
-
- if (list)
- XFree(formats);
-
- break;
- }
-
- if (_dnd_version > 5)
- break;
-
- if (ev.xclient.message_type == _dnd_position) {
+ if (ev.xclient.message_type == _dnd_enter)
+ _dnd_source = ev.xclient.data.l[0];
+ else if (ev.xclient.message_type == _dnd_position) {
i32 xabs = (ev.xclient.data.l[2] >> 16) & 0xffff;
i32 yabs = ev.xclient.data.l[2] & 0xffff;
@@ -2080,52 +1961,95 @@ i32 p_handle_events(void) {
g_platform.cursor_x = xpos;
g_platform.cursor_y = ypos;
- XEvent reply = {
- .xclient = {
- .type = ClientMessage,
- .message_type = _dnd_status,
- .window = _drop_source,
- .format = 32,
- .data = {
- .l = { _window, },
- },
- },
- };
-
- if (_dnd_format) {
- reply.xclient.data.l[1] = 1;
- if (_dnd_version >= 2)
- reply.xclient.data.l[4] = _dnd_action_copy;
- }
-
- XSendEvent(_display, _dnd_source, False, NoEventMask, &reply);
- XFlush(_display);
- } else if (ev.xclient.message_type == _dnd_drop) {
- if (_dnd_format)
+ if (!g_platform.files_dragged) {
XConvertSelection(
_display,
_dnd_selection,
- _dnd_format,
+ _text_uri_list,
_dnd_selection,
_window,
- _dnd_version >= 1 ? ev.xclient.data.l[2] : CurrentTime
+ ev.xclient.data.l[2]
);
- else if (_dnd_version >= 2) {
- XEvent reply = {
+
+ g_platform.files_dragged = 1;
+ }
+
+ XSendEvent(
+ _display,
+ _dnd_source,
+ False,
+ NoEventMask,
+ &(XEvent) {
+ .xclient = {
+ .type = ClientMessage,
+ .message_type = _dnd_status,
+ .window = _drop_source,
+ .format = 32,
+ .data = {
+ .l = { _window, 1, 0, 0, _dnd_action_copy, },
+ },
+ },
+ }
+ );
+
+ XFlush(_display);
+ } else if (ev.xclient.message_type == _dnd_drop) {
+ if (g_platform.drop_files == NULL)
+ LOG_ERROR("No drop files.");
+ else
+ for (i64 i = 0; i < g_platform.num_drop_files; ++i) {
+ FILE *f = fopen(g_platform.drop_files[i].name, "rb");
+
+ if (f == NULL)
+ LOG_ERROR("Unable to open: %s", g_platform.drop_files[i].name);
+
+ i64 size = 0;
+
+ if (f != NULL) {
+ struct stat info;
+ if (fstat(fileno(f), &info) == 0 && S_ISREG(info.st_mode))
+ size = (i64) info.st_size;
+ else
+ LOG_ERROR("Unable to get the file info: %s", g_platform.drop_files[i].name);
+ }
+
+ if (size > 0) {
+ drop_files_set_data_(i, size);
+
+ i64 num = (i64) fread(g_platform.drop_files[i].data, 1, g_platform.drop_files[i].data_size + 1, f);
+ fclose(f);
+
+ if (num != g_platform.drop_files[i].data_size) {
+ LOG_ERROR("Unable to read: %s", g_platform.drop_files[i].name);
+ drop_files_set_data_(i, 0);
+ }
+ }
+ }
+
+ g_platform.files_dropped = 1;
+
+ XSendEvent(
+ _display,
+ _dnd_source,
+ False,
+ NoEventMask,
+ &(XEvent) {
.xclient = {
.type = ClientMessage,
.message_type = _dnd_finished,
.window = _drop_source,
.format = 32,
.data = {
- .l = { _window, },
+ .l = { _window, 1, _dnd_action_copy, },
},
},
- };
+ }
+ );
- XSendEvent(_display, _dnd_source, False, NoEventMask, &reply);
- XFlush(_display);
- }
+ XFlush(_display);
+ } else if (ev.xclient.message_type == _dnd_leave) {
+ if (!g_platform.files_dropped)
+ drop_files_clean_();
}
}