|
|
452870 |
|
|
|
452870 |
#include "app.h"
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
int appInit(App *app) {
|
|
|
452870 |
LOGDBG("app: init");
|
|
|
843e7a |
app->run = 0;
|
|
|
061fcf |
app->x = app->y = app->w = app->h = 0;
|
|
|
843e7a |
app->irx = app->iry = app->irw = app->irh = 0;
|
|
|
452870 |
|
|
|
452870 |
LOGDBG("app: init: connect to xcb");
|
|
|
452870 |
app->xcb = xcb_connect(NULL, NULL);
|
|
|
452870 |
if (!app->xcb)
|
|
|
452870 |
return LOGERR("app: init: cannot connect to xcb");
|
|
|
452870 |
|
|
|
452870 |
LOGDBG("app: init: get screen");
|
|
|
452870 |
app->screen = xcb_setup_roots_iterator(xcb_get_setup(app->xcb)).data;
|
|
|
452870 |
if (app->screen) {
|
|
|
452870 |
LOGDBG("app: init: create window");
|
|
|
061fcf |
|
|
|
061fcf |
app->x = 0;
|
|
|
061fcf |
app->w = app->screen->width_in_pixels;
|
|
|
061fcf |
app->h = app->screen->height_in_pixels/4;
|
|
|
061fcf |
app->y = app->screen->height_in_pixels - app->h;
|
|
|
061fcf |
|
|
|
061fcf |
#ifdef NOBORDER
|
|
|
061fcf |
int noborder = 1;
|
|
|
061fcf |
#else
|
|
|
061fcf |
int noborder = 0;
|
|
|
061fcf |
#endif
|
|
|
061fcf |
|
|
|
452870 |
app->win = xcb_generate_id(app->xcb);
|
|
|
452870 |
uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
|
|
|
452870 |
uint32_t values[] = {
|
|
|
061fcf |
noborder, // override redirect
|
|
|
452870 |
XCB_EVENT_MASK_EXPOSURE // event mask
|
|
|
452870 |
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
|
|
|
452870 |
| XCB_EVENT_MASK_BUTTON_PRESS
|
|
|
63daec |
| XCB_EVENT_MASK_BUTTON_1_MOTION
|
|
|
452870 |
| XCB_EVENT_MASK_BUTTON_RELEASE };
|
|
|
452870 |
xcb_create_window(
|
|
|
452870 |
app->xcb, // connection
|
|
|
452870 |
XCB_COPY_FROM_PARENT, // depth (same as root)
|
|
|
452870 |
app->win, // window id
|
|
|
452870 |
app->screen->root, // parent window
|
|
|
843e7a |
app->x, app->y, // origin
|
|
|
843e7a |
app->w, app->h, // size
|
|
|
452870 |
10, // border_width
|
|
|
452870 |
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
|
|
|
452870 |
app->screen->root_visual, // visual
|
|
|
452870 |
mask, // additional options mask
|
|
|
452870 |
values ); // additional options
|
|
|
452870 |
|
|
|
452870 |
uint32_t hints[9] = {
|
|
|
452870 |
1, // mask for input hints
|
|
|
452870 |
0, // value of input hint
|
|
|
452870 |
};
|
|
|
452870 |
xcb_change_property_checked(
|
|
|
452870 |
app->xcb,
|
|
|
452870 |
XCB_PROP_MODE_REPLACE,
|
|
|
452870 |
app->win,
|
|
|
452870 |
XCB_ATOM_WM_HINTS,
|
|
|
452870 |
XCB_ATOM_WM_HINTS,
|
|
|
452870 |
32,
|
|
|
452870 |
sizeof(hints)/sizeof(hints[0]), hints );
|
|
|
452870 |
|
|
|
452870 |
// init submodules
|
|
|
452870 |
if (graphInit(&app->graph, app)) {
|
|
|
061fcf |
graphResize(&app->graph);
|
|
|
452870 |
if (inputInit(&app->input, app)) {
|
|
|
452870 |
if (keyboardInit(&app->keyboard, app)) {
|
|
|
452870 |
return 1;
|
|
|
452870 |
}
|
|
|
452870 |
inputDeinit(&app->input);
|
|
|
452870 |
}
|
|
|
452870 |
graphDeinit(&app->graph);
|
|
|
452870 |
}
|
|
|
452870 |
} else {
|
|
|
452870 |
LOGERR("app: init: no screen found");
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
xcb_disconnect(app->xcb);
|
|
|
452870 |
return 0;
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void appDeinit(App *app) {
|
|
|
452870 |
LOGDBG("app: deinit");
|
|
|
452870 |
keyboardDeinit(&app->keyboard);
|
|
|
452870 |
inputDeinit(&app->input);
|
|
|
452870 |
graphDeinit(&app->graph);
|
|
|
452870 |
xcb_disconnect(app->xcb);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
int appRun(App *app) {
|
|
|
452870 |
LOGDBG("app: run");
|
|
|
452870 |
|
|
|
843e7a |
if (app->run)
|
|
|
843e7a |
return LOGERR("app: run: seems already run");
|
|
|
843e7a |
app->run = 1;
|
|
|
843e7a |
|
|
|
452870 |
LOGDBG("app: run: show window");
|
|
|
452870 |
xcb_map_window(app->xcb, app->win);
|
|
|
452870 |
xcb_flush(app->xcb);
|
|
|
452870 |
|
|
|
452870 |
LOGDBG("app: run: event loop");
|
|
|
452870 |
xcb_generic_event_t *event;
|
|
|
452870 |
while ((event = xcb_wait_for_event(app->xcb))) {
|
|
|
452870 |
switch (event->response_type & ~0x80) {
|
|
|
452870 |
case XCB_EXPOSE: {
|
|
|
452870 |
xcb_expose_event_t *e = (xcb_expose_event_t*)event;
|
|
|
452870 |
LOGDBG("app: expose: x=%d, y=%d, w=%d, h=%d", e->x, e->y, e->width, e->height);
|
|
|
452870 |
appInvalidateRect(app, e->x, e->y, e->width, e->height);
|
|
|
452870 |
break;
|
|
|
452870 |
}
|
|
|
452870 |
case XCB_CONFIGURE_NOTIFY: {
|
|
|
452870 |
xcb_configure_notify_event_t *e = (xcb_configure_notify_event_t*)event;
|
|
|
843e7a |
if ( e->width
|
|
|
843e7a |
&& e->height
|
|
|
843e7a |
&& ( app->x != e->x
|
|
|
843e7a |
|| app->y != e->y
|
|
|
843e7a |
|| app->w != e->width
|
|
|
843e7a |
|| app->h != e->height ))
|
|
|
843e7a |
{
|
|
|
843e7a |
LOGDBG("app: moved: x=%d y=%d w=%d, h=%d", e->x, e->y, e->width, e->height);
|
|
|
843e7a |
int resized = app->w != e->width || app->h != e->height;
|
|
|
843e7a |
app->x = e->x;
|
|
|
843e7a |
app->y = e->y;
|
|
|
452870 |
app->w = e->width;
|
|
|
452870 |
app->h = e->height;
|
|
|
061fcf |
if (resized) graphResize(&app->graph);
|
|
|
452870 |
}
|
|
|
452870 |
break;
|
|
|
452870 |
}
|
|
|
452870 |
case XCB_BUTTON_PRESS: {
|
|
|
452870 |
xcb_button_press_event_t *e = (xcb_button_press_event_t*)event;
|
|
|
452870 |
if (e->detail == 1) {
|
|
|
452870 |
LOGDBG("app: mouse down: x=%d, y=%d", e->event_x, e->event_y);
|
|
|
452870 |
keyboardMouseDown(&app->keyboard, e->event_x, e->event_y);
|
|
|
452870 |
}
|
|
|
452870 |
break;
|
|
|
452870 |
}
|
|
|
452870 |
case XCB_BUTTON_RELEASE: {
|
|
|
452870 |
xcb_button_press_event_t *e = (xcb_button_press_event_t*)event;
|
|
|
452870 |
if (e->detail == 1) {
|
|
|
452870 |
LOGDBG("app: mouse up");
|
|
|
452870 |
keyboardMouseUp(&app->keyboard);
|
|
|
452870 |
}
|
|
|
452870 |
break;
|
|
|
452870 |
}
|
|
|
63daec |
case XCB_MOTION_NOTIFY: {
|
|
|
63daec |
xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t*)event;
|
|
|
63daec |
if (e->state & Button1Mask) {
|
|
|
63daec |
LOGDBG("app: mouse motion: x=%d, y=%d", e->event_x, e->event_y);
|
|
|
63daec |
keyboardMouseMotion(&app->keyboard, e->event_x, e->event_y);
|
|
|
63daec |
}
|
|
|
63daec |
break;
|
|
|
63daec |
}
|
|
|
452870 |
default:
|
|
|
452870 |
break;
|
|
|
452870 |
}
|
|
|
452870 |
free(event);
|
|
|
452870 |
|
|
|
843e7a |
if (app->run != 1) break;
|
|
|
843e7a |
|
|
|
061fcf |
inputUpdateModifiers(&app->input);
|
|
|
061fcf |
keyboardResize(&app->keyboard);
|
|
|
061fcf |
keyboardUpdateModifiers(&app->keyboard);
|
|
|
452870 |
if (app->irw > 0 && app->irh > 0) {
|
|
|
452870 |
LOGDBG("app: draw: x=%d, y=%d, w=%d, h=%d", app->irx, app->iry, app->irw, app->irh);
|
|
|
452870 |
graphDrawBackgound(&app->graph, app->irx, app->iry, app->irw, app->irh);
|
|
|
452870 |
keyboardDraw(&app->keyboard, app->irx, app->iry, app->irw, app->irh);
|
|
|
452870 |
xcb_flush(app->xcb);
|
|
|
452870 |
app->irw = 0;
|
|
|
452870 |
}
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
843e7a |
int err = app->run == -2;
|
|
|
843e7a |
app->run = 0;
|
|
|
843e7a |
LOGDBG("app: run: done err=%d", err);
|
|
|
843e7a |
return !err;
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void appStop(App *app, int err) {
|
|
|
843e7a |
LOGDBG("app: stop: err=%d", err);
|
|
|
843e7a |
if (!app->run) {
|
|
|
843e7a |
LOGERR("app: stop: seems not started");
|
|
|
843e7a |
return;
|
|
|
843e7a |
}
|
|
|
843e7a |
if (app->run == 1) app->run = -1;
|
|
|
843e7a |
if (err) app->run = -2;
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void appMove(App *app, int x, int y, int w, int h) {
|
|
|
843e7a |
LOGDBG("app: move: x=%d, y=%d, w=%d, h=%d", x, y, w, h);
|
|
|
843e7a |
if (w <= 0 || h <= 0) return;
|
|
|
843e7a |
if (app->x == x && app->y == y && app->w == w && app->h == h)
|
|
|
843e7a |
return;
|
|
|
843e7a |
uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
|
|
|
843e7a |
uint32_t values[] = { x, y, w, h };
|
|
|
843e7a |
xcb_configure_window(app->xcb, app->win, mask, values);
|
|
|
63daec |
xcb_flush(app->xcb);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void appInvalidateRect(App *app, int x, int y, int w, int h) {
|
|
|
452870 |
LOGDBG("app: invalidate rect: x=%d, y=%d, w=%d, h=%d", x, y, w, h);
|
|
|
452870 |
rectIntersect(&x, &y, &w, &h, 0, 0, app->w, app->h);
|
|
|
452870 |
rectMerge(&app->irx, &app->iry, &app->irw, &app->irh, x, y, w, h);
|
|
|
d3e9d7 |
LOGDBG("app: invalidate rect: summary x=%d, y=%d, w=%d, h=%d", app->irx, app->iry, app->irw, app->irh);
|
|
|
452870 |
}
|
|
|
452870 |
|