-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement interaction #10
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
#include <string.h> | ||
#include <sys/mman.h> | ||
#include <sys/select.h> | ||
#include <sys/wait.h> | ||
#include <time.h> | ||
#include <unistd.h> | ||
#include <wayland-client.h> | ||
|
@@ -34,18 +35,24 @@ | |
|
||
/* Includes the newline character */ | ||
#define MAX_LINE_LEN 8192 | ||
#define MAX_CMD_LEN 256 | ||
#define MAX_CLICKABLES 64 | ||
|
||
enum align { ALIGN_C, ALIGN_L, ALIGN_R }; | ||
|
||
static struct wl_display *display; | ||
static struct wl_compositor *compositor; | ||
static struct wl_subcompositor *subcompositor; | ||
static struct wl_shm *shm; | ||
static struct zwlr_layer_shell_v1 *layer_shell; | ||
|
||
static struct zwlr_layer_surface_v1 *layer_surface; | ||
static struct wl_output *wl_output; | ||
static struct wl_surface *wl_surface; | ||
|
||
static struct wl_seat *wl_seat; | ||
static struct wl_pointer *wl_pointer; | ||
|
||
static int32_t output = -1; | ||
|
||
static uint32_t width, height, titlewidth; | ||
|
@@ -135,8 +142,35 @@ parse_color(const char *str, pixman_color_t *clr) | |
return 0; | ||
} | ||
|
||
struct clickable { | ||
uint32_t x1, y1, x2, y2; | ||
uint8_t btn; | ||
char *cmd; | ||
}; | ||
|
||
static int | ||
parse_clickable_area(char *str, struct clickable *c, uint32_t xpos, uint32_t ypos) | ||
{ | ||
c->x1 = xpos; | ||
c->y1 = 0; | ||
|
||
c->btn = 0; | ||
while (*str != ',' && *str != '\0') | ||
if (isdigit(*str)) c->btn = c->btn*10 + (*str++ - '0'); | ||
|
||
if (*str++ == '\0') BARF("bad clickarea cmd"); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
c->cmd = malloc(strlen(str) + 1); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (!c->cmd) BARF("bad malloc clickarea cmd"); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
strcpy(c->cmd, str); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return 0; | ||
} | ||
|
||
static struct clickable clickies[MAX_CLICKABLES]; | ||
static int clicky_i = 0; | ||
Comment on lines
+170
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please move this with the rest of global variables. |
||
|
||
static char * | ||
handle_cmd(char *cmd, pixman_color_t *bg, pixman_color_t *fg) | ||
handle_cmd(char *cmd, pixman_color_t *bg, pixman_color_t *fg, uint32_t *xpos, uint32_t *ypos) | ||
{ | ||
char *arg, *end; | ||
|
||
|
@@ -158,6 +192,14 @@ handle_cmd(char *cmd, pixman_color_t *bg, pixman_color_t *fg) | |
} else if (parse_color(arg, fg)) { | ||
fprintf(stderr, "Bad color string \"%s\"\n", arg); | ||
} | ||
} else if (!strcmp(cmd, "ca")) { | ||
if (!*arg) { | ||
clickies[clicky_i].x2 = *xpos; | ||
clickies[clicky_i].y2 = height; | ||
clicky_i++; | ||
} else if (parse_clickable_area(arg, &clickies[clicky_i], *xpos, *ypos)) { | ||
fprintf(stderr, "bad click area \"%s\"\n", arg); | ||
} | ||
} else { | ||
fprintf(stderr, "Unrecognized command \"%s\"\n", cmd); | ||
} | ||
|
@@ -220,7 +262,7 @@ draw_frame(char *text) | |
if (state == UTF8_ACCEPT && *p == '^') { | ||
p++; | ||
if (*p != '^') { | ||
p = handle_cmd(p, &textbgcolor, &textfgcolor); | ||
p = handle_cmd(p, &textbgcolor, &textfgcolor, &xpos, &ypos); | ||
pixman_image_unref(fgfill); | ||
fgfill = pixman_image_create_solid_fill(&textfgcolor); | ||
continue; | ||
|
@@ -296,6 +338,15 @@ draw_frame(char *text) | |
xdraw = (width - maxxpos) / 2; | ||
break; | ||
} | ||
|
||
clickies[clicky_i] = (struct clickable) { 0 }; | ||
|
||
while (clicky_i > 0) { | ||
clicky_i--; | ||
clickies[clicky_i].x1 += xdraw; | ||
clickies[clicky_i].x2 += xdraw; | ||
} | ||
|
||
pixman_image_composite32(PIXMAN_OP_OVER, background, NULL, bar, 0, 0, 0, 0, | ||
xdraw, 0, width, height); | ||
pixman_image_composite32(PIXMAN_OP_OVER, foreground, NULL, bar, 0, 0, 0, 0, | ||
|
@@ -345,13 +396,138 @@ static struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |
.closed = layer_surface_closed, | ||
}; | ||
|
||
struct input_state { | ||
struct wl_surface *surface; | ||
double x, y; | ||
uint32_t button; | ||
}; | ||
Comment on lines
+407
to
+411
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also move this after the enum, (sort alphabetically) |
||
|
||
static void | ||
noop() {} | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
static void | ||
wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | ||
uint32_t serial, struct wl_surface *surface, | ||
wl_fixed_t surface_x, wl_fixed_t surface_y) | ||
{ | ||
struct input_state *istate = data; | ||
istate->surface = surface; | ||
istate->x = wl_fixed_to_double(surface_x); | ||
istate->y = wl_fixed_to_double(surface_y); | ||
} | ||
Comment on lines
+414
to
+422
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I re-read the protocol, and it says:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's better suited for a separate pr |
||
|
||
static void | ||
wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, | ||
wl_fixed_t surface_x, wl_fixed_t surface_y) | ||
{ | ||
struct input_state *istate = data; | ||
istate->x = wl_fixed_to_double(surface_x); | ||
istate->y = wl_fixed_to_double(surface_y); | ||
} | ||
|
||
static void | ||
wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, | ||
uint32_t time, uint32_t button, uint32_t state) | ||
{ | ||
struct input_state *istate = data; | ||
istate->button = state == WL_POINTER_BUTTON_STATE_RELEASED ? 0 : button; | ||
} | ||
|
||
static void | ||
wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, | ||
uint32_t serial, struct wl_surface *surface) | ||
{ | ||
struct input_state *istate = data; | ||
istate->surface = NULL; | ||
} | ||
|
||
/* borrowed from dzen's util.c, un-double-forked */ | ||
void | ||
spawn(const char *arg) { | ||
static const char *shell = NULL; | ||
|
||
if(!shell && !(shell = getenv("SHELL"))) | ||
shell = "/bin/sh"; | ||
if(!arg) | ||
return; | ||
if(fork() == 0) { | ||
setsid(); | ||
execl(shell, shell, "-c", arg, (char *)NULL); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't read the dzen's docs but maybe hardcoding "/bin/sh" is better |
||
fprintf(stderr, "dtao: execl '%s -c %s'", shell, arg); | ||
perror(" failed"); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
wait(0); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
static void | ||
wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) | ||
{ | ||
struct input_state *istate = data; | ||
|
||
if (!istate || istate->button == 0) | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return; | ||
|
||
for (struct clickable *c = clickies; c->btn > 0; c++) { | ||
if (c->btn == istate->button - 271 && | ||
istate->x >= c->x1 && istate->x <= c->x2 && | ||
istate->y >= c->y1 && istate->y <= c->y2) { | ||
spawn(c->cmd); | ||
break; | ||
} | ||
} | ||
istate->button = 0; | ||
} | ||
|
||
static const struct wl_pointer_listener wl_pointer_listener = { | ||
.enter = wl_pointer_enter, | ||
.leave = wl_pointer_leave, | ||
.motion = wl_pointer_motion, | ||
.button = wl_pointer_button, | ||
.axis = noop, | ||
.axis_source = noop, | ||
.axis_stop = noop, | ||
.axis_discrete = noop, | ||
.frame = wl_pointer_frame, | ||
}; | ||
|
||
static void | ||
wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) | ||
{ | ||
struct input_state *istate = data; | ||
bool have_pointer = capabilities & WL_SEAT_CAPABILITY_POINTER; | ||
|
||
if (have_pointer && wl_pointer == NULL) { | ||
wl_pointer = wl_seat_get_pointer(wl_seat); | ||
wl_pointer_add_listener(wl_pointer, | ||
&wl_pointer_listener, istate); | ||
} else if (!have_pointer && wl_pointer != NULL) { | ||
wl_pointer_release(wl_pointer); | ||
wl_pointer = NULL; | ||
} | ||
} | ||
|
||
static void | ||
wl_seat_name(void *data, struct wl_seat *wl_seat, const char *name) | ||
{ | ||
fprintf(stderr, "seat name: %s\n", name); | ||
} | ||
|
||
static const struct wl_seat_listener wl_seat_listener = { | ||
.capabilities = wl_seat_capabilities, | ||
.name = wl_seat_name, | ||
}; | ||
|
||
static void | ||
handle_global(void *data, struct wl_registry *registry, | ||
uint32_t name, const char *interface, uint32_t version) | ||
{ | ||
struct input_state *istate = data; | ||
if (strcmp(interface, wl_compositor_interface.name) == 0) { | ||
compositor = wl_registry_bind(registry, name, | ||
&wl_compositor_interface, 4); | ||
} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) { | ||
subcompositor = wl_registry_bind( | ||
registry, name, &wl_subcompositor_interface, 1); | ||
} else if (strcmp(interface, wl_shm_interface.name) == 0) { | ||
shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); | ||
} else if (strcmp(interface, wl_output_interface.name) == 0) { | ||
|
@@ -362,10 +538,17 @@ handle_global(void *data, struct wl_registry *registry, | |
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | ||
layer_shell = wl_registry_bind(registry, name, | ||
&zwlr_layer_shell_v1_interface, 1); | ||
} else if (strcmp(interface, wl_seat_interface.name) == 0) { | ||
wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 5); | ||
wl_seat_add_listener(wl_seat, &wl_seat_listener, istate); | ||
} | ||
|
||
} | ||
|
||
static const struct wl_registry_listener registry_listener = {.global = handle_global,}; | ||
static const struct wl_registry_listener registry_listener = { | ||
.global = handle_global, | ||
.global_remove = noop, | ||
}; | ||
|
||
static void | ||
read_stdin(void) | ||
|
@@ -563,7 +746,12 @@ main(int argc, char **argv) | |
BARF("Failed to create display"); | ||
|
||
struct wl_registry *registry = wl_display_get_registry(display); | ||
wl_registry_add_listener(registry, ®istry_listener, NULL); | ||
|
||
struct input_state *istate = calloc(1, sizeof(struct input_state)); | ||
if (!istate) | ||
BARF("Failed to create inputstate"); | ||
|
||
wl_registry_add_listener(registry, ®istry_listener, istate); | ||
youbitchoc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
wl_display_roundtrip(display); | ||
|
||
if (!compositor || !shm || !layer_shell) | ||
|
@@ -609,6 +797,7 @@ main(int argc, char **argv) | |
wl_compositor_destroy(compositor); | ||
wl_registry_destroy(registry); | ||
wl_display_disconnect(display); | ||
free(istate); | ||
|
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this after the enum (L38)