summaryrefslogtreecommitdiff
path: root/src/linux
diff options
context:
space:
mode:
Diffstat (limited to 'src/linux')
-rw-r--r--src/linux/platform.c1593
-rw-r--r--src/linux/thread.c129
2 files changed, 0 insertions, 1722 deletions
diff --git a/src/linux/platform.c b/src/linux/platform.c
deleted file mode 100644
index 140715b..0000000
--- a/src/linux/platform.c
+++ /dev/null
@@ -1,1593 +0,0 @@
-/*
-* BSD 2-Clause “Simplified” License
-* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com
-* All rights reserved.
-*/
-
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/Xatom.h>
-#include <time.h>
-#include <X11/XKBlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <dirent.h>
-#include <errno.h>
-#include <dlfcn.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <X11/cursorfont.h>
-
-#define GET_ATOM(X) window.X = XInternAtom(window.display, #X, False)
-
-struct t_platform_window
-{
- Display *display;
- Window parent;
- XVisualInfo *visual_info;
- Colormap cmap;
- Window window;
- GLXContext gl_context;
- XWindowAttributes window_attributes;
- XEvent event;
- char *clipboard_str;
- s32 clipboard_strlen;
-
- Atom xdnd_req;
- Atom xdnd_source;
- Atom XdndEnter;
- Atom XdndPosition;
- Atom XdndStatus;
- Atom XdndTypeList;
- Atom XdndActionCopy;
- Atom XdndDrop;
- Atom XdndFinished;
- Atom XdndSelection;
- Atom XdndLeave;
- Atom quit;
- Atom PRIMARY;
- Atom CLIPBOARD;
- Atom UTF8_STRING;
- Atom COMPOUND_STRING;
- Atom TARGETS;
- Atom MULTIPLE;
- Atom _NET_WM_STATE;
-
- // shared window properties
- s32 width;
- s32 height;
- bool is_open;
- bool has_focus;
- cursor_type curr_cursor_type;
- cursor_type next_cursor_type;
-};
-
-bool platform_get_clipboard(platform_window *window, char *buffer)
-{
- char *result;
- unsigned long ressize, restail;
- int resbits;
- Atom bufid = XInternAtom(window->display, "CLIPBOARD", False),
- fmtid = XInternAtom(window->display, "UTF8_STRING", False),
- propid = XInternAtom(window->display, "XSEL_DATA", False),
- incrid = XInternAtom(window->display, "INCR", False);
- XEvent event;
-
- if(window->CLIPBOARD != None) {
-
- if (settings_window && XGetSelectionOwner(window->display, window->CLIPBOARD) == settings_window->window)
- {
- snprintf(buffer, MAX_INPUT_LENGTH, "%s", settings_window->clipboard_str);
- return true;
- }
- else if (XGetSelectionOwner(window->display, window->CLIPBOARD) ==
- main_window->window)
- {
- snprintf(buffer, MAX_INPUT_LENGTH, "%s", main_window->clipboard_str);
- return true;
- }
- }
-
- XConvertSelection(window->display, bufid, fmtid, propid, window->window, CurrentTime);
- do {
- XNextEvent(window->display, &event);
- } while (event.type != SelectionNotify || event.xselection.selection != bufid);
-
- if (event.xselection.property)
- {
- XGetWindowProperty(window->display, window->window, propid, 0, LONG_MAX/4, False, AnyPropertyType,
- &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);
-
- if (fmtid == incrid)
- printf("Buffer is too large and INCR reading is not implemented yet.\n");
- else
- snprintf(buffer, MAX_INPUT_LENGTH, "%s", result);
-
- XFree(result);
- return True;
- }
- else // request failed, e.g. owner can't convert to the target format
- return False;
-}
-
-bool platform_set_clipboard(platform_window *window, char *buffer)
-{
- if (buffer)
- {
- if(window->CLIPBOARD != None && XGetSelectionOwner(window->display, window->CLIPBOARD) != window->window) {
- XSetSelectionOwner(window->display, window->CLIPBOARD, window->window, CurrentTime);
- }
-
- window->clipboard_strlen = strlen(buffer);
- if(!window->clipboard_str) {
- window->clipboard_str = mem_alloc(window->clipboard_strlen+1);
- } else {
- window->clipboard_str = mem_realloc(window->clipboard_str, window->clipboard_strlen+1);
- }
- string_copyn(window->clipboard_str, buffer, window->clipboard_strlen+1);
-
- return true;
- }
-
- return false;
-}
-
-void platform_create_config_directory()
-{
- char *env = getenv("HOME");
- char tmp[PATH_MAX];
- snprintf(tmp, PATH_MAX, "%s%s", env, "/.config/moedit");
-
- if (!platform_directory_exists(tmp))
- {
- mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- }
-}
-
-char* get_config_save_location(char *buffer)
-{
- char *env = getenv("HOME");
- snprintf(buffer, PATH_MAX, "%s%s", env, "/.config/moedit/config.txt");
- return buffer;
-}
-
-inline void platform_set_cursor(platform_window *window, cursor_type type)
-{
- if (window->next_cursor_type != type)
- {
- window->next_cursor_type = type;
- }
-}
-
-bool is_platform_in_darkmode()
-{
- return false;
-}
-
-bool get_active_directory(char *buffer)
-{
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) != NULL) {
- string_copyn(buffer, cwd, PATH_MAX);
- } else {
- return false;
- }
- return true;
-}
-
-bool set_active_directory(char *path)
-{
- return !chdir(path);
-}
-
-bool platform_write_file_content(char *path, const char *mode, char *buffer, s32 len)
-{
- bool result = false;
-
- FILE *file = fopen(path, mode);
-
- if (!file)
- {
- goto done_failure;
- }
- else
- {
- fwrite(buffer, 1, len, file); // TODO(Aldrik): is this correct?
- //fprintf(file, "%s", buffer);
- }
-
- //done:
- fclose(file);
- done_failure:
- return result;
-}
-
-void platform_window_set_title(platform_window *window, char *name)
-{
- Atom WM_NAME = XInternAtom(window->display, "WM_NAME", False);
- Atom _NET_WM_NAME = XInternAtom(window->display, "_NET_WM_NAME", False);
- Atom _NET_WM_ICON_NAME = XInternAtom(window->display, "_NET_WM_ICON_NAME", False);
-
- char *list[1] = { (char *) name };
- XTextProperty property;
-
- XStoreName(window->display, window->window, name);
-
- Xutf8TextListToTextProperty(window->display, list, 1, XUTF8StringStyle,
- &property);
- XSetTextProperty(window->display, window->window, &property, WM_NAME);
- XSetTextProperty(window->display, window->window, &property, _NET_WM_NAME);
- XSetTextProperty(window->display, window->window, &property, XA_WM_NAME);
- XSetTextProperty(window->display, window->window, &property, _NET_WM_ICON_NAME);
- XFree(property.value);
-}
-
-bool platform_file_exists(char *path)
-{
- if(access(path, F_OK) != -1) {
- return 1;
- }
-
- return 0;
-}
-
-bool platform_directory_exists(char *path)
-{
- DIR* dir = opendir(path);
- if (dir) {
- /* Directory exists. */
- closedir(dir);
- return 1;
- } else if (ENOENT == errno) {
- return 0; // does not exist
- } else {
- return 0; // error opening dir
- }
-}
-
-file_content platform_read_file_content(char *path, const char *mode)
-{
- file_content result;
- result.content = 0;
- result.content_length = 0;
- result.file_error = 0;
-
- FILE *file = fopen(path, mode);
-
- if (!file)
- {
- if (errno == EMFILE)
- result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS;
- else if (errno == ENFILE)
- result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM;
- else if (errno == EACCES)
- result.file_error = FILE_ERROR_NO_ACCESS;
- else if (errno == EPERM)
- result.file_error = FILE_ERROR_NO_ACCESS;
- else if (errno == ENOENT)
- result.file_error = FILE_ERROR_NOT_FOUND;
- else if (errno == ECONNABORTED)
- result.file_error = FILE_ERROR_CONNECTION_ABORTED;
- else if (errno == ECONNREFUSED)
- result.file_error = FILE_ERROR_CONNECTION_REFUSED;
- else if (errno == ENETDOWN)
- result.file_error = FILE_ERROR_NETWORK_DOWN;
- else if (errno == EREMOTEIO)
- result.file_error = FILE_ERROR_REMOTE_IO_ERROR;
- else if (errno == ESTALE)
- result.file_error = FILE_ERROR_STALE;
- else
- {
- result.file_error = FILE_ERROR_GENERIC;
- printf("ERROR: %d\n", errno);
- }
-
- goto done_failure;
- }
-
- fseek(file, 0 , SEEK_END);
- int length = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- s32 length_to_alloc = length+1;
-
- result.content = mem_alloc(length_to_alloc);
- if (!result.content) goto done;
-
- memset(result.content, 0, length);
- s32 read_result = fread(result.content, 1, length, file);
- if (read_result == 0 && length != 0)
- {
- mem_free(result.content);
- result.content = 0;
- return result;
- }
-
- result.content_length = read_result;
-
- ((char*)result.content)[length] = 0;
-
- done:
- fclose(file);
- done_failure:
- return result;
-}
-
-inline void platform_destroy_file_content(file_content *content)
-{
- assert(content);
- mem_free(content->content);
-}
-
-// Translate an X11 key code to a GLFW key code.
-//
-static s32 translate_keycode(platform_window *window, s32 scancode)
-{
- s32 keySym;
-
- // Valid key code range is [8,255], according to the Xlib manual
-
- if (1)
- {
- // Try secondary keysym, for numeric keypad keys
- // Note: This way we always force "NumLock = ON", which is intentional
- // since the returned key code should correspond to a physical
- // location.
- keySym = XkbKeycodeToKeysym(window->display, scancode, 0, 1);
- switch (keySym)
- {
- case XK_KP_0: return KEY_KP_0;
- case XK_KP_1: return KEY_KP_1;
- case XK_KP_2: return KEY_KP_2;
- case XK_KP_3: return KEY_KP_3;
- case XK_KP_4: return KEY_KP_4;
- case XK_KP_5: return KEY_KP_5;
- case XK_KP_6: return KEY_KP_6;
- case XK_KP_7: return KEY_KP_7;
- case XK_KP_8: return KEY_KP_8;
- case XK_KP_9: return KEY_KP_9;
- case XK_KP_Separator:
- case XK_KP_Decimal: return KEY_KP_DECIMAL;
- case XK_KP_Equal: return KEY_KP_EQUAL;
- case XK_KP_Enter: return KEY_KP_ENTER;
- default: break;
- }
-
- // Now try primary keysym for function keys (non-printable keys)
- // These should not depend on the current keyboard layout
- keySym = XkbKeycodeToKeysym(window->display, scancode, 0, 0);
- }
-
- switch (keySym)
- {
- case XK_Escape: return KEY_ESCAPE;
- case XK_Tab: return KEY_TAB;
- case XK_Shift_L: return KEY_LEFT_SHIFT;
- case XK_Shift_R: return KEY_RIGHT_SHIFT;
- case XK_Control_L: return KEY_LEFT_CONTROL;
- case XK_Control_R: return KEY_RIGHT_CONTROL;
- case XK_Meta_L:
- case XK_Alt_L: return KEY_LEFT_ALT;
- case XK_Mode_switch: // Mapped to Alt_R on many keyboards
- case XK_ISO_Level3_Shift: // AltGr on at least some machines
- case XK_Meta_R:
- case XK_Alt_R: return KEY_RIGHT_ALT;
- case XK_Super_L: return KEY_LEFT_SUPER;
- case XK_Super_R: return KEY_RIGHT_SUPER;
- case XK_Menu: return KEY_MENU;
- case XK_Num_Lock: return KEY_NUM_LOCK;
- case XK_Caps_Lock: return KEY_CAPS_LOCK;
- case XK_Print: return KEY_PRINT_SCREEN;
- case XK_Scroll_Lock: return KEY_SCROLL_LOCK;
- case XK_Pause: return KEY_PAUSE;
- case XK_Delete: return KEY_DELETE;
- case XK_BackSpace: return KEY_BACKSPACE;
- case XK_Return: return KEY_ENTER;
- case XK_Home: return KEY_HOME;
- case XK_End: return KEY_END;
- case XK_Page_Up: return KEY_PAGE_UP;
- case XK_Page_Down: return KEY_PAGE_DOWN;
- case XK_Insert: return KEY_INSERT;
- case XK_Left: return KEY_LEFT;
- case XK_Right: return KEY_RIGHT;
- case XK_Down: return KEY_DOWN;
- case XK_Up: return KEY_UP;
- case XK_F1: return KEY_F1;
- case XK_F2: return KEY_F2;
- case XK_F3: return KEY_F3;
- case XK_F4: return KEY_F4;
- case XK_F5: return KEY_F5;
- case XK_F6: return KEY_F6;
- case XK_F7: return KEY_F7;
- case XK_F8: return KEY_F8;
- case XK_F9: return KEY_F9;
- case XK_F10: return KEY_F10;
- case XK_F11: return KEY_F11;
- case XK_F12: return KEY_F12;
- case XK_F13: return KEY_F13;
- case XK_F14: return KEY_F14;
- case XK_F15: return KEY_F15;
- case XK_F16: return KEY_F16;
- case XK_F17: return KEY_F17;
- case XK_F18: return KEY_F18;
- case XK_F19: return KEY_F19;
- case XK_F20: return KEY_F20;
- case XK_F21: return KEY_F21;
- case XK_F22: return KEY_F22;
- case XK_F23: return KEY_F23;
- case XK_F24: return KEY_F24;
- case XK_F25: return KEY_F25;
-
- // Numeric keypad
- case XK_KP_Divide: return KEY_KP_DIVIDE;
- case XK_KP_Multiply: return KEY_KP_MULTIPLY;
- case XK_KP_Subtract: return KEY_KP_SUBTRACT;
- case XK_KP_Add: return KEY_KP_ADD;
-
- // These should have been detected in secondary keysym test above!
- case XK_KP_Insert: return KEY_KP_0;
- case XK_KP_End: return KEY_KP_1;
- case XK_KP_Down: return KEY_KP_2;
- case XK_KP_Page_Down: return KEY_KP_3;
- case XK_KP_Left: return KEY_KP_4;
- case XK_KP_Right: return KEY_KP_6;
- case XK_KP_Home: return KEY_KP_7;
- case XK_KP_Up: return KEY_KP_8;
- case XK_KP_Page_Up: return KEY_KP_9;
- case XK_KP_Delete: return KEY_KP_DECIMAL;
- case XK_KP_Equal: return KEY_KP_EQUAL;
- case XK_KP_Enter: return KEY_KP_ENTER;
-
- // Last resort: Check for printable keys (should not happen if the XKB
- // extension is available). This will give a layout dependent mapping
- // (which is wrong, and we may miss some keys, especially on non-US
- // keyboards), but it's better than nothing...
- case XK_a: return KEY_A;
- case XK_b: return KEY_B;
- case XK_c: return KEY_C;
- case XK_d: return KEY_D;
- case XK_e: return KEY_E;
- case XK_f: return KEY_F;
- case XK_g: return KEY_G;
- case XK_h: return KEY_H;
- case XK_i: return KEY_I;
- case XK_j: return KEY_J;
- case XK_k: return KEY_K;
- case XK_l: return KEY_L;
- case XK_m: return KEY_M;
- case XK_n: return KEY_N;
- case XK_o: return KEY_O;
- case XK_p: return KEY_P;
- case XK_q: return KEY_Q;
- case XK_r: return KEY_R;
- case XK_s: return KEY_S;
- case XK_t: return KEY_T;
- case XK_u: return KEY_U;
- case XK_v: return KEY_V;
- case XK_w: return KEY_W;
- case XK_x: return KEY_X;
- case XK_y: return KEY_Y;
- case XK_z: return KEY_Z;
- case XK_1: return KEY_1;
- case XK_2: return KEY_2;
- case XK_3: return KEY_3;
- case XK_4: return KEY_4;
- case XK_5: return KEY_5;
- case XK_6: return KEY_6;
- case XK_7: return KEY_7;
- case XK_8: return KEY_8;
- case XK_9: return KEY_9;
- case XK_0: return KEY_0;
- case XK_space: return KEY_SPACE;
- case XK_minus: return KEY_MINUS;
- case XK_equal: return KEY_EQUAL;
- case XK_bracketleft: return KEY_LEFT_BRACKET;
- case XK_bracketright: return KEY_RIGHT_BRACKET;
- case XK_backslash: return KEY_BACKSLASH;
- case XK_semicolon: return KEY_SEMICOLON;
- case XK_apostrophe: return KEY_APOSTROPHE;
- case XK_grave: return KEY_GRAVE_ACCENT;
- case XK_comma: return KEY_COMMA;
- case XK_period: return KEY_PERIOD;
- case XK_slash: return KEY_SLASH;
- case XK_less: return KEY_WORLD_1; // At least in some layouts...
- default: break;
- }
-
- // No matching translation was found
- return KEY_UNKNOWN;
-}
-
-static void create_key_tables(platform_window window)
-{
- s32 scancode, key;
- char name[XkbKeyNameLength + 1];
- XkbDescPtr desc = XkbGetMap(window.display, 0, XkbUseCoreKbd);
- XkbGetNames(window.display, XkbKeyNamesMask, desc);
-
- // uncomment for layout independant input for games.
-#if 0
- for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
- {
- memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
- name[XkbKeyNameLength] = '\0';
-
- // Map the key name to a GLFW key code. Note: We only map printable
- // keys here, and we use the US keyboard layout. The rest of the
- // keys (function keys) are mapped using traditional KeySym
- // translations.
- if (strcmp(name, "TLDE") == 0) key = KEY_GRAVE_ACCENT;
- else if (strcmp(name, "AE01") == 0) key = KEY_1;
- else if (strcmp(name, "AE02") == 0) key = KEY_2;
- else if (strcmp(name, "AE03") == 0) key = KEY_3;
- else if (strcmp(name, "AE04") == 0) key = KEY_4;
- else if (strcmp(name, "AE05") == 0) key = KEY_5;
- else if (strcmp(name, "AE06") == 0) key = KEY_6;
- else if (strcmp(name, "AE07") == 0) key = KEY_7;
- else if (strcmp(name, "AE08") == 0) key = KEY_8;
- else if (strcmp(name, "AE09") == 0) key = KEY_9;
- else if (strcmp(name, "AE10") == 0) key = KEY_0;
- else if (strcmp(name, "AE11") == 0) key = KEY_MINUS;
- else if (strcmp(name, "AE12") == 0) key = KEY_EQUAL;
- else if (strcmp(name, "AD01") == 0) key = KEY_Q;
- else if (strcmp(name, "AD02") == 0) key = KEY_W;
- else if (strcmp(name, "AD03") == 0) key = KEY_E;
- else if (strcmp(name, "AD04") == 0) key = KEY_R;
- else if (strcmp(name, "AD05") == 0) key = KEY_T;
- else if (strcmp(name, "AD06") == 0) key = KEY_Y;
- else if (strcmp(name, "AD07") == 0) key = KEY_U;
- else if (strcmp(name, "AD08") == 0) key = KEY_I;
- else if (strcmp(name, "AD09") == 0) key = KEY_O;
- else if (strcmp(name, "AD10") == 0) key = KEY_P;
- else if (strcmp(name, "AD11") == 0) key = KEY_LEFT_BRACKET;
- else if (strcmp(name, "AD12") == 0) key = KEY_RIGHT_BRACKET;
- else if (strcmp(name, "AC01") == 0) key = KEY_A;
- else if (strcmp(name, "AC02") == 0) key = KEY_S;
- else if (strcmp(name, "AC03") == 0) key = KEY_D;
- else if (strcmp(name, "AC04") == 0) key = KEY_F;
- else if (strcmp(name, "AC05") == 0) key = KEY_G;
- else if (strcmp(name, "AC06") == 0) key = KEY_H;
- else if (strcmp(name, "AC07") == 0) key = KEY_J;
- else if (strcmp(name, "AC08") == 0) key = KEY_K;
- else if (strcmp(name, "AC09") == 0) key = KEY_L;
- else if (strcmp(name, "AC10") == 0) key = KEY_SEMICOLON;
- else if (strcmp(name, "AC11") == 0) key = KEY_APOSTROPHE;
- else if (strcmp(name, "AB01") == 0) key = KEY_Z;
- else if (strcmp(name, "AB02") == 0) key = KEY_X;
- else if (strcmp(name, "AB03") == 0) key = KEY_C;
- else if (strcmp(name, "AB04") == 0) key = KEY_V;
- else if (strcmp(name, "AB05") == 0) key = KEY_B;
- else if (strcmp(name, "AB06") == 0) key = KEY_N;
- else if (strcmp(name, "AB07") == 0) key = KEY_M;
- else if (strcmp(name, "AB08") == 0) key = KEY_COMMA;
- else if (strcmp(name, "AB09") == 0) key = KEY_PERIOD;
- else if (strcmp(name, "AB10") == 0) key = KEY_SLASH;
- else if (strcmp(name, "BKSL") == 0) key = KEY_BACKSLASH;
- else if (strcmp(name, "LSGT") == 0) key = KEY_WORLD_1;
- else key = KEY_UNKNOWN;
-
- if ((scancode >= 0) && (scancode < 256))
- keycode_map[scancode] = key;
- }
-#endif
-
- for (scancode = 0; scancode < MAX_KEYCODE; scancode++)
- {
- // Translate the un-translated key codes using traditional X11 KeySym
- // lookups
-
- keycode_map[scancode] = translate_keycode(&window, scancode);
- }
-
- XkbFreeNames(desc, XkbKeyNamesMask, True);
- XkbFreeKeyboard(desc, 0, True);
-}
-
-inline void platform_init(int argc, char **argv)
-{
-#if 0
- dlerror(); // clear error
- void *x11 = dlopen("libX11.so.6", RTLD_NOW | RTLD_GLOBAL);
- void *randr = dlopen("libXrandr.so", RTLD_NOW | RTLD_GLOBAL);
-#endif
-
- setlocale(LC_ALL, "en_US.UTF-8");
-
- XInitThreads();
-
- // get fullpath of the directory the binary is residing in
- binary_path = platform_get_full_path(argv[0]);
-
- platform_create_config_directory();
-
- char buf[MAX_INPUT_LENGTH];
- get_directory_from_path(buf, binary_path);
- string_copyn(binary_path, buf, MAX_INPUT_LENGTH);
-
- assets_create();
-}
-
-inline void platform_destroy()
-{
- assets_destroy();
-
-#if defined(MODE_DEVELOPER)
- memory_print_leaks();
-#endif
-}
-
-inline void platform_window_make_current(platform_window *window)
-{
- glXMakeCurrent(window->display, window->window, window->gl_context);
-}
-
-void platform_window_set_size(platform_window *window, u16 width, u16 height)
-{
- XResizeWindow(window->display, window->window, width, height);
-}
-
-void platform_window_set_position(platform_window *window, u16 x, u16 y)
-{
- XMoveWindow(window->display, window->window, x, y);
-}
-
-
-vec2 platform_get_window_size(platform_window *window)
-{
- vec2 res;
- res.x = window->width;
- res.y = window->height;
- return res;
-}
-
-platform_window platform_open_window(char *name, u16 width, u16 height, u16 max_w, u16 max_h, u16 min_w, u16 min_h)
-{
- bool has_max_size = max_w || max_h;
-
- platform_window window;
- window.has_focus = true;
- window.curr_cursor_type = CURSOR_DEFAULT;
- window.next_cursor_type = CURSOR_DEFAULT;
- window.clipboard_str = 0;
- window.clipboard_strlen = 0;
-
- static int att[] =
- {
- GLX_X_RENDERABLE , True,
- GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
- GLX_RENDER_TYPE , GLX_RGBA_BIT,
- GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
- GLX_RED_SIZE , 8,
- GLX_GREEN_SIZE , 8,
- GLX_BLUE_SIZE , 8,
- GLX_ALPHA_SIZE , 8,
- GLX_DEPTH_SIZE , 24,
- GLX_STENCIL_SIZE , 8,
- GLX_DOUBLEBUFFER , True,
- //GLX_SAMPLE_BUFFERS , 1,
- //GLX_SAMPLES , 4,
- None
- };
-
- window.display = XOpenDisplay(NULL);
-
- if(window.display == NULL) {
- return window;
- }
-
- window.parent = DefaultRootWindow(window.display);
-
- int fbcount;
- GLXFBConfig* fbc = glXChooseFBConfig(window.display, DefaultScreen(window.display), att, &fbcount);
- int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
-
- int i;
- for (i=0; i<fbcount; ++i)
- {
- XVisualInfo *vi = glXGetVisualFromFBConfig(window.display, fbc[i] );
- if ( vi )
- {
- int samp_buf, samples;
- glXGetFBConfigAttrib(window.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
- glXGetFBConfigAttrib(window.display, fbc[i], GLX_SAMPLES , &samples );
-
- if ( best_fbc < 0 || (samp_buf && samples > best_num_samp))
- best_fbc = i, best_num_samp = samples;
- if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
- worst_fbc = i, worst_num_samp = samples;
- }
- XFree(vi);
- }
-
- GLXFBConfig bestFbc = fbc[best_fbc];
- XFree(fbc);
-
- XVisualInfo *vi = glXGetVisualFromFBConfig(window.display, bestFbc );
- window.visual_info = vi;
-
- if(window.visual_info == NULL) {
- return window;
- }
-
- window.cmap = XCreateColormap(window.display, window.parent, window.visual_info->visual, AllocNone);
-
- // calculate window center
- XRRScreenResources *screens = XRRGetScreenResources(window.display, window.parent);
- XRRCrtcInfo *info = XRRGetCrtcInfo(window.display, screens, screens->crtcs[0]);
-
- s32 center_x = (info->width / 2) - (width / 2);
- s32 center_y = (info->height / 2) - (height / 2);
-
- XRRFreeCrtcInfo(info);
- XRRFreeScreenResources(screens);
-
- XSetWindowAttributes window_attributes;
- window_attributes.colormap = window.cmap;
- window_attributes.border_pixel = 0;
- window_attributes.event_mask = KeyPressMask | KeyReleaseMask | PointerMotionMask |
- ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask;
-
- window.window = XCreateWindow(window.display, window.parent, center_x, center_y, width, height, 0, window.visual_info->depth, InputOutput, window.visual_info->visual, CWColormap | CWEventMask | CWBorderPixel, &window_attributes);
-
- XMapWindow(window.display, window.window);
- XFlush(window.display);
-
- XSync(window.display, False);
-
- XSizeHints hints;
-
- if (has_max_size)
- hints.flags = PMaxSize | PMinSize | USPosition;
- else
- hints.flags = PMinSize | USPosition;
- hints.x = center_x;
- hints.y = center_y;
- hints.max_width = width;
- hints.max_height = height;
- hints.min_width = min_w;
- hints.min_height = min_h;
-
- XSetWMNormalHints(window.display, window.window, &hints);
-
- // window name
- {
- Atom WM_NAME = XInternAtom(window.display, "WM_NAME", False);
- Atom _NET_WM_NAME = XInternAtom(window.display, "_NET_WM_NAME", False);
- Atom _NET_WM_ICON_NAME = XInternAtom(window.display, "_NET_WM_ICON_NAME", False);
-
- char *list[1] = { (char *) name };
- XTextProperty property;
-
- XStoreName(window.display, window.window, name);
-
- Xutf8TextListToTextProperty(window.display, list, 1, XUTF8StringStyle,
- &property);
- XSetTextProperty(window.display, window.window, &property, WM_NAME);
- XSetTextProperty(window.display, window.window, &property, _NET_WM_NAME);
- XSetTextProperty(window.display, window.window, &property, XA_WM_NAME);
- XSetTextProperty(window.display, window.window, &property, _NET_WM_ICON_NAME);
- XFree(property.value);
-
- XClassHint class_hint;
- class_hint.res_name = name;
- class_hint.res_class = name;
- XSetClassHint(window.display, window.window, &class_hint);
- }
-
-
- // hide taskbar icon and stay on top
-#if 0
- {
- Atom wm_state = XInternAtom(window.display,
- "_NET_WM_STATE", False);
- Atom taskbar_atom = XInternAtom(window.display,
- "_NET_WM_STATE_SKIP_TASKBAR", False);
- Atom above_atom = XInternAtom(window.display,
- "_NET_WM_STATE_ABOVE", False);
-
- Atom atom_list[2] = {taskbar_atom, above_atom};
- XChangeProperty(window.display, window.window, wm_state, XA_ATOM, 32,
- PropModeReplace, (const unsigned char*)&atom_list, 2);
- }
-#endif
-
- {
- XWMHints* win_hints = XAllocWMHints();
- win_hints->flags = StateHint | IconPositionHint;
- win_hints->initial_state = IconicState;
- win_hints->icon_x = 0;
- win_hints->icon_y = 0;
-
- /* pass the hints to the window manager. */
- XSetWMHints(window.display, window.window, win_hints);
- XFree(win_hints);
- }
-
- static GLXContext share_list = 0;
-
- // get opengl context
- window.gl_context = glXCreateContext(window.display, window.visual_info,
- share_list, GL_TRUE);
-
- if (share_list == 0)
- share_list = window.gl_context;
- glXMakeCurrent(window.display, window.window, window.gl_context);
-
- // blending
- glEnable(GL_DEPTH_TEST);
- //glDepthMask(true);
- //glClearDepth(50);
- glDepthFunc(GL_LEQUAL);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- // setup multisampling
-#if 0
- glEnable(GL_ALPHA_TEST);
- glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glEnable(GL_SAMPLE_ALPHA_TO_ONE);
- glEnable(GL_MULTISAMPLE);
- glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
-#endif
-
- window.is_open = true;
- window.width = width;
- window.height = height;
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, width, height, 0, -1, 1);
-
- glMatrixMode(GL_MODELVIEW);
-
- create_key_tables(window);
-
- // recieve window close event
- window.quit = XInternAtom(window.display, "WM_DELETE_WINDOW", False);
-
- GET_ATOM(XdndEnter);
- GET_ATOM(XdndPosition);
- GET_ATOM(XdndStatus);
- GET_ATOM(XdndTypeList);
- GET_ATOM(XdndActionCopy);
- GET_ATOM(XdndDrop);
- GET_ATOM(XdndFinished);
- GET_ATOM(XdndSelection);
- GET_ATOM(XdndLeave);
- GET_ATOM(PRIMARY);
- GET_ATOM(CLIPBOARD);
- GET_ATOM(UTF8_STRING);
- GET_ATOM(COMPOUND_STRING);
- GET_ATOM(TARGETS);
- GET_ATOM(MULTIPLE);
- GET_ATOM(_NET_WM_STATE);
-
- array atoms = array_create(sizeof(Atom));
- array_push(&atoms, &window.quit);
- array_push(&atoms, &window.XdndEnter);
- array_push(&atoms, &window.XdndPosition);
- array_push(&atoms, &window.XdndStatus);
- array_push(&atoms, &window.XdndTypeList);
- array_push(&atoms, &window.XdndActionCopy);
- array_push(&atoms, &window.XdndDrop);
- array_push(&atoms, &window.XdndFinished);
- array_push(&atoms, &window.XdndSelection);
- array_push(&atoms, &window.XdndLeave);
- array_push(&atoms, &window.PRIMARY);
- array_push(&atoms, &window.CLIPBOARD);
- array_push(&atoms, &window.UTF8_STRING);
- array_push(&atoms, &window.COMPOUND_STRING);
- array_push(&atoms, &window.TARGETS);
- array_push(&atoms, &window.MULTIPLE);
- array_push(&atoms, &window._NET_WM_STATE);
-
- XSetWMProtocols(window.display, window.window, atoms.data, atoms.length);
- array_destroy(&atoms);
-
- Atom XdndAware = XInternAtom(window.display, "XdndAware", False);
- Atom xdnd_version = 5;
- XChangeProperty(window.display, window.window, XdndAware, XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&xdnd_version, 1);
-
-
- XFlush(window.display);
- XSync(window.display, True);
-
- return window;
-}
-
-inline bool platform_window_is_valid(platform_window *window)
-{
- return window->window && window->display;
-}
-
-void platform_destroy_window(platform_window *window)
-{
- glXMakeCurrent(window->display, None, NULL);
- glXDestroyContext(window->display, window->gl_context);
- XDestroyWindow(window->display, window->window);
- XCloseDisplay(window->display);
- XFree(window->visual_info);
- mem_free(window->clipboard_str);
-
- window->window = 0;
- window->display = 0;
-}
-
-void platform_hide_window_taskbar_icon(platform_window *window)
-{
- XClientMessageEvent m;
- memset(&m, 0, sizeof(XClientMessageEvent));
- m.type = ClientMessage;
- m.display = window->display;
- m.window = window->window;
- m.message_type = window->_NET_WM_STATE;
- m.format=32;
- m.data.l[0] = 1;
- m.data.l[1] = XInternAtom(window->display, "_NET_WM_STATE_SKIP_TASKBAR", False);
- m.data.l[2] = None;
- m.data.l[3] = 1;
- m.data.l[4] = 0;
- XSendEvent(window->display, window->window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&m);
-
- XFlush(window->display);
-}
-
-void platform_handle_events(platform_window *window, mouse_input *mouse, keyboard_input *keyboard)
-{
- mouse->left_state &= ~MOUSE_CLICK;
- mouse->right_state &= ~MOUSE_CLICK;
- mouse->left_state &= ~MOUSE_DOUBLE_CLICK;
- mouse->right_state &= ~MOUSE_DOUBLE_CLICK;
- mouse->left_state &= ~MOUSE_RELEASE;
- mouse->right_state &= ~MOUSE_RELEASE;
- memset(keyboard->input_keys, 0, MAX_KEYCODE);
- mouse->move_x = 0;
- mouse->move_y = 0;
- mouse->scroll_state = 0;
- keyboard->text_changed = false;
-
- XClientMessageEvent m;
-
- s32 pending_events = XPending(window->display);
- for (s32 i = 0; i < pending_events; i++)
- {
- XNextEvent(window->display, &window->event);
- if (window->event.type == ClientMessage)
- {
- static int xdnd_version=0;
-
- if ((Atom)window->event.xclient.data.l[0] == window->quit) {
- window->is_open = false;
- }
-
- if (window->event.xclient.message_type == window->XdndDrop)
- {
- if (window->xdnd_req == None) {
- /* say again - not interested! */
- memset(&m, 0, sizeof(XClientMessageEvent));
- m.type = ClientMessage;
- m.display = window->event.xclient.display;
- m.window = window->event.xclient.data.l[0];
- m.message_type = window->XdndFinished;
- m.format=32;
- m.data.l[0] = window->window;
- m.data.l[1] = 0;
- m.data.l[2] = None; /* fail! */
- XSendEvent(window->display, window->event.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
- } else {
- /* convert */
- if(xdnd_version >= 1) {
- XConvertSelection(window->display, window->XdndSelection, window->xdnd_req, window->PRIMARY, window->window, window->event.xclient.data.l[2]);
- } else {
- printf("time to find the time.\n");
- //XConvertSelection(window->display, window->XdndSelection, window->xdnd_req, window->PRIMARY, window->xwindow, CurrentTime);
- }
- }
- }
- }
- else if (window->event.type == LeaveNotify)
- {
- mouse->x = MOUSE_OFFSCREEN;
- mouse->y = MOUSE_OFFSCREEN;
- }
- else if (window->event.type == ConfigureNotify)
- {
- XConfigureEvent xce = window->event.xconfigure;
- window->width = xce.width;
- window->height = xce.height;
- glViewport(0, 0, window->width, window->height);
- }
- else if (window->event.type == FocusIn)
- {
- window->has_focus = true;
- }
- else if (window->event.type == FocusOut)
- {
- mouse->x = MOUSE_OFFSCREEN;
- mouse->y = MOUSE_OFFSCREEN;
- window->has_focus = false;
-
- // if windows loses focus, set all keys to not pressed
- memset(keyboard->keys, 0, MAX_KEYCODE);
- }
- else if (window->event.type == MotionNotify)
- {
- s32 x = mouse->x;
- s32 y = mouse->y;
-
- mouse->total_move_x += window->event.xmotion.x - mouse->x;
- mouse->total_move_y += window->event.xmotion.y - mouse->y;
-
- mouse->x = window->event.xmotion.x;
- mouse->y = window->event.xmotion.y;
-
- mouse->move_x = mouse->x - x;
- mouse->move_y = mouse->y - y;
- }
- else if (window->event.type == ButtonPress)
- {
- Time ev_time = window->event.xbutton.time;
- static Time last_ev_time = 0;
-
- bool is_left_down = window->event.xbutton.button == Button1;
- bool is_right_down = window->event.xbutton.button == Button3;
- bool is_middle_down = window->event.xbutton.button == Button2;
- bool scroll_up = window->event.xbutton.button == Button4;
- bool scroll_down = window->event.xbutton.button == Button5;
-
- if (scroll_up)
- mouse->scroll_state = SCROLL_UP;
- if (scroll_down)
- mouse->scroll_state = SCROLL_DOWN;
-
- if (is_left_down)
- {
- if (ev_time - last_ev_time < 200)
- {
- mouse->left_state |= MOUSE_DOUBLE_CLICK;
- }
-
- mouse->left_state |= MOUSE_DOWN;
- mouse->left_state |= MOUSE_CLICK;
-
- mouse->total_move_x = 0;
- mouse->total_move_y = 0;
- last_ev_time = ev_time;
- }
- if (is_right_down)
- {
- mouse->right_state |= MOUSE_DOWN;
- mouse->right_state |= MOUSE_CLICK;
- }
- }
- else if (window->event.type == ButtonRelease)
- {
- bool is_left_up = window->event.xbutton.button == Button1;
- bool is_right_up = window->event.xbutton.button == Button3;
- bool is_middle_up = window->event.xbutton.button == Button2;
-
- if (is_left_up)
- {
- mouse->left_state = MOUSE_RELEASE;
- }
- if (is_right_up)
- {
- mouse->right_state = MOUSE_RELEASE;
- }
- }
- else if(window->event.type == KeyPress)
- {
- s32 key = window->event.xkey.keycode;
-
- keyboard->keys[keycode_map[key]] = true;
- keyboard->input_keys[keycode_map[key]] = true;
-
- // https://gist.github.com/rickyzhang82/8581a762c9f9fc6ddb8390872552c250
- //printf("state: %d\n", window->event.xkey.state);
-
- // remove key control key from mask so it doesnt block input
- window->event.xkey.state &= ~ControlMask;
-
- // replace capslock with shiftkey else keylookup returns 0...
- if (window->event.xkey.state == 2)
- window->event.xkey.state = 1;
-
- KeySym ksym = XLookupKeysym(&window->event.xkey, window->event.xkey.state);
-
- if (keyboard->take_input)
- {
- char *ch = 0;
- switch(ksym)
- {
- case XK_space: ch = " "; break;
- case XK_exclam: ch = "!"; break;
- case XK_quotedbl: ch = "\""; break;
- case XK_numbersign: ch = "#"; break;
- case XK_dollar: ch = "$"; break;
- case XK_percent: ch = "%"; break;
- case XK_ampersand: ch = "&"; break;
- case XK_apostrophe: ch = "`"; break;
- case XK_parenleft: ch = "("; break;
- case XK_parenright: ch = ")"; break;
- case XK_asterisk: ch = "*"; break;
- case XK_plus: ch = "+"; break;
- case XK_comma: ch = ","; break;
- case XK_minus: ch = "-"; break;
- case XK_period: ch = "."; break;
- case XK_slash: ch = "/"; break;
- case XK_0: ch = "0"; break;
- case XK_1: ch = "1"; break;
- case XK_2: ch = "2"; break;
- case XK_3: ch = "3"; break;
- case XK_4: ch = "4"; break;
- case XK_5: ch = "5"; break;
- case XK_6: ch = "6"; break;
- case XK_7: ch = "7"; break;
- case XK_8: ch = "8"; break;
- case XK_9: ch = "9"; break;
-
- case XK_colon: ch = ":"; break;
- case XK_semicolon: ch = ";"; break;
- case XK_less: ch = "<"; break;
- case XK_equal: ch = "="; break;
- case XK_greater: ch = ">"; break;
- case XK_question: ch = "?"; break;
- case XK_at: ch = "@"; break;
- case XK_bracketleft: ch = "["; break;
- case XK_backslash: ch = "\\"; break;
- case XK_bracketright: ch = "]"; break;
- case XK_asciicircum: ch = "^"; break;
- case XK_underscore: ch = "_"; break;
- case XK_grave: ch = "`"; break;
- case XK_braceleft: ch = "{"; break;
- case XK_bar: ch = "|"; break;
- case XK_braceright: ch = "}"; break;
- case XK_asciitilde: ch = "~"; break;
- }
-
- if ((ksym >= XK_A && ksym <= XK_Z) || (ksym >= XK_a && ksym <= XK_z))
- {
- ch = XKeysymToString(ksym);
- }
-
- if (ch && keyboard->input_mode == INPUT_NUMERIC)
- {
- if (!(*ch >= 48 && *ch <= 57))
- {
- ch = 0;
- }
- }
-
- keyboard_handle_input_string(window, keyboard, ch);
- }
- }
- else if (window->event.type == KeyRelease)
- {
- s32 key = window->event.xkey.keycode;
- keyboard->keys[keycode_map[key]] = false;
-
- KeySym ksym = XLookupKeysym(&window->event.xkey, 0);
- }
- else if (window->event.type == SelectionClear)
- {
- window->clipboard_str = 0;
- window->clipboard_strlen = 0;
- }
- else if (window->event.type == SelectionRequest)
- {
- Atom formats[] = {window->UTF8_STRING, window->COMPOUND_STRING, XA_STRING};
- Atom targets[] = {window->TARGETS, window->MULTIPLE, window->UTF8_STRING, window->COMPOUND_STRING, XA_STRING};
- int formatCount = sizeof(formats) / sizeof(formats[0]);
-
- XSelectionEvent event = {.type = SelectionNotify, .selection = window->event.xselectionrequest.selection, .target = window->event.xselectionrequest.target, .display = window->event.xselectionrequest.display, .requestor = window->event.xselectionrequest.requestor, .time = window->event.xselectionrequest.time};
-
- if(window->event.xselectionrequest.target == window->TARGETS) {
- XChangeProperty(window->display, window->event.xselectionrequest.requestor, window->event.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char*)targets, sizeof(targets) / sizeof(targets[0]));
-
- event.property = window->event.xselectionrequest.property;
- } else {
- event.property = None;
- int i;
- for(i = 0; i < formatCount; i++) {
- if(window->event.xselectionrequest.target == formats[i]) {
- XChangeProperty(window->display, window->event.xselectionrequest.requestor, window->event.xselectionrequest.property, window->event.xselectionrequest.target, 8, PropModeReplace, (unsigned char*)window->clipboard_str, window->clipboard_strlen);
-
- event.property = window->event.xselectionrequest.property;
- break;
- }
- }
- }
-
- XSendEvent(window->display, window->event.xselectionrequest.requestor, False, 0, (XEvent*)&event);
- XFlush(window->display);
- }
- }
-}
-
-inline void platform_show_alert(char *title, char *message)
-{
- char command[MAX_INPUT_LENGTH];
- snprintf(command, MAX_INPUT_LENGTH, "notify-send \"%s\" \"%s\"", title, message);
- platform_run_command(command);
-}
-
-inline void platform_window_swap_buffers(platform_window *window)
-{
- // set cursor if changed
- if (window->curr_cursor_type != window->next_cursor_type)
- {
- int cursor_shape = 0;
- switch(window->next_cursor_type)
- {
- case CURSOR_DEFAULT: cursor_shape = XC_arrow; break;
- case CURSOR_POINTER: cursor_shape = XC_hand1; break;
- }
- Cursor cursor = XCreateFontCursor(window->display, cursor_shape);
- XDefineCursor(window->display, window->window, cursor);
- window->curr_cursor_type = window->next_cursor_type;
- }
-
- glXSwapBuffers(window->display, window->window);
-}
-
-u64 platform_get_time(time_type time_type, time_precision precision)
-{
- s32 type = CLOCK_REALTIME;
- switch(time_type)
- {
- case TIME_FULL: type = CLOCK_REALTIME; break;
- case TIME_THREAD: type = CLOCK_THREAD_CPUTIME_ID; break;
- case TIME_PROCESS: type = CLOCK_PROCESS_CPUTIME_ID; break;
- }
-
- struct timespec tms;
- if (clock_gettime(type,&tms)) {
- return -1;
- }
-
- long result = 0;
-
- if (precision == TIME_NS)
- {
- result = tms.tv_sec * 1000000000;
- result += tms.tv_nsec;
- if (tms.tv_nsec % 1000 >= 500) {
- ++result;
- }
- }
- else if (precision == TIME_US)
- {
- result = tms.tv_sec * 1000000;
- result += tms.tv_nsec/1000;
- if (tms.tv_nsec % 1000 >= 500) {
- ++result;
- }
- }
- else if (precision == TIME_MILI_S)
- {
- result = tms.tv_sec * 1000;
- result += tms.tv_nsec/1000000;
- if (tms.tv_nsec % 1000 >= 500) {
- ++result;
- }
- }
- else if (precision == TIME_S)
- {
- result = tms.tv_sec;
- result += tms.tv_nsec/1000000000;
- if (tms.tv_nsec % 1000 >= 500) {
- ++result;
- }
- }
-
- return result;
-}
-
-inline s32 platform_get_cpu_count()
-{
- return (int)sysconf(_SC_NPROCESSORS_ONLN);
-}
-
-inline s32 platform_get_memory_size()
-{
- uint64_t aid = (uint64_t) sysconf(_SC_PHYS_PAGES);
- aid *= (uint64_t) sysconf(_SC_PAGESIZE);
- aid /= (uint64_t) (1024 * 1024);
- return (int)(aid);
-}
-
-void platform_show_message(platform_window *window, char *message, char *title)
-{
- char command[MAX_INPUT_LENGTH];
- snprintf(command, MAX_INPUT_LENGTH, "zenity --info --text=\"%s\" --title=\"%s\" --width=240", message, title);
- FILE *f = popen(command, "r");
-}
-
-static void* platform_open_file_dialog_thread(void *data)
-{
- struct open_dialog_args *args = data;
-
- FILE *f;
-
- char current_val[MAX_INPUT_LENGTH];
- string_copyn(current_val, args->buffer, MAX_INPUT_LENGTH);
-
- char file_filter[MAX_INPUT_LENGTH];
- file_filter[0] = 0;
- if (args->file_filter)
- snprintf(file_filter, MAX_INPUT_LENGTH, "--file-filter=\"%s\"", args->file_filter);
-
- char start_path[MAX_INPUT_LENGTH];
- start_path[0] = 0;
- if (args->start_path)
- snprintf(start_path, MAX_INPUT_LENGTH, "--filename=\"%s\"", args->start_path);
-
-
- char command[MAX_INPUT_LENGTH];
-
- if (args->type == OPEN_FILE)
- {
- snprintf(command, MAX_INPUT_LENGTH, "zenity --file-selection %s %s", file_filter, start_path);
- }
- else if (args->type == OPEN_DIRECTORY)
- {
- snprintf(command, MAX_INPUT_LENGTH, "zenity --file-selection --directory %s %s", file_filter, start_path);
- }
- else if (args->type == SAVE_FILE)
- {
- snprintf(command, MAX_INPUT_LENGTH, "zenity --file-selection --save --confirm-overwrite %s %s", file_filter, start_path);
- }
-
- f = popen(command, "r");
-
- char buffer[MAX_INPUT_LENGTH];
- char *result = fgets(buffer, MAX_INPUT_LENGTH, f);
-
- if (!result)
- return 0;
-
- // replace newlines with 0, we only want one file path
- s32 len = strlen(buffer);
- for (s32 x = 0; x < len; x++)
- {
- if (buffer[x] == '\n') buffer[x] = 0;
- }
-
- if (strcmp(buffer, current_val) != 0 && strcmp(buffer, "") != 0)
- {
- string_copyn(args->buffer, buffer, MAX_INPUT_LENGTH);
- s32 len = strlen(args->buffer);
- args->buffer[len] = 0;
- }
-
- return 0;
-}
-
-void *platform_open_file_dialog_block(void *arg)
-{
- thread thr = thread_start(platform_open_file_dialog_thread, arg);
- thread_join(&thr);
- mem_free(arg);
- return 0;
-}
-
-void platform_list_files_block(array *list, char *start_dir, array filters, bool recursive, memory_bucket *bucket, bool include_directories, bool *is_cancelled)
-{
- assert(list);
-
- s32 len = 0;
- char *matched_filter = 0;
-
- char *subdirname_buf;
- if (bucket)
- subdirname_buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH);
- else
- subdirname_buf = mem_alloc(MAX_INPUT_LENGTH);
-
- DIR *d;
- struct dirent *dir;
- d = opendir(start_dir);
- if (d) {
- set_active_directory(start_dir);
- while ((dir = readdir(d)) != NULL) {
- if (*is_cancelled) break;
- set_active_directory(start_dir);
-
- if (dir->d_type == DT_DIR)
- {
- if ((strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0))
- continue;
-
- if (include_directories)
- {
- if ((len = filter_matches(&filters, dir->d_name,
- &matched_filter)) && len != -1)
- {
- char *buf;
- if (bucket)
- buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH);
- else
- buf = mem_alloc(MAX_INPUT_LENGTH);
-
- //realpath(dir->d_name, buf);
- snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, dir->d_name);
-
- found_file f;
- f.path = buf;
-
- if (bucket)
- f.matched_filter = memory_bucket_reserve(bucket, len+1);
- else
- f.matched_filter = mem_alloc(len+1);
-
- string_copyn(f.matched_filter, matched_filter, len+1);
-
- mutex_lock(&list->mutex);
- array_push_size(list, &f, sizeof(found_file));
- mutex_unlock(&list->mutex);
- }
- }
-
- if (recursive)
- {
- string_copyn(subdirname_buf, start_dir, MAX_INPUT_LENGTH);
- string_appendn(subdirname_buf, dir->d_name, MAX_INPUT_LENGTH);
- string_appendn(subdirname_buf, "/", MAX_INPUT_LENGTH);
-
- // do recursive search
- platform_list_files_block(list, subdirname_buf, filters, recursive, bucket, include_directories, is_cancelled);
- }
- }
- // we handle DT_UNKNOWN for file systems that do not support type lookup.
- else if (dir->d_type == DT_REG || dir->d_type == DT_UNKNOWN)
- {
- // check if name matches pattern
- if ((len = filter_matches(&filters, dir->d_name,
- &matched_filter)) && len != -1)
- {
- char *buf;
- if (bucket)
- buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH);
- else
- buf = mem_alloc(MAX_INPUT_LENGTH);
-
- //realpath(dir->d_name, buf);
- snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, dir->d_name);
-
- found_file f;
- f.path = buf;
-
- if (bucket)
- f.matched_filter = memory_bucket_reserve(bucket, len+1);
- else
- f.matched_filter = mem_alloc(len+1);
-
- string_copyn(f.matched_filter, matched_filter, len+1);
-
- mutex_lock(&list->mutex);
- array_push_size(list, &f, sizeof(found_file));
- mutex_unlock(&list->mutex);
-
- }
- }
- }
- closedir(d);
- }
-
- if (!bucket)
- mem_free(subdirname_buf);
-}
-
-char *platform_get_full_path(char *file)
-{
- char *buf = mem_alloc(PATH_MAX);
- buf[0] = 0;
-
- char *result = realpath(file, buf);
-
- if (!result)
- {
- buf[0] = 0;
- return buf;
- }
-
- return buf;
-}
-
-inline u64 string_to_u64(char *str)
-{
- return (u64)strtoull(str, 0, 10);
-}
-
-inline u32 string_to_u32(char *str)
-{
- return (u32)strtoul(str, 0, 10);
-}
-
-inline u16 string_to_u16(char *str)
-{
- return (u16)strtoul(str, 0, 10);
-}
-
-inline u8 string_to_u8(char *str)
-{
- return (u8)strtoul(str, 0, 10);
-}
-
-inline s64 string_to_s64(char *str)
-{
- return (s64)strtoll(str, 0, 10);
-}
-
-inline s32 string_to_s32(char *str)
-{
- return (u32)strtol(str, 0, 10);
-}
-
-inline s16 string_to_s16(char *str)
-{
- return (s16)strtol(str, 0, 10);
-}
-
-inline s8 string_to_s8(char *str)
-{
- return (s8)strtol(str, 0, 10);
-}
-
-inline void platform_open_url(char *url)
-{
- char buffer[MAX_INPUT_LENGTH];
- snprintf(buffer, MAX_INPUT_LENGTH, "xdg-open %s", url);
- platform_run_command(buffer);
-}
-
-inline void platform_run_command(char *command)
-{
- s32 result = system(command);
-}
-
-void platform_set_icon(platform_window *window, image *img)
-{
- s32 w = img->width;
- s32 h = img->height;
-
- s32 nelements = (w * h) + 2;
-
- unsigned long data[nelements];
- int i = 0;
- (data)[i++] = w;
- (data)[i++] = h;
-
- for (s32 y = 0; y < h; y++)
- {
- for (s32 x = 0; x < w; x++)
- {
- s32 *pixel = (s32*)(&((data)[i++]));
-
- s32 img_pixel = *(((s32*)img->data+(x+(y*w))));
-
- // 0xAABBGGRR
- s32 a = (img_pixel>>24) & 0x000000FF;
- s32 b = (img_pixel>>16) & 0x000000FF;
- s32 g = (img_pixel>> 8) & 0x000000FF;
- s32 r = (img_pixel>> 0) & 0x000000FF;
-
- //s32 c = (r << 24) | (g << 16) | (b << 8) | (a << 0);
- s32 c = (a << 24) | (r << 16) | (g << 8) | (b << 0);
- *pixel = c;
- }
- }
-
- Atom property = XInternAtom(window->display, "_NET_WM_ICON", 0);
- Atom cardinal = XInternAtom(window->display, "CARDINAL", False);
-
- int result = XChangeProperty(window->display, window->window,
- property, cardinal, 32, PropModeReplace,
- (unsigned char *)data, nelements);
-}
diff --git a/src/linux/thread.c b/src/linux/thread.c
deleted file mode 100644
index b6295ef..0000000
--- a/src/linux/thread.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-* BSD 2-Clause “Simplified” License
-* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com
-* All rights reserved.
-*/
-
-// stop gcc from reporting implicit declaration warning..
-extern long int syscall (long int __sysno, ...);
-extern int pthread_tryjoin_np(pthread_t thread, void **retval);
-
-thread thread_start(void *(*start_routine) (void *), void *arg)
-{
- thread result;
- result.valid = false;
-
- pthread_attr_t attr;
- int attr_init_result = pthread_attr_init(&attr);
- if (attr_init_result)
- return result;
-
- int start_thread_result = pthread_create(&result.thread, &attr, start_routine, arg);
- if (start_thread_result)
- {
- pthread_attr_destroy(&attr);
- return result;
- }
-
- result.valid = true;
- pthread_attr_destroy(&attr);
-
- return result;
-}
-
-inline void thread_detach(thread *thread)
-{
- if (thread->valid)
- {
- pthread_detach(thread->thread);
- }
-}
-
-inline void thread_join(thread *thread)
-{
- if (thread->valid)
- {
- void *retval;
- pthread_join(thread->thread, &retval);
- }
-}
-
-bool thread_tryjoin(thread *thread)
-{
- if (thread->valid)
- {
- void *retval;
- bool thread_joined = !pthread_tryjoin_np(thread->thread, &retval);
- return thread_joined;
- }
- return false;
-}
-
-inline void thread_stop(thread *thread)
-{
- if (thread->valid)
- {
- pthread_cancel(thread->thread);
- }
-}
-
-mutex mutex_create()
-{
- mutex result;
-
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
-
- pthread_mutex_init(&result.mutex, &attr);
-
- pthread_mutexattr_destroy(&attr);
-
- return result;
-}
-
-mutex mutex_create_recursive()
-{
- mutex result;
-
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-
- pthread_mutex_init(&result.mutex, &attr);
-
- pthread_mutexattr_destroy(&attr);
-
- return result;
-}
-
-inline void mutex_lock(mutex *mutex)
-{
- pthread_mutex_lock(&mutex->mutex);
-}
-
-inline bool mutex_trylock(mutex *mutex)
-{
- return !pthread_mutex_trylock(&mutex->mutex);
-}
-
-inline void mutex_unlock(mutex *mutex)
-{
- pthread_mutex_unlock(&mutex->mutex);
-}
-
-inline void mutex_destroy(mutex *mutex)
-{
- mutex_unlock(mutex);
- pthread_mutex_destroy(&mutex->mutex);
-}
-
-inline u32 thread_get_id()
-{
- return (u32)syscall(__NR_gettid);
-}
-
-inline void thread_sleep(u64 microseconds)
-{
- usleep(microseconds);
-}