diff options
Diffstat (limited to 'reduced_system_layer.c')
-rw-r--r-- | reduced_system_layer.c | 316 |
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_(); } } |