-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bf61731
Showing
12 changed files
with
1,559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
Oops, something went wrong.