More work on per window logo
This commit is contained in:
parent
e04919098f
commit
3d2877eeb9
8 changed files with 168 additions and 20 deletions
|
|
@ -65,9 +65,9 @@ typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOC
|
|||
typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
||||
typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
||||
typedef enum { TILING, SCALED, MIRRORED, CLAMPED } BackgroundImageLayout;
|
||||
typedef struct {
|
||||
float x, y;
|
||||
} BackgroundImageAnchor;
|
||||
typedef struct ImageAnchorPosition {
|
||||
float canvas_x, canvas_y, image_x, image_y;
|
||||
} ImageAnchorPosition;
|
||||
|
||||
#define MAX_CHILDREN 512
|
||||
#define BLANK_CHAR 0
|
||||
|
|
|
|||
|
|
@ -541,6 +541,7 @@ make_os_window_context_current(OSWindow *w) {
|
|||
GLFWwindow *current_context = glfwGetCurrentContext();
|
||||
if (w->handle != current_context) {
|
||||
glfwMakeContextCurrent(w->handle);
|
||||
global_state.current_opengl_context_id = w->id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -870,6 +871,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
w->cursor_blink_zero_time = now;
|
||||
w->last_mouse_activity_at = now;
|
||||
w->is_semi_transparent = is_semi_transparent;
|
||||
global_state.current_opengl_context_id = w->id;
|
||||
if (want_semi_transparent && !w->is_semi_transparent) {
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
|
|
|
|||
|
|
@ -78,19 +78,19 @@ bglayout(PyObject *layout_name) {
|
|||
return TILING;
|
||||
}
|
||||
|
||||
static BackgroundImageAnchor
|
||||
static ImageAnchorPosition
|
||||
bganchor(PyObject *anchor_name) {
|
||||
const char *name = PyUnicode_AsUTF8(anchor_name);
|
||||
BackgroundImageAnchor anchor = { .x = 0.5f, .y = 0.5f };
|
||||
ImageAnchorPosition anchor = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
if (strstr(name, "top") != NULL) {
|
||||
anchor.y = 0.0f;
|
||||
anchor.canvas_y = 0.f; anchor.image_y = 0.f;
|
||||
} else if (strstr(name, "bottom") != NULL) {
|
||||
anchor.y = 1.0f;
|
||||
anchor.canvas_y = 1.f; anchor.image_y = 1.f;
|
||||
}
|
||||
if (strstr(name, "left") != NULL) {
|
||||
anchor.x = 0.0f;
|
||||
anchor.canvas_x = 0.f; anchor.image_x = 0.f;
|
||||
} else if (strstr(name, "right") != NULL) {
|
||||
anchor.x = 1.0f;
|
||||
anchor.canvas_x = 1.f; anchor.image_x = 1.f;
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "gl.h"
|
||||
#include "colors.h"
|
||||
#include <stddef.h>
|
||||
#include "window_logo.h"
|
||||
|
||||
#define BLEND_ONTO_OPAQUE glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blending onto opaque colors
|
||||
#define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors
|
||||
|
|
@ -578,6 +579,19 @@ render_window_title(OSWindow *os_window, Screen *screen UNUSED, GLfloat xstart,
|
|||
return 2.f * (GLfloat)bar_height / (GLfloat)os_window->viewport_height;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_window_logo(int program, OSWindow *os_window, const WindowLogoRenderData *wl, GLfloat window_left_gl, GLfloat window_top_gl, GLfloat window_width_gl, GLfloat window_height_gl) {
|
||||
GLfloat logo_width_gl = 2.f * ((float)wl->instance->width) / os_window->viewport_width;
|
||||
GLfloat logo_height_gl = 2.f * ((float)wl->instance->height) / os_window->viewport_height;
|
||||
GLfloat logo_left_gl = window_left_gl + window_width_gl * wl->position.canvas_x - logo_width_gl * wl->position.image_x;
|
||||
GLfloat logo_top_gl = window_top_gl - window_height_gl * wl->position.canvas_y + logo_height_gl * wl->position.image_y;
|
||||
static ImageRenderData ird = {.group_count=1};
|
||||
ird.texture_id = wl->instance->texture_id;
|
||||
gpu_data_for_image(&ird, logo_left_gl, logo_top_gl, logo_left_gl + logo_width_gl, logo_top_gl - logo_height_gl);
|
||||
send_graphics_data_to_gpu(1, os_window->gvao_idx, &ird);
|
||||
draw_graphics(program, 0, os_window->gvao_idx, &ird, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height, Window *window, GLfloat dx, GLfloat dy) {
|
||||
GLfloat left = os_window->viewport_width * (xstart + 1.f) / 2.f;
|
||||
|
|
@ -652,7 +666,7 @@ draw_visual_bell_flash(GLfloat intensity, GLfloat xstart, GLfloat ystart, GLfloa
|
|||
}
|
||||
|
||||
static void
|
||||
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *w, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height) {
|
||||
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *w, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height, const WindowLogoRenderData *wl) {
|
||||
glEnable(GL_BLEND);
|
||||
BLEND_ONTO_OPAQUE;
|
||||
|
||||
|
|
@ -667,10 +681,11 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWind
|
|||
BLEND_ONTO_OPAQUE;
|
||||
}
|
||||
|
||||
if (screen->grman->num_of_below_refs || has_bgimage(w)) {
|
||||
if (screen->grman->num_of_below_refs || has_bgimage(w) || wl) {
|
||||
if (wl) draw_window_logo(GRAPHICS_PROGRAM, w, wl, xstart, ystart, width, height);
|
||||
bind_program(CELL_BG_PROGRAM);
|
||||
if (screen->grman->num_of_below_refs) draw_graphics(
|
||||
GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
||||
bind_program(CELL_BG_PROGRAM);
|
||||
// draw background for non-default bg cells
|
||||
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 2);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
|
|
@ -692,7 +707,7 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWind
|
|||
}
|
||||
|
||||
static void
|
||||
draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *os_window, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height) {
|
||||
draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *os_window, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height, const WindowLogoRenderData *wl) {
|
||||
if (OPT(background_tint) > 0.f) {
|
||||
glEnable(GL_BLEND);
|
||||
BLEND_PREMULT;
|
||||
|
|
@ -722,7 +737,8 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||
glEnable(GL_BLEND);
|
||||
BLEND_PREMULT;
|
||||
|
||||
if (screen->grman->num_of_below_refs || has_bgimage(os_window)) {
|
||||
if (screen->grman->num_of_below_refs || has_bgimage(os_window) || wl) {
|
||||
if (wl) draw_window_logo(GRAPHICS_PREMULT_PROGRAM, os_window, wl, xstart, ystart, width, height);
|
||||
if (screen->grman->num_of_below_refs) draw_graphics(
|
||||
GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
||||
bind_program(CELL_BG_PROGRAM);
|
||||
|
|
@ -841,13 +857,19 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
|||
(GLsizei)roundf(SCALE(height, h / 2.f)) // height
|
||||
);
|
||||
#undef SCALE
|
||||
bool has_underlying_image = has_bgimage(os_window);
|
||||
WindowLogoRenderData *wl = &window->window_logo;
|
||||
if (wl->instance && wl->instance->load_from_disk_ok) {
|
||||
has_underlying_image = true;
|
||||
set_on_gpu_state(window->window_logo.instance, true);
|
||||
} else wl = NULL;
|
||||
if (os_window->is_semi_transparent) {
|
||||
if (screen->grman->count || has_bgimage(os_window)) draw_cells_interleaved_premult(
|
||||
vao_idx, gvao_idx, screen, os_window, xstart, ystart, w, h);
|
||||
if (screen->grman->count || has_underlying_image) draw_cells_interleaved_premult(
|
||||
vao_idx, gvao_idx, screen, os_window, xstart, ystart, w, h, wl);
|
||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||
} else {
|
||||
if (screen->grman->num_of_negative_refs || screen->grman->num_of_below_refs || has_bgimage(os_window)) draw_cells_interleaved(
|
||||
vao_idx, gvao_idx, screen, os_window, xstart, ystart, w, h);
|
||||
if (screen->grman->num_of_negative_refs || screen->grman->num_of_below_refs || has_underlying_image) draw_cells_interleaved(
|
||||
vao_idx, gvao_idx, screen, os_window, xstart, ystart, w, h, wl);
|
||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -224,12 +224,30 @@ release_gpu_resources_for_window(Window *w) {
|
|||
w->render_data.gvao_idx = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
set_default_window_logo(Window *w) {
|
||||
if (OPT(default_window_logo)) {
|
||||
WindowLogo *wl = find_or_create_window_logo(&global_state.all_window_logos, OPT(default_window_logo));
|
||||
if (wl) {
|
||||
w->window_logo.instance = wl;
|
||||
w->window_logo.position = OPT(window_logo_position);
|
||||
} else if (PyErr_Occurred()) {
|
||||
log_error("Failed to load default window logo: %s", OPT(default_window_logo));
|
||||
PyErr_Print();
|
||||
}
|
||||
} else {
|
||||
decref_window_logo(&global_state.all_window_logos, &w->window_logo.instance);
|
||||
}
|
||||
w->window_logo.using_default = true;
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_window(Window *w, PyObject *title, bool init_gpu_resources) {
|
||||
w->id = ++global_state.window_id_counter;
|
||||
w->visible = true;
|
||||
w->title = title;
|
||||
Py_XINCREF(title);
|
||||
set_default_window_logo(w);
|
||||
if (init_gpu_resources) create_gpu_resources_for_window(w);
|
||||
else {
|
||||
w->render_data.vao_idx = -1;
|
||||
|
|
@ -290,6 +308,7 @@ 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);
|
||||
decref_window_logo(&global_state.all_window_logos, &w->window_logo.instance);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "data-types.h"
|
||||
#include "screen.h"
|
||||
#include "monotonic.h"
|
||||
#include "window_logo.h"
|
||||
|
||||
#define OPT(name) global_state.opts.name
|
||||
|
||||
|
|
@ -47,7 +48,7 @@ typedef struct {
|
|||
|
||||
char *background_image, *default_window_logo;
|
||||
BackgroundImageLayout background_image_layout;
|
||||
BackgroundImageAnchor window_logo_position;
|
||||
ImageAnchorPosition window_logo_position;
|
||||
bool background_image_linear;
|
||||
float background_tint;
|
||||
|
||||
|
|
@ -81,6 +82,12 @@ typedef struct {
|
|||
} tab_bar_margin_height;
|
||||
} Options;
|
||||
|
||||
typedef struct WindowLogoRenderData {
|
||||
WindowLogo *instance;
|
||||
ImageAnchorPosition position;
|
||||
bool using_default;
|
||||
} WindowLogoRenderData;
|
||||
|
||||
typedef struct {
|
||||
ssize_t vao_idx, gvao_idx;
|
||||
float xstart, ystart, dx, dy;
|
||||
|
|
@ -116,6 +123,7 @@ typedef struct {
|
|||
CursorShape last_cursor_shape;
|
||||
PyObject *title;
|
||||
ScreenRenderData render_data;
|
||||
WindowLogoRenderData window_logo;
|
||||
MousePosition mouse_pos;
|
||||
struct {
|
||||
unsigned int left, top, right, bottom;
|
||||
|
|
@ -205,7 +213,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
Options opts;
|
||||
|
||||
id_type os_window_id_counter, tab_id_counter, window_id_counter;
|
||||
id_type os_window_id_counter, tab_id_counter, window_id_counter, current_opengl_context_id;
|
||||
PyObject *boss;
|
||||
BackgroundImage *bgimage;
|
||||
OSWindow *os_windows;
|
||||
|
|
@ -222,6 +230,7 @@ typedef struct {
|
|||
int active_drag_button;
|
||||
CloseRequest quit_request;
|
||||
bool redirect_mouse_handling;
|
||||
WindowLogo *all_window_logos;
|
||||
} GlobalState;
|
||||
|
||||
extern GlobalState global_state;
|
||||
|
|
|
|||
67
kitty/window_logo.c
Normal file
67
kitty/window_logo.c
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* window_logo.c
|
||||
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "window_logo.h"
|
||||
#include "state.h"
|
||||
|
||||
|
||||
typedef struct WindowLogoItem {
|
||||
WindowLogoHead
|
||||
unsigned int refcnt;
|
||||
char *path;
|
||||
UT_hash_handle hh;
|
||||
} WindowLogoItem;
|
||||
|
||||
|
||||
static void
|
||||
free_window_logo(WindowLogoItem **head, WindowLogoItem **itemref) {
|
||||
WindowLogoItem *item = *itemref;
|
||||
free(item->path);
|
||||
free(item->bitmap);
|
||||
if (item->texture_id) free_texture(&item->texture_id);
|
||||
HASH_DEL(*head, item);
|
||||
free(item); itemref = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
send_logo_to_gpu(WindowLogoItem *s) {
|
||||
send_image_to_gpu(&s->texture_id, s->bitmap, s->width, s->height, false, true, true, REPEAT_CLAMP);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_on_gpu_state(WindowLogo *x, bool on_gpu) {
|
||||
WindowLogoItem *s = (WindowLogoItem*)x;
|
||||
if (s->load_from_disk_ok) {
|
||||
if (on_gpu) { if (!s->texture_id) send_logo_to_gpu(s); }
|
||||
else if (s->texture_id) free_texture(&s->texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
WindowLogo*
|
||||
find_or_create_window_logo(WindowLogo **head_, const char *path) {
|
||||
WindowLogoItem **head = (WindowLogoItem**)head_;
|
||||
WindowLogoItem *s = NULL;
|
||||
HASH_FIND_STR(*head, path, s);
|
||||
if (s) return (WindowLogo*)s;
|
||||
s = calloc(1, sizeof *s);
|
||||
size_t size;
|
||||
if (!s) { PyErr_NoMemory(); return NULL; }
|
||||
s->path = strdup(path);
|
||||
if (!s->path) { free(s->bitmap); free(s); PyErr_NoMemory(); return NULL; }
|
||||
if (png_path_to_bitmap(path, &s->bitmap, &s->width, &s->height, &size)) s->load_from_disk_ok = true;
|
||||
s->refcnt++;
|
||||
HASH_ADD_KEYPTR(hh, *head, s->path, strlen(s->path), s);
|
||||
return (WindowLogo*)s;
|
||||
}
|
||||
|
||||
void
|
||||
decref_window_logo(WindowLogo **head_, WindowLogo** logo) {
|
||||
WindowLogoItem **head = (WindowLogoItem**)head_;
|
||||
WindowLogoItem **s = (WindowLogoItem**)logo;
|
||||
if (*s) { if ((*s)->refcnt < 2) free_window_logo(head, s); else (*s)->refcnt--; }
|
||||
}
|
||||
29
kitty/window_logo.h
Normal file
29
kitty/window_logo.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kitty-uthash.h"
|
||||
|
||||
#define WindowLogoHead \
|
||||
unsigned int height, width; \
|
||||
bool load_from_disk_ok; \
|
||||
uint32_t texture_id; \
|
||||
uint8_t* bitmap;
|
||||
|
||||
|
||||
typedef struct WindowLogo {
|
||||
WindowLogoHead
|
||||
} WindowLogo;
|
||||
|
||||
WindowLogo*
|
||||
find_or_create_window_logo(WindowLogo **head, const char *path);
|
||||
|
||||
void
|
||||
decref_window_logo(WindowLogo **head, WindowLogo** logo);
|
||||
|
||||
void
|
||||
set_on_gpu_state(WindowLogo *logo, bool on_gpu);
|
||||
Loading…
Reference in a new issue