Show window titles during visual select

Still has to be implemented on macOS
This commit is contained in:
Kovid Goyal 2021-10-15 14:19:56 +05:30
parent dcda2bff69
commit 78c63e6a18
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 114 additions and 33 deletions

View File

@ -416,8 +416,7 @@ apple_file_open_callback(const char* filepath) {
static FreeTypeRenderCtx csd_title_render_ctx = NULL;
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, size_t right_margin) {
if (!set_callback_window(window)) return false;
ensure_csd_title_render_ctx(void) {
if (!csd_title_render_ctx) {
csd_title_render_ctx = create_freetype_render_context(NULL, true, false);
if (!csd_title_render_ctx) {
@ -425,6 +424,13 @@ draw_text_callback(GLFWwindow *window, const char *text, uint32_t fg, uint32_t b
return false;
}
}
return true;
}
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, size_t right_margin) {
if (!set_callback_window(window)) return false;
if (!ensure_csd_title_render_ctx()) 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.);
@ -435,6 +441,18 @@ draw_text_callback(GLFWwindow *window, const char *text, uint32_t fg, uint32_t b
if (!ok && PyErr_Occurred()) PyErr_Print();
return ok;
}
bool
draw_window_title(OSWindow *window, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height) {
if (!ensure_csd_title_render_ctx()) return false;
unsigned px_sz = (unsigned)(window->fonts_data->font_sz_in_pts * window->fonts_data->logical_dpi_y / 72.);
px_sz = MIN(px_sz, 3 * height / 4);
#define RGB2BGR(x) (x & 0xFF000000) | ((x & 0xFF0000) >> 16) | (x & 0x00FF00) | ((x & 0x0000FF) << 16)
bool ok = render_single_line(csd_title_render_ctx, text, px_sz, RGB2BGR(fg), RGB2BGR(bg), output_buf, width, height, 0, 0, 0);
#undef RGB2BGR
if (!ok && PyErr_Occurred()) PyErr_Print();
return ok;
}
#endif
// }}}

View File

@ -716,14 +716,21 @@ set_vertex_data(ImageRenderData *rd, const ImageRef *ref, const ImageRect *dest_
}
void
gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height) {
gpu_data_for_image(ImageRenderData *ans, float left, float top, float right, float bottom) {
// x-axis is from -1 to 1, y axis is from 1 to -1
static const ImageRef source_rect = { .src_rect = { .left=0, .top=0, .bottom=1, .right=1 }};
const ImageRef *ref = &source_rect;
const ImageRect r = { .left = left, .right = right, .top = top, .bottom = bottom };
set_vertex_data(ans, ref, &r);
ans->group_count = 1;
}
void
gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height) {
float width_frac = 2 * MIN(1, width / (float)screen_width_px), height_frac = 2 * MIN(1, height / (float)screen_height_px);
float hmargin = (2 - width_frac) / 2;
float vmargin = (2 - height_frac) / 2;
const ImageRect r = { .left = -1 + hmargin, .right = -1 + hmargin + width_frac, .top = 1 - vmargin, .bottom = 1 - vmargin - height_frac };
set_vertex_data(ans, ref, &r);
gpu_data_for_image(ans, -1 + hmargin, 1 - vmargin, -1 + hmargin + width_frac, 1 - vmargin - height_frac);
}
bool

View File

@ -128,6 +128,7 @@ bool grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float
void grman_scroll_images(GraphicsManager *self, const ScrollData*, CellPixelSize fg);
void grman_resize(GraphicsManager*, index_type, index_type, index_type, index_type);
void grman_rescale(GraphicsManager *self, CellPixelSize fg);
void gpu_data_for_image(ImageRenderData *ans, float left, float top, float right, float bottom);
void gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height);
bool png_path_to_bitmap(const char *path, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz);
bool scan_active_animations(GraphicsManager *self, const monotonic_t now, monotonic_t *minimum_gap, bool os_window_context_set);

View File

@ -467,14 +467,87 @@ draw_tint(bool premult, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat
}
static void
draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height, Window *window UNUSED) {
set_cell_uniforms(float current_inactive_text_alpha, bool force) {
if (!cell_uniform_data.constants_set || force) {
cell_uniform_data.gploc = glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "inactive_text_alpha");
cell_uniform_data.gpploc = glGetUniformLocation(program_id(GRAPHICS_PREMULT_PROGRAM), "inactive_text_alpha");
cell_uniform_data.cploc = glGetUniformLocation(program_id(CELL_PROGRAM), "inactive_text_alpha");
cell_uniform_data.cfploc = glGetUniformLocation(program_id(CELL_FG_PROGRAM), "inactive_text_alpha");
cell_uniform_data.amask_premult_loc = glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "alpha_mask_premult");
#define S(prog, name, val, type) { bind_program(prog); glUniform##type(glGetUniformLocation(program_id(prog), #name), val); }
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
S(CELL_BG_PROGRAM, defaultbg, OPT(background), 1f);
#undef S
cell_uniform_data.constants_set = true;
}
if (current_inactive_text_alpha != cell_uniform_data.prev_inactive_text_alpha || force) {
cell_uniform_data.prev_inactive_text_alpha = current_inactive_text_alpha;
#define S(prog, loc) { bind_program(prog); glUniform1f(cell_uniform_data.loc, current_inactive_text_alpha); }
S(CELL_PROGRAM, cploc); S(CELL_FG_PROGRAM, cfploc); S(GRAPHICS_PROGRAM, gploc); S(GRAPHICS_PREMULT_PROGRAM, gpploc);
}
}
static GLfloat
render_window_title(OSWindow *os_window, Screen *screen UNUSED, GLfloat xstart, GLfloat ystart, GLfloat width, Window *window, GLfloat left, GLfloat right) {
unsigned bar_height = os_window->fonts_data->cell_height + 2;
if (!bar_height || right <= left) return 0;
unsigned bar_width = (unsigned)ceilf(right - left);
if (!window->title_bar_data.buf || window->title_bar_data.width != bar_width || window->title_bar_data.height != bar_height) {
free(window->title_bar_data.buf);
window->title_bar_data.buf = malloc(4 * bar_width * bar_height);
window->title_bar_data.last_drawn_title_object_id = NULL;
if (!window->title_bar_data.buf) return 0;
window->title_bar_data.height = bar_height;
window->title_bar_data.width = bar_width;
}
static char title[2048] = {0};
if (window->title_bar_data.last_drawn_title_object_id != window->title) {
snprintf(title, arraysz(title), " %s", PyUnicode_AsUTF8(window->title));
#define RGBCOL(which) ( 0xff000000 | colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.which, screen->color_profile->configured.which) )
if (!draw_window_title(os_window, title, RGBCOL(highlight_fg), RGBCOL(highlight_bg), window->title_bar_data.buf, bar_width, bar_height)) return 0;
#undef RGBCOL
window->title_bar_data.last_drawn_title_object_id = window->title;
}
static ImageRenderData data = {.group_count=1};
gpu_data_for_image(&data, xstart, ystart, xstart + width, ystart - 2.f * (bar_height / (float)os_window->viewport_height));
if (!data.texture_id) { glGenTextures(1, &data.texture_id); }
glBindTexture(GL_TEXTURE_2D, data.texture_id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bar_width, bar_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, window->title_bar_data.buf);
set_cell_uniforms(1.f, false);
bind_program(GRAPHICS_PROGRAM);
send_graphics_data_to_gpu(1, os_window->gvao_idx, &data);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); // BLEND_PREMULT
bind_program(SEVEN_SEGMENT_PROGRAM);
if (os_window->is_semi_transparent) { BLEND_PREMULT; } else { BLEND_ONTO_OPAQUE; }
draw_graphics(GRAPHICS_PROGRAM, 0, os_window->gvao_idx, &data, 0, 1);
glDisable(GL_BLEND);
return (GLfloat)bar_height / (GLfloat)os_window->viewport_height;
}
static void
draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height, Window *window) {
GLfloat left = os_window->viewport_width * (xstart + 1.f) / 2.f;
GLfloat right = left + os_window->viewport_width * width / 2.f;
GLfloat top = os_window->viewport_height * (1.f - ystart) / 2.f;
GLfloat bottom = os_window->viewport_height * (1.f + height - ystart) / 2.f;
GLfloat title_bar_height = 0;
if (window->title && PyUnicode_Check(window->title)) title_bar_height = render_window_title(
os_window, screen, xstart, ystart, width, window, left, right);
if (title_bar_height > 0) {
ystart -= title_bar_height;
top = os_window->viewport_height * (1.f - ystart) / 2.f;
bottom = os_window->viewport_height * (1.f + height - ystart) / 2.f;
}
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); // BLEND_PREMULT
bind_program(SEVEN_SEGMENT_PROGRAM);
glUniform4f(seven_segment_program_layout.edges_location, xstart, ystart - height, xstart + width, ystart);
glUniform4f(seven_segment_program_layout.area_bounds_location, left, top, right - left, bottom - top);
color_type digit_color = colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.highlight_bg, screen->color_profile->configured.highlight_bg);
@ -621,31 +694,6 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
glDisable(GL_BLEND);
}
static void
set_cell_uniforms(float current_inactive_text_alpha, bool force) {
if (!cell_uniform_data.constants_set || force) {
cell_uniform_data.gploc = glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "inactive_text_alpha");
cell_uniform_data.gpploc = glGetUniformLocation(program_id(GRAPHICS_PREMULT_PROGRAM), "inactive_text_alpha");
cell_uniform_data.cploc = glGetUniformLocation(program_id(CELL_PROGRAM), "inactive_text_alpha");
cell_uniform_data.cfploc = glGetUniformLocation(program_id(CELL_FG_PROGRAM), "inactive_text_alpha");
cell_uniform_data.amask_premult_loc = glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "alpha_mask_premult");
#define S(prog, name, val, type) { bind_program(prog); glUniform##type(glGetUniformLocation(program_id(prog), #name), val); }
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
S(CELL_BG_PROGRAM, defaultbg, OPT(background), 1f);
#undef S
cell_uniform_data.constants_set = true;
}
if (current_inactive_text_alpha != cell_uniform_data.prev_inactive_text_alpha || force) {
cell_uniform_data.prev_inactive_text_alpha = current_inactive_text_alpha;
#define S(prog, loc) { bind_program(prog); glUniform1f(cell_uniform_data.loc, current_inactive_text_alpha); }
S(CELL_PROGRAM, cploc); S(CELL_FG_PROGRAM, cfploc); S(GRAPHICS_PROGRAM, gploc); S(GRAPHICS_PREMULT_PROGRAM, gpploc);
#undef S
}
}
void
blank_canvas(float background_opacity, color_type color) {
// See https://github.com/glfw/glfw/issues/1538 for why we use pre-multiplied alpha

View File

@ -287,6 +287,7 @@ update_os_window_title(OSWindow *os_window) {
static void
destroy_window(Window *w) {
Py_CLEAR(w->render_data.screen); Py_CLEAR(w->title);
free(w->title_bar_data.buf); w->title_bar_data.buf = NULL;
release_gpu_resources_for_window(w);
}

View File

@ -123,6 +123,11 @@ typedef struct {
ClickQueue click_queues[8];
monotonic_t last_drag_scroll_at;
uint32_t last_special_key_pressed;
struct {
unsigned width, height;
uint8_t *buf;
PyObject *last_drawn_title_object_id;
} title_bar_data;
} Window;
typedef struct {
@ -313,3 +318,4 @@ const char* format_mods(unsigned mods);
void send_pending_click_to_window_id(id_type, void*);
void send_pending_click_to_window(Window*, void*);
void get_platform_dependent_config_values(void *glfw_window);
bool draw_window_title(OSWindow *window, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height);