Implement rendering of titles in CSD

This commit is contained in:
Kovid Goyal 2021-04-01 10:23:04 +05:30
parent e92ed67021
commit 5d496216e0
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
7 changed files with 34 additions and 9 deletions

2
glfw/glfw3.h vendored
View file

@ -1683,7 +1683,7 @@ typedef void (* GLFWjoystickfun)(int,int);
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
typedef void (* GLFWtickcallback)(void*);
typedef void (* GLFWdrawtextfun)(const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
/*! @brief Video mode type.
*

View file

@ -50,6 +50,9 @@ alloc_buffer_pair(_GLFWWaylandBufferPair *pair, struct wl_shm_pool *pool, uint8_
static void
render_title_bar(_GLFWwindow *window, bool to_front_buffer) {
uint8_t *output = to_front_buffer ? decs.top.buffer.data.front : decs.top.buffer.data.back;
if (window->wl.title && window->wl.title[0] && _glfw.callbacks.draw_text) {
if (_glfw.callbacks.draw_text((GLFWwindow*)window, window->wl.title, 0, bg_color, output, decs.top.buffer.width, decs.top.buffer.height, 10, 0)) return;
}
for (uint32_t *px = (uint32_t*)output, *end = (uint32_t*)(output + decs.top.buffer.size_in_bytes); px < end; px++) {
*px = bg_color;
}

5
glfw/wl_window.c vendored
View file

@ -817,7 +817,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
if (window->wl.title) free(window->wl.title);
if (window->wl.title) {
if (title && strcmp(title, window->wl.title) == 0) return;
free(window->wl.title);
} else if (!title) return;
// Wayland cannot handle requests larger than ~8200 bytes. Sending
// one causes an abort(). Since titles this large are meaningless anyway
// ensure they do not happen.

View file

@ -99,7 +99,7 @@ load_font(FontConfigFace *info, Face *ans) {
static bool
ensure_state(void) {
if (main_face.freetype && main_face.hb) return false;
if (main_face.freetype && main_face.hb) return true;
if (!information_for_font_family(main_face_family.name, main_face_family.bold, main_face_family.italic, &main_face_information)) return false;
if (!load_font(&main_face_information, &main_face)) return false;
hb_buffer = hb_buffer_create();
@ -147,6 +147,7 @@ typedef struct RenderState {
Face *current_face;
float x, y;
Region src, dest;
unsigned sz_px;
} RenderState;
static void
@ -227,7 +228,7 @@ render_run(RenderState *rs) {
}
FT_Face face = rs->current_face->freetype;
bool has_color = FT_HAS_COLOR(face);
FT_UInt pixel_size = 3 * rs->output_height / 4;
FT_UInt pixel_size = rs->sz_px;
set_pixel_size(rs->current_face, pixel_size, has_color);
hb_shape(rs->current_face->hb, hb_buffer, NULL, 0);
unsigned int len = hb_buffer_get_length(hb_buffer);
@ -327,7 +328,7 @@ process_codepoint(RenderState *rs, char_type codep, char_type next_codep) {
}
bool
render_single_line(const char *text, pixel fg, pixel bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset) {
render_single_line(const char *text, unsigned sz_px, pixel fg, pixel bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset) {
if (!ensure_state()) return false;
bool has_text = text && text[0];
pixel pbg = premult_pixel(bg, ((bg >> 24) & 0xff));
@ -343,7 +344,7 @@ render_single_line(const char *text, pixel fg, pixel bg, uint8_t *output_buf, si
text_len = decode_utf8_string(text, text_len, unicode);
RenderState rs = {
.current_face = &main_face, .fg = fg, .bg = bg, .output_width = width, .output_height = height,
.output = (pixel*)output_buf, .x = x_offset, .y = y_offset
.output = (pixel*)output_buf, .x = x_offset, .y = y_offset, .sz_px = sz_px
};
for (size_t i = 0; i < text_len && rs.x < rs.output_width; i++) {
@ -376,7 +377,7 @@ render_line(PyObject *self UNUSED, PyObject *args, PyObject *kw) {
PyObject *ans = PyBytes_FromStringAndSize(NULL, width * height * 4);
if (!ans) return NULL;
uint8_t *buffer = (u_int8_t*) PyBytes_AS_STRING(ans);
if (!render_single_line(text, 0, 0xffffffff, buffer, width, height, x_offset, y_offset)) {
if (!render_single_line(text, 3 * height / 4, 0, 0xffffffff, buffer, width, height, x_offset, y_offset)) {
Py_CLEAR(ans);
if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "Unknown error while rendering text");
ans = NULL;

View file

@ -9,7 +9,7 @@
#include "data-types.h"
#include <hb-ft.h>
bool render_single_line(const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
bool render_single_line(const char *text, unsigned sz_px, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
typedef struct FontConfigFace {
char *path;

2
kitty/glfw-wrapper.h generated
View file

@ -1421,7 +1421,7 @@ typedef void (* GLFWjoystickfun)(int,int);
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
typedef void (* GLFWtickcallback)(void*);
typedef void (* GLFWdrawtextfun)(const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset);
/*! @brief Video mode type.
*

View file

@ -10,6 +10,9 @@
#include "charsets.h"
#include <structmember.h>
#include "glfw-wrapper.h"
#ifndef __APPLE__
#include "freetype_render_ui_text.h"
#endif
extern bool cocoa_make_window_resizable(void *w, bool);
extern void cocoa_focus_window(void *w);
extern long cocoa_window_number(void *w);
@ -381,12 +384,25 @@ application_close_requested_callback(int flags) {
}
}
static inline void get_window_dpi(GLFWwindow *w, double *x, double *y);
#ifdef __APPLE__
static bool
apple_file_open_callback(const char* filepath) {
set_cocoa_pending_action(OPEN_FILE, filepath);
return true;
}
#else
static bool
draw_text_callback(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset) {
if (!set_callback_window(window)) return false;
double xdpi, ydpi;
get_window_dpi(window, &xdpi, &ydpi);
unsigned px_sz = (unsigned)(global_state.callback_os_window->font_sz_in_pts * ydpi / 72.);
px_sz = MIN(px_sz, 3 * height / 4);
return render_single_line(text, px_sz, fg, bg, output_buf, width, height, x_offset, y_offset);
}
#endif
// }}}
@ -855,6 +871,8 @@ glfw_init(PyObject UNUSED *self, PyObject *args) {
if (ans == Py_True) {
#ifdef __APPLE__
glfwSetCocoaFileOpenCallback(apple_file_open_callback);
#else
glfwSetDrawTextFunction(draw_text_callback);
#endif
OSWindow w = {0};
set_os_window_dpi(&w);