diff options
| author | quou <quou@disroot.org> | 2024-12-15 22:48:12 +1100 | 
|---|---|---|
| committer | quou <quou@disroot.org> | 2024-12-15 22:48:12 +1100 | 
| commit | 1b8008c41a04ceeb3ac4970f469ce9420ec29241 (patch) | |
| tree | e09c89f5e0b0f03709da75a7e5c338a5108166ce /app.cpp | |
| parent | b9550388afdf53b1efc858cd568181217b060897 (diff) | |
Windowing + keyboard and mouse input
Diffstat (limited to 'app.cpp')
| -rw-r--r-- | app.cpp | 300 | 
1 files changed, 300 insertions, 0 deletions
| @@ -0,0 +1,300 @@ +#include "app.hpp" + +extern "C" { +#include "memory.h" +} + +#ifdef plat_x11 +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include <stdlib.h> + +Key key_from_xkey(unsigned key) { +	switch (key) { +		case 0x61:           return key_A; +		case 0x62:           return key_B; +		case 0x63:           return key_C; +		case 0x64:           return key_D; +		case 0x65:           return key_E; +		case 0x66:           return key_F; +		case 0x67:           return key_G; +		case 0x68:           return key_H; +		case 0x69:           return key_I; +		case 0x6A:           return key_J; +		case 0x6B:           return key_K; +		case 0x6C:           return key_L; +		case 0x6D:           return key_M; +		case 0x6E:           return key_N; +		case 0x6F:           return key_O; +		case 0x70:           return key_P; +		case 0x71:           return key_Q; +		case 0x72:           return key_R; +		case 0x73:           return key_S; +		case 0x74:           return key_T; +		case 0x75:           return key_U; +		case 0x76:           return key_V; +		case 0x77:           return key_W; +		case 0x78:           return key_X; +		case 0x79:           return key_Y; +		case 0x7A:           return key_Z; +		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_Down:        return key_down; +		case XK_Left:        return key_left; +		case XK_Right:       return key_right; +		case XK_Up:          return key_up; +		case XK_Escape:      return key_escape; +		case XK_Return:      return key_return; +		case XK_BackSpace:   return key_backspace; +		case XK_Linefeed:    return key_return; +		case XK_Tab:         return key_tab; +		case XK_Delete:      return key_delete; +		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_Shift_L:     return key_shift; +		case XK_Shift_R:     return key_shift; +		case XK_Control_L:   return key_control; +		case XK_Control_R:   return key_control; +		case XK_Super_L:     return key_super; +		case XK_Super_R:     return key_super; +		case XK_Alt_L:       return key_alt; +		case XK_Alt_R:       return key_alt; +		case XK_space:       return key_space; +		case XK_period:      return key_period; +		case XK_0:           return key_0; +		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; +		default:             return key_unknown; +	} +} + +struct App_Internal { +	Display* d; +	Window wi; +	Atom wm_delete; + +	void init(App* app, const char* name) { +		const int default_w = 1920; +		const int default_h = 1080; +		XWindowAttributes wa; +		XSetWindowAttributes attribs = { +			.event_mask = +				ExposureMask | +				KeyPressMask | +				KeyReleaseMask | +				ButtonPressMask | +				ButtonReleaseMask | +				PointerMotionMask +		}; +		Window root; +		Visual* v; +		d = XOpenDisplay(0); +		wm_delete = XInternAtom( +			d, +			"WM_DELETE_WINDOW", +			0 +		); +		root = DefaultRootWindow(d); +		v = XDefaultVisual(d, 0); +		wi = XCreateWindow( +			d, +			root, +			0, +			0, +			default_w, +			default_h, +			0, +			0, +			InputOutput, +			v, +			CWEventMask, +			&attribs +		); +		XSetWMProtocols(d, wi, &wm_delete, 1); +		XStoreName(d, wi, name); +		XMapRaised(d, wi); +		XGetWindowAttributes(d, wi, &wa); +		app->w = wa.width; +		app->h = wa.height; +	} + +	void begin(App* app) { +		while (XPending(d)) { +			XEvent e; +			KeySym sym; +			Key key; +			int btn; +			XNextEvent(d, &e); +			switch (e.type) { +				case ClientMessage: +					if ( +						(Atom)e.xclient.data.l[0] == +						wm_delete +					) { +						app->running = 0; +					} +					break; +				case MotionNotify: +					app->mx = e.xmotion.x; +					app->my = e.xmotion.y; +					break; +				case ButtonPress: +					switch (e.xbutton.button) { +						case 1: +						case 2: +						case 3: +							app->mbtn_states[e.xbutton.button - 1] |=  +								key_state_pressed | +								key_state_just_pressed; +							break; +						case 4: +							app->scrolly++; +							break; +						case 5: +							app->scrolly--; +							break; +						case 6: +							app->scrollx++; +							break; +						case 7: +							app->scrollx--; +							break; +					} +					break; +				case ButtonRelease: +					switch (e.xbutton.button) { +						case 1: +						case 2: +						case 3: +							btn = e.xbutton.button - 1; +							app->mbtn_states[btn] &= ~key_state_pressed; +							app->mbtn_states[btn] |= key_state_just_released; +							break; +						case 4: +							app->scrolly++; +							break; +						case 5: +							app->scrolly--; +							break; +						case 6: +							app->scrollx++; +							break; +						case 7: +							app->scrollx--; +							break; +					} +					break; +				case KeyPress: +					sym = XLookupKeysym(&e.xkey, 0); +					key = key_from_xkey(sym); +					app->key_states[key] |= +						key_state_pressed | +						key_state_just_pressed; +					break; +				case KeyRelease: +					sym = XLookupKeysym(&e.xkey, 0); +					key = key_from_xkey(sym); +					app->key_states[key] &= ~key_state_pressed; +					app->key_states[key] |= key_state_just_released; +					break; +			} +		} +	} + +	void end(App* app) { +		(void)app; +	} +}; + +#endif + +App* App::create(const char* name) { +	App* app; +	App_Internal* i; +	char* mem = (char*)malloc(app_memory_size); +	Arena* a = (Arena*)mem; +	mem += sizeof *a; +	init_arena(a, mem, app_memory_size - sizeof *a); +	app = (App*)arena_alloc(a, sizeof *app + sizeof *i); +	app->running = 0; +	app->arena = a; +	i = (App_Internal*)&app[1]; +	i->init(app, name); +	return app; +} + +void App::destroy() { +	free(arena); +} + +void App::begin() { +	int j; +	App_Internal* i = (App_Internal*)&this[1]; +	for (j = 0; j < key_count; j++) +		key_states[j] &= ~( +			key_state_just_pressed | key_state_just_released +		); +	for (j = 0; j < mbtn_count; j++) +		mbtn_states[j] &= ~( +			key_state_just_pressed | key_state_just_released +		); +	i->begin(this); +} + +void App::end() { +	App_Internal* i = (App_Internal*)&this[1]; +	i->end(this); +} + +Key_State App::ks(Key k) { +	return (Key_State)key_states[k]; +} + +Key_State App::ms(Mbtn k) { +	return (Key_State)mbtn_states[k]; +} + +bool App::kp(Key k) { +	return key_states[k] & key_state_pressed; +} + +bool App::kjp(Key k) { +	return key_states[k] & key_state_just_pressed; +} + +bool App::kjr(Key k) { +	return key_states[k] & key_state_just_released; +} + +bool App::mp(Mbtn b) { +	return mbtn_states[b] & key_state_pressed; +} + +bool App::mjp(Mbtn b) { +	return mbtn_states[b] & key_state_just_pressed; +} + +bool App::mjr(Mbtn b) { +	return mbtn_states[b] & key_state_just_released; +} |