433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "kinc/graphics4/graphics.h"
 | |
| #include <kinc/display.h>
 | |
| #include <kinc/input/gamepad.h>
 | |
| #include <kinc/input/keyboard.h>
 | |
| #include <kinc/input/mouse.h>
 | |
| #include <kinc/input/pen.h>
 | |
| #include <kinc/log.h>
 | |
| #include <kinc/system.h>
 | |
| #include <kinc/video.h>
 | |
| #include <kinc/window.h>
 | |
| 
 | |
| #ifndef __FreeBSD__
 | |
| #include "gamepad.h"
 | |
| #endif
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <limits.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include <pwd.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/types.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include "funcs.h"
 | |
| 
 | |
| bool kinc_internal_handle_messages() {
 | |
| 	if (!procs.handle_messages()) {
 | |
| 		return false;
 | |
| 	}
 | |
| #ifndef __FreeBSD__
 | |
| 	kinc_linux_updateHIDGamepads();
 | |
| #endif // TODO: add #else with proper call to FreeBSD backend impl
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| const char *kinc_system_id() {
 | |
| 	return "Linux";
 | |
| }
 | |
| 
 | |
| void kinc_set_keep_screen_on(bool on) {}
 | |
| 
 | |
| void kinc_keyboard_show() {}
 | |
| 
 | |
| void kinc_keyboard_hide() {}
 | |
| 
 | |
| bool kinc_keyboard_active() {
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| void kinc_load_url(const char *url) {
 | |
| #define MAX_COMMAND_BUFFER_SIZE 256
 | |
| #define HTTP "http://"
 | |
| #define HTTPS "https://"
 | |
| 	if (strncmp(url, HTTP, sizeof(HTTP) - 1) == 0 || strncmp(url, HTTPS, sizeof(HTTPS) - 1) == 0) {
 | |
| 		char openUrlCommand[MAX_COMMAND_BUFFER_SIZE];
 | |
| 		snprintf(openUrlCommand, MAX_COMMAND_BUFFER_SIZE, "xdg-open %s", url);
 | |
| 		int err = system(openUrlCommand);
 | |
| 		if (err != 0) {
 | |
| 			kinc_log(KINC_LOG_LEVEL_WARNING, "Error opening url %s", url);
 | |
| 		}
 | |
| 	}
 | |
| #undef HTTPS
 | |
| #undef HTTP
 | |
| #undef MAX_COMMAND_BUFFER_SIZE
 | |
| }
 | |
| 
 | |
| void kinc_vibrate(int ms) {}
 | |
| 
 | |
| const char *kinc_language() {
 | |
| 	return "en";
 | |
| }
 | |
| 
 | |
| static char save[2000];
 | |
| static bool saveInitialized = false;
 | |
| 
 | |
| const char *kinc_internal_save_path() {
 | |
| 	// first check for an existing directory in $HOME
 | |
| 	// if one exists, use it, else create one in $XDG_DATA_HOME
 | |
| 	// See: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
 | |
| 	if (!saveInitialized) {
 | |
| 		const char *homedir;
 | |
| 
 | |
| 		if ((homedir = getenv("HOME")) == NULL) {
 | |
| 			homedir = getpwuid(getuid())->pw_dir;
 | |
| 		}
 | |
| 
 | |
| 		strcpy(save, homedir);
 | |
| 		strcat(save, "/.");
 | |
| 		strcat(save, kinc_application_name());
 | |
| 		strcat(save, "/");
 | |
| 		struct stat st;
 | |
| 		if (stat(save, &st) == 0) {
 | |
| 			// use existing folder in $HOME
 | |
| 		}
 | |
| 		else {
 | |
| 			// use XDG folder
 | |
| 			const char *data_home;
 | |
| 			if ((data_home = getenv("XDG_DATA_HOME")) == NULL) {
 | |
| 				// $XDG_DATA_HOME is not defined, fall back to the default, $HOME/.local/share
 | |
| 				strcpy(save, homedir);
 | |
| 				strcat(save, "/.local/share/");
 | |
| 			}
 | |
| 			else {
 | |
| 				// use $XDG_DATA_HOME
 | |
| 				strcpy(save, data_home);
 | |
| 				if (data_home[strlen(data_home) - 1] != '/') {
 | |
| 					strcat(save, "/");
 | |
| 				}
 | |
| 			}
 | |
| 			strcat(save, kinc_application_name());
 | |
| 			strcat(save, "/");
 | |
| 			int res = mkdir(save, 0700);
 | |
| 			if (res != 0 && errno != EEXIST) {
 | |
| 				kinc_log(KINC_LOG_LEVEL_ERROR, "Could not create save directory '%s'. Error %d", save, errno);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		saveInitialized = true;
 | |
| 	}
 | |
| 	return save;
 | |
| }
 | |
| 
 | |
| static const char *videoFormats[] = {"ogv", NULL};
 | |
| 
 | |
| const char **kinc_video_formats() {
 | |
| 	return videoFormats;
 | |
| }
 | |
| 
 | |
| #include <sys/time.h>
 | |
| #include <time.h>
 | |
| 
 | |
| double kinc_frequency(void) {
 | |
| 	return 1000000.0;
 | |
| }
 | |
| 
 | |
| static struct timeval start;
 | |
| 
 | |
| kinc_ticks_t kinc_timestamp(void) {
 | |
| 	struct timeval now;
 | |
| 	gettimeofday(&now, NULL);
 | |
| 	now.tv_sec -= start.tv_sec;
 | |
| 	now.tv_usec -= start.tv_usec;
 | |
| 	return (kinc_ticks_t)now.tv_sec * 1000000 + (kinc_ticks_t)now.tv_usec;
 | |
| }
 | |
| 
 | |
| void kinc_login() {}
 | |
| 
 | |
| void kinc_unlock_achievement(int id) {}
 | |
| 
 | |
| void kinc_linux_init_procs();
 | |
| 
 | |
| #ifdef KINC_KONG
 | |
| void kong_init(void);
 | |
| #endif
 | |
| 
 | |
| int kinc_init(const char *name, int width, int height, kinc_window_options_t *win, kinc_framebuffer_options_t *frame) {
 | |
| #ifndef __FreeBSD__
 | |
| 	kinc_linux_initHIDGamepads();
 | |
| #endif // TODO: add #else with proper call to FreeBSD backend impl
 | |
| 
 | |
| 	gettimeofday(&start, NULL);
 | |
| 	kinc_linux_init_procs();
 | |
| 	kinc_display_init();
 | |
| 
 | |
| 	kinc_set_application_name(name);
 | |
| 
 | |
| 	kinc_g4_internal_init();
 | |
| 
 | |
| 	kinc_window_options_t defaultWin;
 | |
| 	if (win == NULL) {
 | |
| 		kinc_window_options_set_defaults(&defaultWin);
 | |
| 		win = &defaultWin;
 | |
| 	}
 | |
| 	kinc_framebuffer_options_t defaultFrame;
 | |
| 	if (frame == NULL) {
 | |
| 		kinc_framebuffer_options_set_defaults(&defaultFrame);
 | |
| 		frame = &defaultFrame;
 | |
| 	}
 | |
| 	win->width = width;
 | |
| 	win->height = height;
 | |
| 	if (win->title == NULL) {
 | |
| 		win->title = name;
 | |
| 	}
 | |
| 
 | |
| 	int window = kinc_window_create(win, frame);
 | |
| #ifdef KINC_KONG
 | |
| 	kong_init();
 | |
| #endif
 | |
| 	return window;
 | |
| }
 | |
| 
 | |
| void kinc_internal_shutdown() {
 | |
| 	kinc_g4_internal_destroy();
 | |
| #ifndef __FreeBSD__
 | |
| 	kinc_linux_closeHIDGamepads();
 | |
| #endif // TODO: add #else with proper call to FreeBSD backend impl
 | |
| 	procs.shutdown();
 | |
| 	kinc_internal_shutdown_callback();
 | |
| }
 | |
| 
 | |
| #ifndef KINC_NO_MAIN
 | |
| int main(int argc, char **argv) {
 | |
| 	return kickstart(argc, argv);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void kinc_copy_to_clipboard(const char *text) {
 | |
| 	procs.copy_to_clipboard(text);
 | |
| }
 | |
| 
 | |
| static int parse_number_at_end_of_line(char *line) {
 | |
| 	char *end = &line[strlen(line) - 2];
 | |
| 	int num = 0;
 | |
| 	int multi = 1;
 | |
| 	while (*end >= '0' && *end <= '9') {
 | |
| 		num += (*end - '0') * multi;
 | |
| 		multi *= 10;
 | |
| 		--end;
 | |
| 	}
 | |
| 	return num;
 | |
| }
 | |
| 
 | |
| int kinc_cpu_cores(void) {
 | |
| 	char line[1024];
 | |
| 	FILE *file = fopen("/proc/cpuinfo", "r");
 | |
| 
 | |
| 	if (file != NULL) {
 | |
| 		int cores[1024];
 | |
| 		memset(cores, 0, sizeof(cores));
 | |
| 
 | |
| 		int cpu_count = 0;
 | |
| 		int physical_id = -1;
 | |
| 		int per_cpu_cores = -1;
 | |
| 		int processor_count = 0;
 | |
| 
 | |
| 		while (fgets(line, sizeof(line), file)) {
 | |
| 			if (strncmp(line, "processor", 9) == 0) {
 | |
| 				++processor_count;
 | |
| 				if (physical_id >= 0 && per_cpu_cores > 0) {
 | |
| 					if (physical_id + 1 > cpu_count) {
 | |
| 						cpu_count = physical_id + 1;
 | |
| 					}
 | |
| 					cores[physical_id] = per_cpu_cores;
 | |
| 					physical_id = -1;
 | |
| 					per_cpu_cores = -1;
 | |
| 				}
 | |
| 			}
 | |
| 			else if (strncmp(line, "physical id", 11) == 0) {
 | |
| 				physical_id = parse_number_at_end_of_line(line);
 | |
| 			}
 | |
| 			else if (strncmp(line, "cpu cores", 9) == 0) {
 | |
| 				per_cpu_cores = parse_number_at_end_of_line(line);
 | |
| 			}
 | |
| 		}
 | |
| 		fclose(file);
 | |
| 
 | |
| 		if (physical_id >= 0 && per_cpu_cores > 0) {
 | |
| 			if (physical_id + 1 > cpu_count) {
 | |
| 				cpu_count = physical_id + 1;
 | |
| 			}
 | |
| 			cores[physical_id] = per_cpu_cores;
 | |
| 		}
 | |
| 
 | |
| 		int proper_cpu_count = 0;
 | |
| 		for (int i = 0; i < cpu_count; ++i) {
 | |
| 			proper_cpu_count += cores[i];
 | |
| 		}
 | |
| 
 | |
| 		if (proper_cpu_count > 0) {
 | |
| 			return proper_cpu_count;
 | |
| 		}
 | |
| 		else {
 | |
| 			return processor_count == 0 ? 1 : processor_count;
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		return 1;
 | |
| 	};
 | |
| }
 | |
| 
 | |
| int kinc_hardware_threads(void) {
 | |
| #ifndef __FreeBSD__
 | |
| 	return sysconf(_SC_NPROCESSORS_ONLN);
 | |
| #else
 | |
| 	return kinc_cpu_cores();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #include <xkbcommon/xkbcommon.h>
 | |
| 
 | |
| int xkb_to_kinc(xkb_keysym_t symbol) {
 | |
| #define KEY(xkb, kinc)                                                                                                                                         \
 | |
| 	case xkb:                                                                                                                                                  \
 | |
| 		return kinc;
 | |
| 	switch (symbol) {
 | |
| 		KEY(XKB_KEY_Right, KINC_KEY_RIGHT)
 | |
| 		KEY(XKB_KEY_Left, KINC_KEY_LEFT)
 | |
| 		KEY(XKB_KEY_Up, KINC_KEY_UP)
 | |
| 		KEY(XKB_KEY_Down, KINC_KEY_DOWN)
 | |
| 		KEY(XKB_KEY_space, KINC_KEY_SPACE)
 | |
| 		KEY(XKB_KEY_BackSpace, KINC_KEY_BACKSPACE)
 | |
| 		KEY(XKB_KEY_Tab, KINC_KEY_TAB)
 | |
| 		KEY(XKB_KEY_Return, KINC_KEY_RETURN)
 | |
| 		KEY(XKB_KEY_Shift_L, KINC_KEY_SHIFT)
 | |
| 		KEY(XKB_KEY_Shift_R, KINC_KEY_SHIFT)
 | |
| 		KEY(XKB_KEY_Control_L, KINC_KEY_CONTROL)
 | |
| 		KEY(XKB_KEY_Control_R, KINC_KEY_CONTROL)
 | |
| 		KEY(XKB_KEY_Alt_L, KINC_KEY_ALT)
 | |
| 		KEY(XKB_KEY_Alt_R, KINC_KEY_ALT)
 | |
| 		KEY(XKB_KEY_Delete, KINC_KEY_DELETE)
 | |
| 		KEY(XKB_KEY_comma, KINC_KEY_COMMA)
 | |
| 		KEY(XKB_KEY_period, KINC_KEY_PERIOD)
 | |
| 		KEY(XKB_KEY_bracketleft, KINC_KEY_OPEN_BRACKET)
 | |
| 		KEY(XKB_KEY_bracketright, KINC_KEY_CLOSE_BRACKET)
 | |
| 		KEY(XKB_KEY_braceleft, KINC_KEY_OPEN_CURLY_BRACKET)
 | |
| 		KEY(XKB_KEY_braceright, KINC_KEY_CLOSE_CURLY_BRACKET)
 | |
| 		KEY(XKB_KEY_parenleft, KINC_KEY_OPEN_PAREN)
 | |
| 		KEY(XKB_KEY_parenright, KINC_KEY_CLOSE_PAREN)
 | |
| 		KEY(XKB_KEY_backslash, KINC_KEY_BACK_SLASH)
 | |
| 		KEY(XKB_KEY_apostrophe, KINC_KEY_QUOTE)
 | |
| 		KEY(XKB_KEY_colon, KINC_KEY_COLON)
 | |
| 		KEY(XKB_KEY_semicolon, KINC_KEY_SEMICOLON)
 | |
| 		KEY(XKB_KEY_minus, KINC_KEY_HYPHEN_MINUS)
 | |
| 		KEY(XKB_KEY_underscore, KINC_KEY_UNDERSCORE)
 | |
| 		KEY(XKB_KEY_slash, KINC_KEY_SLASH)
 | |
| 		KEY(XKB_KEY_bar, KINC_KEY_PIPE)
 | |
| 		KEY(XKB_KEY_question, KINC_KEY_QUESTIONMARK)
 | |
| 		KEY(XKB_KEY_less, KINC_KEY_LESS_THAN)
 | |
| 		KEY(XKB_KEY_greater, KINC_KEY_GREATER_THAN)
 | |
| 		KEY(XKB_KEY_asterisk, KINC_KEY_ASTERISK)
 | |
| 		KEY(XKB_KEY_ampersand, KINC_KEY_AMPERSAND)
 | |
| 		KEY(XKB_KEY_asciicircum, KINC_KEY_CIRCUMFLEX)
 | |
| 		KEY(XKB_KEY_percent, KINC_KEY_PERCENT)
 | |
| 		KEY(XKB_KEY_dollar, KINC_KEY_DOLLAR)
 | |
| 		KEY(XKB_KEY_numbersign, KINC_KEY_HASH)
 | |
| 		KEY(XKB_KEY_at, KINC_KEY_AT)
 | |
| 		KEY(XKB_KEY_exclam, KINC_KEY_EXCLAMATION)
 | |
| 		KEY(XKB_KEY_equal, KINC_KEY_EQUALS)
 | |
| 		KEY(XKB_KEY_plus, KINC_KEY_ADD)
 | |
| 		KEY(XKB_KEY_quoteleft, KINC_KEY_BACK_QUOTE)
 | |
| 		KEY(XKB_KEY_quotedbl, KINC_KEY_DOUBLE_QUOTE)
 | |
| 		KEY(XKB_KEY_asciitilde, KINC_KEY_TILDE)
 | |
| 		KEY(XKB_KEY_Pause, KINC_KEY_PAUSE)
 | |
| 		KEY(XKB_KEY_Scroll_Lock, KINC_KEY_SCROLL_LOCK)
 | |
| 		KEY(XKB_KEY_Home, KINC_KEY_HOME)
 | |
| 		KEY(XKB_KEY_Page_Up, KINC_KEY_PAGE_UP)
 | |
| 		KEY(XKB_KEY_Page_Down, KINC_KEY_PAGE_DOWN)
 | |
| 		KEY(XKB_KEY_End, KINC_KEY_END)
 | |
| 		KEY(XKB_KEY_Insert, KINC_KEY_INSERT)
 | |
| 		KEY(XKB_KEY_KP_Enter, KINC_KEY_RETURN)
 | |
| 		KEY(XKB_KEY_KP_Multiply, KINC_KEY_MULTIPLY)
 | |
| 		KEY(XKB_KEY_KP_Add, KINC_KEY_ADD)
 | |
| 		KEY(XKB_KEY_KP_Subtract, KINC_KEY_SUBTRACT)
 | |
| 		KEY(XKB_KEY_KP_Decimal, KINC_KEY_DECIMAL)
 | |
| 		KEY(XKB_KEY_KP_Divide, KINC_KEY_DIVIDE)
 | |
| 		KEY(XKB_KEY_KP_0, KINC_KEY_NUMPAD_0)
 | |
| 		KEY(XKB_KEY_KP_1, KINC_KEY_NUMPAD_1)
 | |
| 		KEY(XKB_KEY_KP_2, KINC_KEY_NUMPAD_2)
 | |
| 		KEY(XKB_KEY_KP_3, KINC_KEY_NUMPAD_3)
 | |
| 		KEY(XKB_KEY_KP_4, KINC_KEY_NUMPAD_4)
 | |
| 		KEY(XKB_KEY_KP_5, KINC_KEY_NUMPAD_5)
 | |
| 		KEY(XKB_KEY_KP_6, KINC_KEY_NUMPAD_6)
 | |
| 		KEY(XKB_KEY_KP_7, KINC_KEY_NUMPAD_7)
 | |
| 		KEY(XKB_KEY_KP_8, KINC_KEY_NUMPAD_8)
 | |
| 		KEY(XKB_KEY_KP_9, KINC_KEY_NUMPAD_9)
 | |
| 		KEY(XKB_KEY_KP_Insert, KINC_KEY_INSERT)
 | |
| 		KEY(XKB_KEY_KP_Delete, KINC_KEY_DELETE)
 | |
| 		KEY(XKB_KEY_KP_End, KINC_KEY_END)
 | |
| 		KEY(XKB_KEY_KP_Home, KINC_KEY_HOME)
 | |
| 		KEY(XKB_KEY_KP_Left, KINC_KEY_LEFT)
 | |
| 		KEY(XKB_KEY_KP_Up, KINC_KEY_UP)
 | |
| 		KEY(XKB_KEY_KP_Right, KINC_KEY_RIGHT)
 | |
| 		KEY(XKB_KEY_KP_Down, KINC_KEY_DOWN)
 | |
| 		KEY(XKB_KEY_KP_Page_Up, KINC_KEY_PAGE_UP)
 | |
| 		KEY(XKB_KEY_KP_Page_Down, KINC_KEY_PAGE_DOWN)
 | |
| 		KEY(XKB_KEY_Menu, KINC_KEY_CONTEXT_MENU)
 | |
| 		KEY(XKB_KEY_a, KINC_KEY_A)
 | |
| 		KEY(XKB_KEY_b, KINC_KEY_B)
 | |
| 		KEY(XKB_KEY_c, KINC_KEY_C)
 | |
| 		KEY(XKB_KEY_d, KINC_KEY_D)
 | |
| 		KEY(XKB_KEY_e, KINC_KEY_E)
 | |
| 		KEY(XKB_KEY_f, KINC_KEY_F)
 | |
| 		KEY(XKB_KEY_g, KINC_KEY_G)
 | |
| 		KEY(XKB_KEY_h, KINC_KEY_H)
 | |
| 		KEY(XKB_KEY_i, KINC_KEY_I)
 | |
| 		KEY(XKB_KEY_j, KINC_KEY_J)
 | |
| 		KEY(XKB_KEY_k, KINC_KEY_K)
 | |
| 		KEY(XKB_KEY_l, KINC_KEY_L)
 | |
| 		KEY(XKB_KEY_m, KINC_KEY_M)
 | |
| 		KEY(XKB_KEY_n, KINC_KEY_N)
 | |
| 		KEY(XKB_KEY_o, KINC_KEY_O)
 | |
| 		KEY(XKB_KEY_p, KINC_KEY_P)
 | |
| 		KEY(XKB_KEY_q, KINC_KEY_Q)
 | |
| 		KEY(XKB_KEY_r, KINC_KEY_R)
 | |
| 		KEY(XKB_KEY_s, KINC_KEY_S)
 | |
| 		KEY(XKB_KEY_t, KINC_KEY_T)
 | |
| 		KEY(XKB_KEY_u, KINC_KEY_U)
 | |
| 		KEY(XKB_KEY_v, KINC_KEY_V)
 | |
| 		KEY(XKB_KEY_w, KINC_KEY_W)
 | |
| 		KEY(XKB_KEY_x, KINC_KEY_X)
 | |
| 		KEY(XKB_KEY_y, KINC_KEY_Y)
 | |
| 		KEY(XKB_KEY_z, KINC_KEY_Z)
 | |
| 		KEY(XKB_KEY_1, KINC_KEY_1)
 | |
| 		KEY(XKB_KEY_2, KINC_KEY_2)
 | |
| 		KEY(XKB_KEY_3, KINC_KEY_3)
 | |
| 		KEY(XKB_KEY_4, KINC_KEY_4)
 | |
| 		KEY(XKB_KEY_5, KINC_KEY_5)
 | |
| 		KEY(XKB_KEY_6, KINC_KEY_6)
 | |
| 		KEY(XKB_KEY_7, KINC_KEY_7)
 | |
| 		KEY(XKB_KEY_8, KINC_KEY_8)
 | |
| 		KEY(XKB_KEY_9, KINC_KEY_9)
 | |
| 		KEY(XKB_KEY_0, KINC_KEY_0)
 | |
| 		KEY(XKB_KEY_Escape, KINC_KEY_ESCAPE)
 | |
| 		KEY(XKB_KEY_F1, KINC_KEY_F1)
 | |
| 		KEY(XKB_KEY_F2, KINC_KEY_F2)
 | |
| 		KEY(XKB_KEY_F3, KINC_KEY_F3)
 | |
| 		KEY(XKB_KEY_F4, KINC_KEY_F4)
 | |
| 		KEY(XKB_KEY_F5, KINC_KEY_F5)
 | |
| 		KEY(XKB_KEY_F6, KINC_KEY_F6)
 | |
| 		KEY(XKB_KEY_F7, KINC_KEY_F7)
 | |
| 		KEY(XKB_KEY_F8, KINC_KEY_F8)
 | |
| 		KEY(XKB_KEY_F9, KINC_KEY_F9)
 | |
| 		KEY(XKB_KEY_F10, KINC_KEY_F10)
 | |
| 		KEY(XKB_KEY_F11, KINC_KEY_F11)
 | |
| 		KEY(XKB_KEY_F12, KINC_KEY_F12)
 | |
| 	default:
 | |
| 		return KINC_KEY_UNKNOWN;
 | |
| 	}
 | |
| #undef KEY
 | |
| } |