Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
xdavidwu committed Nov 15, 2019
0 parents commit bf61731
Show file tree
Hide file tree
Showing 12 changed files with 1,559 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
157 changes: 157 additions & 0 deletions bottom-panel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#include <assert.h>
#include <stdbool.h>

#include "wlchewing.h"
#include "buffer.h"
#include "bottom-panel.h"

static void noop() {
// no-op
}

static void layer_surface_configure(void *data,
struct zwlr_layer_surface_v1 *wlr_layer_surface,
uint32_t serial, uint32_t w, uint32_t h) {
printf("resize %d %d\n", w, h);
struct wlchewing_bottom_panel *panel = data;
panel->width = w;
panel->height = h;
zwlr_layer_surface_v1_ack_configure(wlr_layer_surface, serial);
}

static void layer_surface_closed(void *data,
struct zwlr_layer_surface_v1 *wlr_layer_surface) {
struct wlchewing_bottom_panel *panel = data;
bottom_panel_destroy(panel);
}

static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.configure = layer_surface_configure,
.closed = layer_surface_closed,
};

static void surface_enter(void *data, struct wl_surface *wl_surface,
struct wl_output *output) {
struct wlchewing_bottom_panel *panel = data;
panel->scale = *((uint32_t *)wl_output_get_user_data(output));
printf("scale %d\n", panel->scale);
}

static const struct wl_surface_listener surface_listener = {
.enter = surface_enter,
.leave = noop,
};

static void bottom_panel_configure(struct wlchewing_bottom_panel *panel,
struct wlchewing_state *state){
printf("render scale %d\n", panel->scale);
struct wlchewing_buffer *buffer = buffer_new(state->shm,
panel->width, panel->height, panel->scale);
assert(buffer);
panel->layout = pango_cairo_create_layout(buffer->cairo);
pango_layout_set_text(panel->layout, "哈嘍 PangoCairo", -1);
int width, height;
pango_layout_get_size(panel->layout, &width, &height);
panel->height = height / PANGO_SCALE;
wl_surface_attach(panel->wl_surface, buffer->wl_buffer, 0, 0);
zwlr_layer_surface_v1_set_size(panel->layer_surface, 0, panel->height);
zwlr_layer_surface_v1_set_exclusive_zone(panel->layer_surface, panel->height);
wl_surface_commit(panel->wl_surface);
wl_display_roundtrip(state->display);
wl_surface_set_buffer_scale(panel->wl_surface, panel->scale);
buffer_destroy(buffer);
}

static int render_cand(struct wlchewing_buffer *buffer, PangoLayout *layout,
const char *text, bool selected) {
pango_layout_set_text(layout, text, -1);
int width, height;
pango_layout_get_size(layout, &width, &height);
width /= PANGO_SCALE;
if (selected) {
cairo_set_source_rgba(buffer->cairo, 0.2, 0.2, 0.2, 0.9);
cairo_rectangle(buffer->cairo, 0, 0, width + 8, buffer->height);
cairo_fill(buffer->cairo);

}
cairo_move_to(buffer->cairo, 4, 0);
cairo_set_source_rgba(buffer->cairo, 1, 1, 1, 0.9);
pango_cairo_show_layout(buffer->cairo, layout);
return width + 8;
}

struct wlchewing_bottom_panel *bottom_panel_new(
struct wlchewing_state *state) {
struct wlchewing_bottom_panel *panel = calloc(1,
sizeof(struct wlchewing_bottom_panel));
if (panel == NULL) {
wlchewing_err("Failed to calloc for bottom panel");
return NULL;
}
panel->scale = 1;
panel->height = 1;
panel->width = 1;
panel->wl_surface = wl_compositor_create_surface(state->compositor);
assert(panel->wl_surface);
wl_surface_add_listener(panel->wl_surface, &surface_listener, panel);
panel->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
state->layer_shell, panel->wl_surface, NULL,
ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "input-method-panel");
assert(panel->layer_surface);

zwlr_layer_surface_v1_add_listener(panel->layer_surface,
&layer_surface_listener, panel);
zwlr_layer_surface_v1_set_anchor(panel->layer_surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
wl_surface_commit(panel->wl_surface);
wl_display_roundtrip(state->display);

// set scale and height TODO: set font options there
bottom_panel_configure(panel, state);

panel->buffer_pool = buffer_pool_new(state->shm,
panel->width, panel->height, panel->scale);
return panel;
}

void bottom_panel_destroy(struct wlchewing_bottom_panel *panel) {
zwlr_layer_surface_v1_destroy(panel->layer_surface);
buffer_pool_destroy(panel->buffer_pool);
g_object_unref(panel->layout);
free(panel);
}

void bottom_panel_render(struct wlchewing_bottom_panel *panel,
ChewingContext *ctx) {
int total = chewing_cand_TotalChoice(ctx);
assert(panel->selected_index < total);

struct wlchewing_buffer *buffer = buffer_pool_get_buffer(
panel->buffer_pool);
cairo_t *cairo = buffer->cairo;
cairo_save(cairo);
cairo_set_source_rgba(cairo, 0, 0, 0, 0.9);
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_paint(cairo);
cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
printf("selected %d\n", panel->selected_index);

int offset = 0, total_offset = 0;
offset = render_cand(buffer, panel->layout,
chewing_cand_string_by_index_static(ctx,
panel->selected_index), true);
for (int i = panel->selected_index + 1; i < total; i++) {
cairo_translate(cairo, offset, 0);
total_offset += offset;
offset = render_cand(buffer, panel->layout,
chewing_cand_string_by_index_static(ctx, i), false);
}
cairo_translate(cairo, -total_offset, 0);
cairo_restore(cairo);
wl_surface_attach(panel->wl_surface, buffer->wl_buffer, 0, 0);
wl_surface_damage_buffer(panel->wl_surface, 0, 0,
buffer->width * buffer->scale, buffer->height * buffer->scale);
wl_surface_commit(panel->wl_surface);
}
27 changes: 27 additions & 0 deletions bottom-panel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef BOTTOM_PANEL_H
#define BOTTOM_PANEL_H

#include <pango/pangocairo.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"

struct wlchewing_state;
struct wlchewing_buffer;

struct wlchewing_bottom_panel {
struct zwlr_layer_surface_v1 *layer_surface;
struct wl_surface *wl_surface;
struct wl_list *buffer_pool;
uint32_t width, height;
int32_t scale;
PangoLayout *layout;
int selected_index;
};

struct wlchewing_bottom_panel *bottom_panel_new(struct wlchewing_state *state);

void bottom_panel_destroy(struct wlchewing_bottom_panel *panel);

void bottom_panel_render(struct wlchewing_bottom_panel *panel,
ChewingContext *ctx);

#endif
126 changes: 126 additions & 0 deletions buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "wlchewing.h"
#include "buffer.h"

#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

static void handle_release(void *data, struct wl_buffer *wl_buffer) {
struct wlchewing_buffer *buffer = data;
buffer->available = true;
}

static const struct wl_buffer_listener buffer_listener = {
.release = handle_release,
};

static void mktempname(char *template) {
}

struct wlchewing_buffer *buffer_new(struct wl_shm *shm,
uint32_t width, uint32_t height, uint32_t scale) {
struct wlchewing_buffer *buffer = calloc(1, sizeof(struct wlchewing_buffer));
if (buffer == NULL){
wlchewing_err("Failed to calloc for wlchewing_buffer");
return NULL;
}
buffer->width = width;
buffer->height = height;
buffer->scale = scale;
buffer->shm = shm;

char *template=strdup("/wlchewing-XXXXXX");
char *name=mktemp(template); //TODO
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd < 0) {
wlchewing_err("Failed to shm_open");
free(buffer);
return NULL;
}
shm_unlink(name);
free(name);

off_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
width * scale);
buffer->size = (height * scale) * stride;
int ret = ftruncate(fd, buffer->size);
if (ret == -1) {
wlchewing_err("Failed to ftruncate");
free(buffer);
return NULL;
}
buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (buffer->data == MAP_FAILED) {
wlchewing_err("Failed to mmap %ld", buffer->size);
close(fd);
free(buffer);
return NULL;
}

struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer->size);
buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0, width * scale,
height * scale, stride, WL_SHM_FORMAT_ARGB8888);
wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
wl_shm_pool_destroy(pool);
close(fd);

buffer->cairo_surface = cairo_image_surface_create_for_data(
buffer->data, CAIRO_FORMAT_ARGB32, width * scale,
height * scale, stride);
buffer->cairo = cairo_create(buffer->cairo_surface);
cairo_scale(buffer->cairo, scale, scale);
return buffer;
}

void buffer_destroy(struct wlchewing_buffer *buffer) {
wl_buffer_destroy(buffer->wl_buffer);
cairo_destroy(buffer->cairo);
cairo_surface_destroy(buffer->cairo_surface);
munmap(buffer->data, buffer->size);
free(buffer);
}

struct wl_list *buffer_pool_new(struct wl_shm *shm,
uint32_t width, uint32_t height, uint32_t scale) {
struct wl_list *pool = calloc(1, sizeof(struct wl_list));
if (pool == NULL) {
wlchewing_err("Failed to calloc wl_list for buffer pool");
return NULL;
}
wl_list_init(pool);
struct wlchewing_buffer *buffer = buffer_new(shm, width, height, scale);
buffer->available = true;
if (buffer == NULL) {
free(pool);
wlchewing_err("Failed to create first buffer for buffer pool");
return NULL;
}
wl_list_insert(pool, &buffer->link);
return pool;
}

struct wlchewing_buffer *buffer_pool_get_buffer(struct wl_list *pool) {
struct wlchewing_buffer *cur_buffer;
wl_list_for_each(cur_buffer, pool, link) {
if (cur_buffer->available) {
cur_buffer->available = false;
return cur_buffer;
}
}
printf("new buffer\n");
struct wlchewing_buffer *new_buffer = buffer_new(cur_buffer->shm,
cur_buffer->width, cur_buffer->height, cur_buffer->scale);
wl_list_insert(&cur_buffer->link, &new_buffer->link);
return new_buffer;
}

void buffer_pool_destroy(struct wl_list *pool) {
struct wlchewing_buffer *cur_buffer, *tmp;
wl_list_for_each_safe(cur_buffer, tmp, pool, link) {
buffer_destroy(cur_buffer);
}
free(pool);
}
35 changes: 35 additions & 0 deletions buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef BUFFER_H
#define BUFFER_H

#include <cairo.h>
#include <wayland-client.h>

struct wlchewing_buffer {
uint32_t width, height;
int32_t scale;
off_t size;

void *data;
struct wl_buffer *wl_buffer;
cairo_surface_t *cairo_surface;
cairo_t *cairo;
bool available;

struct wl_list link;
struct wl_shm *shm;
};

struct wlchewing_buffer *buffer_new(struct wl_shm *shm,
uint32_t width, uint32_t height, uint32_t scale);

void buffer_destroy(struct wlchewing_buffer *buffer);


struct wl_list *buffer_pool_new(struct wl_shm *shm,
uint32_t width, uint32_t height, uint32_t scale);

struct wlchewing_buffer *buffer_pool_get_buffer(struct wl_list *pool);

void buffer_pool_destroy(struct wl_list *pool);

#endif
Empty file added config.c
Empty file.
Loading

0 comments on commit bf61731

Please sign in to comment.