mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-19 14:33:16 -04:00
feat: add dispatch togglejump
This commit is contained in:
parent
5c6cf39901
commit
bb909cc2ed
10 changed files with 544 additions and 147 deletions
|
|
@ -161,6 +161,7 @@ bindr=Super,Super_L,spawn,rofi -show run
|
||||||
| `reload_config` | - | Hot-reload configuration. |
|
| `reload_config` | - | Hot-reload configuration. |
|
||||||
| `quit` | - | Exit mangowm. |
|
| `quit` | - | Exit mangowm. |
|
||||||
| `toggleoverview` | - | Toggle overview mode. |
|
| `toggleoverview` | - | Toggle overview mode. |
|
||||||
|
| `toggleojump` | - | Toggle overview with jump mode. |
|
||||||
| `create_virtual_output` | - | Create a headless monitor (for VNC/Sunshine). |
|
| `create_virtual_output` | - | Create a headless monitor (for VNC/Sunshine). |
|
||||||
| `destroy_all_virtual_output` | - | Destroy all virtual monitors. |
|
| `destroy_all_virtual_output` | - | Destroy all virtual monitors. |
|
||||||
| `toggleoverlay` | - | Toggle overlay state for the focused window. |
|
| `toggleoverlay` | - | Toggle overlay state for the focused window. |
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,18 @@ You can also color-code windows based on their state:
|
||||||
|
|
||||||
> **Tip:** For scratchpad window sizing, see [Scratchpad](/docs/window-management/scratchpad) configuration.
|
> **Tip:** For scratchpad window sizing, see [Scratchpad](/docs/window-management/scratchpad) configuration.
|
||||||
|
|
||||||
|
### Overview Jump Mode
|
||||||
|
| Setting | Default | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `jump_hit_fg_color` | `0xc4939dff` | label text color. |
|
||||||
|
| `jump_hit_bg_color` | `0x201b14ff` | label background color.
|
||||||
|
| `jump_hit_border_color` | `0x8BAA9Bff` | label border color.
|
||||||
|
| `jump_hit_border_width` | `4` | label border width.
|
||||||
|
| `jump_hit_corner_radius` | `5` | label corner radius.
|
||||||
|
| `jump_hit_padding_x` | `10` | label horizontal padding.
|
||||||
|
| `jump_hit_padding_y` | `10` | label vertical padding.
|
||||||
|
| `jump_hit_font_desc` | `monospace Bold 24` | label font set.|
|
||||||
|
|
||||||
## Cursor Theme
|
## Cursor Theme
|
||||||
|
|
||||||
Set the size and theme of your mouse cursor.
|
Set the size and theme of your mouse cursor.
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ pcre2_dep = dependency('libpcre2-8')
|
||||||
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
||||||
pixman_dep = dependency('pixman-1')
|
pixman_dep = dependency('pixman-1')
|
||||||
cjson_dep = dependency('libcjson')
|
cjson_dep = dependency('libcjson')
|
||||||
cairo_dep = dependency('cairo')
|
|
||||||
pango_dep = dependency('pango')
|
|
||||||
pangocairo_dep = dependency('pangocairo')
|
pangocairo_dep = dependency('pangocairo')
|
||||||
|
|
||||||
# version info
|
# version info
|
||||||
|
|
@ -113,8 +111,6 @@ executable('mango',
|
||||||
pcre2_dep,
|
pcre2_dep,
|
||||||
pixman_dep,
|
pixman_dep,
|
||||||
cjson_dep,
|
cjson_dep,
|
||||||
cairo_dep,
|
|
||||||
pango_dep,
|
|
||||||
pangocairo_dep,
|
pangocairo_dep,
|
||||||
],
|
],
|
||||||
install : true,
|
install : true,
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,7 @@ typedef struct {
|
||||||
int32_t enable_hotarea;
|
int32_t enable_hotarea;
|
||||||
int32_t ov_tab_mode;
|
int32_t ov_tab_mode;
|
||||||
int32_t ov_no_resize;
|
int32_t ov_no_resize;
|
||||||
|
|
||||||
int32_t overviewgappi;
|
int32_t overviewgappi;
|
||||||
int32_t overviewgappo;
|
int32_t overviewgappo;
|
||||||
uint32_t cursor_hide_timeout;
|
uint32_t cursor_hide_timeout;
|
||||||
|
|
@ -407,6 +408,7 @@ typedef struct {
|
||||||
|
|
||||||
struct xkb_context *ctx;
|
struct xkb_context *ctx;
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
|
JumphitData jumhitdata;
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
typedef int32_t (*FuncType)(const Arg *);
|
typedef int32_t (*FuncType)(const Arg *);
|
||||||
|
|
@ -1030,6 +1032,9 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
} else if (strcmp(func_name, "toggleoverview") == 0) {
|
} else if (strcmp(func_name, "toggleoverview") == 0) {
|
||||||
func = toggleoverview;
|
func = toggleoverview;
|
||||||
(*arg).i = atoi(arg_value);
|
(*arg).i = atoi(arg_value);
|
||||||
|
} else if (strcmp(func_name, "togglejump") == 0) {
|
||||||
|
func = togglejump;
|
||||||
|
(*arg).i = atoi(arg_value);
|
||||||
} else if (strcmp(func_name, "set_proportion") == 0) {
|
} else if (strcmp(func_name, "set_proportion") == 0) {
|
||||||
func = set_proportion;
|
func = set_proportion;
|
||||||
(*arg).f = atof(arg_value);
|
(*arg).f = atof(arg_value);
|
||||||
|
|
@ -1758,6 +1763,50 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->cursor_size = atoi(value);
|
config->cursor_size = atoi(value);
|
||||||
} else if (strcmp(key, "cursor_theme") == 0) {
|
} else if (strcmp(key, "cursor_theme") == 0) {
|
||||||
config->cursor_theme = strdup(value);
|
config->cursor_theme = strdup(value);
|
||||||
|
} else if (strcmp(key, "jump_hit_fg_color") == 0) {
|
||||||
|
int64_t color = parse_color(value);
|
||||||
|
if (color == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid jump_hit_fg_color "
|
||||||
|
"format: %s\n",
|
||||||
|
value);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
convert_hex_to_rgba(config->jumhitdata.fg_color, color);
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "jump_hit_font_desc") == 0) {
|
||||||
|
config->jumhitdata.font_desc = strdup(value);
|
||||||
|
} else if (strcmp(key, "jump_hit_bg_color") == 0) {
|
||||||
|
int64_t color = parse_color(value);
|
||||||
|
if (color == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid jump_hit_bg_color "
|
||||||
|
"format: %s\n",
|
||||||
|
value);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
convert_hex_to_rgba(config->jumhitdata.bg_color, color);
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "jump_hit_border_color") == 0) {
|
||||||
|
int64_t color = parse_color(value);
|
||||||
|
if (color == -1) {
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid jump_hit_border_color "
|
||||||
|
"format: %s\n",
|
||||||
|
value);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
convert_hex_to_rgba(config->jumhitdata.border_color, color);
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "jump_hit_border_width") == 0) {
|
||||||
|
config->jumhitdata.border_width = CLAMP_FLOAT(atoi(value), 0, 100);
|
||||||
|
} else if (strcmp(key, "jump_hit_corner_radius") == 0) {
|
||||||
|
config->jumhitdata.corner_radius = CLAMP_FLOAT(atoi(value), 0, 100);
|
||||||
|
} else if (strcmp(key, "jump_hit_padding_x") == 0) {
|
||||||
|
config->jumhitdata.padding_x = CLAMP_FLOAT(atoi(value), 0, 100);
|
||||||
|
} else if (strcmp(key, "jump_hit_padding_y") == 0) {
|
||||||
|
config->jumhitdata.padding_y = CLAMP_FLOAT(atoi(value), 0, 100);
|
||||||
} else if (strcmp(key, "disable_while_typing") == 0) {
|
} else if (strcmp(key, "disable_while_typing") == 0) {
|
||||||
config->disable_while_typing = atoi(value);
|
config->disable_while_typing = atoi(value);
|
||||||
} else if (strcmp(key, "left_handed") == 0) {
|
} else if (strcmp(key, "left_handed") == 0) {
|
||||||
|
|
@ -3247,6 +3296,11 @@ void free_config(void) {
|
||||||
config.cursor_theme = NULL;
|
config.cursor_theme = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.jumhitdata.font_desc) {
|
||||||
|
free((void *)config.jumhitdata.font_desc);
|
||||||
|
config.jumhitdata.font_desc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.tablet_map_to_mon) {
|
if (config.tablet_map_to_mon) {
|
||||||
free(config.tablet_map_to_mon);
|
free(config.tablet_map_to_mon);
|
||||||
config.tablet_map_to_mon = NULL;
|
config.tablet_map_to_mon = NULL;
|
||||||
|
|
@ -3437,6 +3491,15 @@ void override_config(void) {
|
||||||
config.focused_opacity = CLAMP_FLOAT(config.focused_opacity, 0.0f, 1.0f);
|
config.focused_opacity = CLAMP_FLOAT(config.focused_opacity, 0.0f, 1.0f);
|
||||||
config.unfocused_opacity =
|
config.unfocused_opacity =
|
||||||
CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f);
|
CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
config.jumhitdata.border_width =
|
||||||
|
CLAMP_INT(config.jumhitdata.border_width, 0, 100);
|
||||||
|
config.jumhitdata.corner_radius =
|
||||||
|
CLAMP_INT(config.jumhitdata.corner_radius, 0, 100);
|
||||||
|
config.jumhitdata.padding_x =
|
||||||
|
CLAMP_INT(config.jumhitdata.padding_x, 0, 100);
|
||||||
|
config.jumhitdata.padding_y =
|
||||||
|
CLAMP_INT(config.jumhitdata.padding_y, 0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_value_default() {
|
void set_value_default() {
|
||||||
|
|
@ -3475,7 +3538,6 @@ void set_value_default() {
|
||||||
config.log_level = WLR_ERROR;
|
config.log_level = WLR_ERROR;
|
||||||
config.numlockon = 0;
|
config.numlockon = 0;
|
||||||
config.capslock = 0;
|
config.capslock = 0;
|
||||||
|
|
||||||
config.ov_tab_mode = 1;
|
config.ov_tab_mode = 1;
|
||||||
config.ov_no_resize = 1;
|
config.ov_no_resize = 1;
|
||||||
config.hotarea_size = 10;
|
config.hotarea_size = 10;
|
||||||
|
|
@ -3613,6 +3675,23 @@ void set_value_default() {
|
||||||
config.animation_curve_opafadeout[2] = 0.5;
|
config.animation_curve_opafadeout[2] = 0.5;
|
||||||
config.animation_curve_opafadeout[3] = 0.5;
|
config.animation_curve_opafadeout[3] = 0.5;
|
||||||
|
|
||||||
|
config.jumhitdata.fg_color[0] = 0xc4 / 255.0f;
|
||||||
|
config.jumhitdata.fg_color[1] = 0x93 / 255.0f;
|
||||||
|
config.jumhitdata.fg_color[2] = 0x9d / 255.0f;
|
||||||
|
config.jumhitdata.fg_color[3] = 1.0f;
|
||||||
|
config.jumhitdata.bg_color[0] = 0x32 / 255.0f;
|
||||||
|
config.jumhitdata.bg_color[1] = 0x32 / 255.0f;
|
||||||
|
config.jumhitdata.bg_color[2] = 0x32 / 255.0f;
|
||||||
|
config.jumhitdata.bg_color[3] = 1.0f;
|
||||||
|
config.jumhitdata.border_color[0] = 0x8b / 255.0f;
|
||||||
|
config.jumhitdata.border_color[1] = 0xaa / 255.0f;
|
||||||
|
config.jumhitdata.border_color[2] = 0x9b / 255.0f;
|
||||||
|
config.jumhitdata.border_color[3] = 1.0f;
|
||||||
|
config.jumhitdata.border_width = 4;
|
||||||
|
config.jumhitdata.corner_radius = 5;
|
||||||
|
config.jumhitdata.padding_x = 10;
|
||||||
|
config.jumhitdata.padding_y = 10;
|
||||||
|
|
||||||
config.rootcolor[0] = 0x32 / 255.0f;
|
config.rootcolor[0] = 0x32 / 255.0f;
|
||||||
config.rootcolor[1] = 0x32 / 255.0f;
|
config.rootcolor[1] = 0x32 / 255.0f;
|
||||||
config.rootcolor[2] = 0x32 / 255.0f;
|
config.rootcolor[2] = 0x32 / 255.0f;
|
||||||
|
|
@ -3725,6 +3804,7 @@ bool parse_config(void) {
|
||||||
config.tag_rules = NULL;
|
config.tag_rules = NULL;
|
||||||
config.tag_rules_count = 0;
|
config.tag_rules_count = 0;
|
||||||
config.cursor_theme = NULL;
|
config.cursor_theme = NULL;
|
||||||
|
config.jumhitdata.font_desc = NULL;
|
||||||
config.tablet_map_to_mon = NULL;
|
config.tablet_map_to_mon = NULL;
|
||||||
strcpy(config.keymode, "default");
|
strcpy(config.keymode, "default");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ int32_t restore_minimized(const Arg *arg);
|
||||||
int32_t toggle_scratchpad(const Arg *arg);
|
int32_t toggle_scratchpad(const Arg *arg);
|
||||||
int32_t focusdir(const Arg *arg);
|
int32_t focusdir(const Arg *arg);
|
||||||
int32_t toggleoverview(const Arg *arg);
|
int32_t toggleoverview(const Arg *arg);
|
||||||
|
int32_t togglejump(const Arg *arg);
|
||||||
int32_t set_proportion(const Arg *arg);
|
int32_t set_proportion(const Arg *arg);
|
||||||
int32_t switch_proportion_preset(const Arg *arg);
|
int32_t switch_proportion_preset(const Arg *arg);
|
||||||
int32_t zoom(const Arg *arg);
|
int32_t zoom(const Arg *arg);
|
||||||
|
|
|
||||||
|
|
@ -1737,6 +1737,10 @@ int32_t toggleoverview(const Arg *arg) {
|
||||||
uint32_t target;
|
uint32_t target;
|
||||||
uint32_t visible_client_number = 0;
|
uint32_t visible_client_number = 0;
|
||||||
|
|
||||||
|
if (!selmon->isoverview && selmon->is_jump_mode) {
|
||||||
|
finish_jump_mode(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
if (selmon->isoverview) {
|
if (selmon->isoverview) {
|
||||||
wl_list_for_each(c, &clients, link) if (c && c->mon == selmon &&
|
wl_list_for_each(c, &clients, link) if (c && c->mon == selmon &&
|
||||||
!client_is_unmanaged(c) &&
|
!client_is_unmanaged(c) &&
|
||||||
|
|
@ -1781,6 +1785,7 @@ int32_t toggleoverview(const Arg *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
selmon->tagset[selmon->seltags] = target;
|
selmon->tagset[selmon->seltags] = target;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c && c->mon == selmon && !c->iskilling &&
|
if (c && c->mon == selmon && !c->iskilling &&
|
||||||
|
|
@ -1794,6 +1799,24 @@ int32_t toggleoverview(const Arg *arg) {
|
||||||
view(&(Arg){.ui = target}, false);
|
view(&(Arg){.ui = target}, false);
|
||||||
fix_mon_tagset_from_overview(selmon);
|
fix_mon_tagset_from_overview(selmon);
|
||||||
refresh_monitors_workspaces_status(selmon);
|
refresh_monitors_workspaces_status(selmon);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t togglejump(const Arg *arg) {
|
||||||
|
if (!selmon)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!selmon->isoverview) {
|
||||||
|
begin_jump_mode(selmon);
|
||||||
|
toggleoverview(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selmon->isoverview) {
|
||||||
|
toggleoverview(arg);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,140 +1,322 @@
|
||||||
#include "text-node.h"
|
#include "text-node.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <pango/pangocairo.h>
|
|
||||||
#include <wlr/interfaces/wlr_buffer.h>
|
|
||||||
#include <wayland-server-core.h>
|
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/interfaces/wlr_buffer.h>
|
||||||
|
|
||||||
// 自定义 wlr_buffer,用于将 Cairo Surface 包装并注入 wlr_scene
|
// 自定义 wlr_buffer,用于将 Cairo Surface 包装并注入 wlr_scene
|
||||||
struct mango_text_buffer {
|
struct mango_text_buffer {
|
||||||
struct wlr_buffer base;
|
struct wlr_buffer base;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 全局字体描述缓存
|
||||||
|
static GHashTable *font_desc_cache = NULL;
|
||||||
|
|
||||||
|
static PangoFontDescription *get_cached_font_desc(const char *font_desc) {
|
||||||
|
if (!font_desc_cache) {
|
||||||
|
font_desc_cache =
|
||||||
|
g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
|
||||||
|
(GDestroyNotify)pango_font_description_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
PangoFontDescription *desc =
|
||||||
|
g_hash_table_lookup(font_desc_cache, font_desc);
|
||||||
|
if (!desc) {
|
||||||
|
desc = pango_font_description_from_string(font_desc);
|
||||||
|
g_hash_table_insert(font_desc_cache, g_strdup(font_desc), desc);
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mango_text_global_finish(void) {
|
||||||
|
if (font_desc_cache) {
|
||||||
|
g_hash_table_destroy(font_desc_cache);
|
||||||
|
font_desc_cache = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wlr_buffer 实现
|
||||||
static void text_buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
static void text_buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||||
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
||||||
cairo_surface_destroy(buf->surface);
|
cairo_surface_destroy(buf->surface);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool text_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
|
static bool text_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
|
||||||
uint32_t flags,
|
uint32_t flags, void **data,
|
||||||
void **data,
|
uint32_t *format,
|
||||||
uint32_t *format,
|
size_t *stride) {
|
||||||
size_t *stride) {
|
(void)flags;
|
||||||
(void)flags; // 该参数当前无需使用
|
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
||||||
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
*data = cairo_image_surface_get_data(buf->surface);
|
||||||
*data = cairo_image_surface_get_data(buf->surface);
|
*format = DRM_FORMAT_ARGB8888;
|
||||||
*format = DRM_FORMAT_ARGB8888;
|
*stride = cairo_image_surface_get_stride(buf->surface);
|
||||||
*stride = cairo_image_surface_get_stride(buf->surface);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
|
static void text_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {}
|
||||||
// Cairo 表面数据在 flush 后稳定,此处无需额外操作
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wlr_buffer_impl text_buffer_impl = {
|
static const struct wlr_buffer_impl text_buffer_impl = {
|
||||||
.destroy = text_buffer_destroy,
|
.destroy = text_buffer_destroy,
|
||||||
.begin_data_ptr_access = text_buffer_begin_data_ptr_access,
|
.begin_data_ptr_access = text_buffer_begin_data_ptr_access,
|
||||||
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent) {
|
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent,
|
||||||
struct mango_text_node *node = calloc(1, sizeof(*node));
|
JumphitData data) {
|
||||||
if (!node) return NULL;
|
struct mango_text_node *node = calloc(1, sizeof(*node));
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
node->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
node->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
||||||
if (!node->scene_buffer) {
|
if (!node->scene_buffer) {
|
||||||
free(node);
|
free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
// 默认外观:无边框、无背景、无内边距(保持原有行为)
|
||||||
const char *font_desc, float color[4], float scale) {
|
node->fg_color[0] = data.fg_color[0];
|
||||||
if (!node || !text || !font_desc) return;
|
node->fg_color[1] = data.fg_color[1];
|
||||||
if (scale <= 0.0f) scale = 1.0f;
|
node->fg_color[2] = data.fg_color[2];
|
||||||
|
node->fg_color[3] = data.fg_color[3];
|
||||||
|
node->bg_color[0] = data.bg_color[0];
|
||||||
|
node->bg_color[1] = data.bg_color[1];
|
||||||
|
node->bg_color[2] = data.bg_color[2];
|
||||||
|
node->bg_color[3] = data.bg_color[3];
|
||||||
|
node->border_color[0] = data.border_color[0];
|
||||||
|
node->border_color[1] = data.border_color[1];
|
||||||
|
node->border_color[2] = data.border_color[2];
|
||||||
|
node->border_color[3] = data.border_color[3];
|
||||||
|
node->border_width = data.border_width;
|
||||||
|
node->corner_radius = data.corner_radius;
|
||||||
|
node->padding_x = data.padding_x;
|
||||||
|
node->padding_y = data.padding_y;
|
||||||
|
node->font_desc = data.font_desc ? data.font_desc : "monospace Bold 24";
|
||||||
|
|
||||||
// 测量文字像素尺寸
|
return node;
|
||||||
cairo_surface_t *dummy_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
|
||||||
cairo_t *dummy_cr = cairo_create(dummy_surface);
|
|
||||||
PangoContext *dummy_ctx = pango_cairo_create_context(dummy_cr);
|
|
||||||
pango_cairo_context_set_resolution(dummy_ctx, 96.0 * scale);
|
|
||||||
PangoLayout *dummy_layout = pango_layout_new(dummy_ctx);
|
|
||||||
PangoFontDescription *desc = pango_font_description_from_string(font_desc);
|
|
||||||
pango_layout_set_font_description(dummy_layout, desc);
|
|
||||||
pango_layout_set_text(dummy_layout, text, -1);
|
|
||||||
|
|
||||||
int pixel_width, pixel_height;
|
|
||||||
pango_layout_get_pixel_size(dummy_layout, &pixel_width, &pixel_height);
|
|
||||||
|
|
||||||
g_object_unref(dummy_layout);
|
|
||||||
pango_font_description_free(desc);
|
|
||||||
g_object_unref(dummy_ctx);
|
|
||||||
cairo_destroy(dummy_cr);
|
|
||||||
cairo_surface_destroy(dummy_surface);
|
|
||||||
|
|
||||||
if (pixel_width <= 0 || pixel_height <= 0) {
|
|
||||||
wlr_scene_buffer_set_buffer(node->scene_buffer, NULL);
|
|
||||||
node->logical_width = 0;
|
|
||||||
node->logical_height = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建真实大小的 Surface 并绘制文字
|
|
||||||
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pixel_width, pixel_height);
|
|
||||||
cairo_t *cr = cairo_create(surface);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_paint(cr);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
|
||||||
|
|
||||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
|
||||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
|
||||||
PangoLayout *layout = pango_layout_new(ctx);
|
|
||||||
desc = pango_font_description_from_string(font_desc);
|
|
||||||
pango_layout_set_font_description(layout, desc);
|
|
||||||
pango_layout_set_text(layout, text, -1);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, color[0], color[1], color[2], color[3]);
|
|
||||||
pango_cairo_show_layout(cr, layout);
|
|
||||||
cairo_surface_flush(surface);
|
|
||||||
|
|
||||||
// 包装成 wlr_buffer
|
|
||||||
struct mango_text_buffer *buf = calloc(1, sizeof(*buf));
|
|
||||||
if (!buf) {
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
cairo_destroy(cr);
|
|
||||||
g_object_unref(layout);
|
|
||||||
pango_font_description_free(desc);
|
|
||||||
g_object_unref(ctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wlr_buffer_init(&buf->base, &text_buffer_impl, pixel_width, pixel_height);
|
|
||||||
buf->surface = surface;
|
|
||||||
|
|
||||||
// 提交给场景图
|
|
||||||
wlr_scene_buffer_set_buffer(node->scene_buffer, &buf->base);
|
|
||||||
wlr_buffer_drop(&buf->base); // 函数内引用计数 -1,交给场景图管理
|
|
||||||
|
|
||||||
// 设置逻辑大小,实现 HiDPI 缩放
|
|
||||||
node->logical_width = (int)(pixel_width / scale);
|
|
||||||
node->logical_height = (int)(pixel_height / scale);
|
|
||||||
wlr_scene_buffer_set_dest_size(node->scene_buffer, node->logical_width, node->logical_height);
|
|
||||||
|
|
||||||
// 清理绘制资源
|
|
||||||
g_object_unref(layout);
|
|
||||||
pango_font_description_free(desc);
|
|
||||||
g_object_unref(ctx);
|
|
||||||
cairo_destroy(cr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_text_node_destroy(struct mango_text_node *node) {
|
void mango_text_node_destroy(struct mango_text_node *node) {
|
||||||
if (!node) return;
|
if (!node)
|
||||||
wlr_scene_node_destroy(&node->scene_buffer->node);
|
return;
|
||||||
free(node);
|
|
||||||
|
wlr_scene_node_destroy(&node->scene_buffer->node);
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mango_text_node_set_background(struct mango_text_node *node, float r,
|
||||||
|
float g, float b, float a) {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
node->bg_color[0] = r;
|
||||||
|
node->bg_color[1] = g;
|
||||||
|
node->bg_color[2] = b;
|
||||||
|
node->bg_color[3] = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mango_text_node_set_border(struct mango_text_node *node, float r, float g,
|
||||||
|
float b, float a, float width, float radius) {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
node->border_color[0] = r;
|
||||||
|
node->border_color[1] = g;
|
||||||
|
node->border_color[2] = b;
|
||||||
|
node->border_color[3] = a;
|
||||||
|
node->border_width = width > 0.0f ? width : 0.0f;
|
||||||
|
node->corner_radius = radius >= 0.0f ? radius : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mango_text_node_set_padding(struct mango_text_node *node, float pad_x,
|
||||||
|
float pad_y) {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
node->padding_x = pad_x >= 0.0f ? pad_x : 0.0f;
|
||||||
|
node->padding_y = pad_y >= 0.0f ? pad_y : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
||||||
|
double h, double r) {
|
||||||
|
// 使用 Cairo 的标准圆角矩形路径
|
||||||
|
double degrees = G_PI / 180.0;
|
||||||
|
cairo_new_sub_path(cr);
|
||||||
|
cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);
|
||||||
|
cairo_arc(cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees);
|
||||||
|
cairo_arc(cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees);
|
||||||
|
cairo_arc(cr, x + r, y + r, r, 180 * degrees, 270 * degrees);
|
||||||
|
cairo_close_path(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
||||||
|
|
||||||
|
float scale) {
|
||||||
|
if (!node || !text)
|
||||||
|
return;
|
||||||
|
if (scale <= 0.0f)
|
||||||
|
scale = 1.0f;
|
||||||
|
|
||||||
|
const char *font_desc = node->font_desc;
|
||||||
|
PangoFontDescription *desc = get_cached_font_desc(font_desc);
|
||||||
|
|
||||||
|
// 测量文字像素尺寸(无缩放的实际像素)
|
||||||
|
cairo_surface_t *dummy_surface =
|
||||||
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||||
|
cairo_t *dummy_cr = cairo_create(dummy_surface);
|
||||||
|
PangoContext *dummy_ctx = pango_cairo_create_context(dummy_cr);
|
||||||
|
pango_cairo_context_set_resolution(dummy_ctx, 96.0 * scale);
|
||||||
|
PangoLayout *dummy_layout = pango_layout_new(dummy_ctx);
|
||||||
|
pango_layout_set_font_description(dummy_layout, desc);
|
||||||
|
pango_layout_set_text(dummy_layout, text, -1);
|
||||||
|
|
||||||
|
int text_pixel_w, text_pixel_h;
|
||||||
|
pango_layout_get_pixel_size(dummy_layout, &text_pixel_w, &text_pixel_h);
|
||||||
|
|
||||||
|
g_object_unref(dummy_layout);
|
||||||
|
g_object_unref(dummy_ctx);
|
||||||
|
cairo_destroy(dummy_cr);
|
||||||
|
cairo_surface_destroy(dummy_surface);
|
||||||
|
|
||||||
|
if (text_pixel_w <= 0 || text_pixel_h <= 0) {
|
||||||
|
wlr_scene_buffer_set_buffer(node->scene_buffer, NULL);
|
||||||
|
node->logical_width = 0;
|
||||||
|
node->logical_height = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逻辑尺寸:文本的逻辑宽高
|
||||||
|
float logical_text_w = text_pixel_w / scale;
|
||||||
|
float logical_text_h = text_pixel_h / scale;
|
||||||
|
|
||||||
|
// 背景框的逻辑尺寸(包含内边距)
|
||||||
|
float pad_x = node->padding_x;
|
||||||
|
float pad_y = node->padding_y;
|
||||||
|
float box_logical_w = logical_text_w + 2.0f * pad_x;
|
||||||
|
float box_logical_h = logical_text_h + 2.0f * pad_y;
|
||||||
|
|
||||||
|
// 边框相关尺寸(全部以逻辑像素为单位)
|
||||||
|
float border = node->border_width;
|
||||||
|
bool draw_border = (border > 0.0f) && (node->border_color[3] > 0.0f);
|
||||||
|
bool draw_bg = (node->bg_color[3] > 0.0f);
|
||||||
|
|
||||||
|
// 最终 surface 的像素尺寸:背景框 + 两倍边框宽度(边框外扩)
|
||||||
|
int surface_pixel_w = (int)((box_logical_w + 2.0f * border) * scale + 0.5f);
|
||||||
|
int surface_pixel_h = (int)((box_logical_h + 2.0f * border) * scale + 0.5f);
|
||||||
|
|
||||||
|
// 限制最小尺寸以避免 Cairo 错误
|
||||||
|
if (surface_pixel_w < 1)
|
||||||
|
surface_pixel_w = 1;
|
||||||
|
if (surface_pixel_h < 1)
|
||||||
|
surface_pixel_h = 1;
|
||||||
|
|
||||||
|
// 创建绘制表面
|
||||||
|
cairo_surface_t *surface = cairo_image_surface_create(
|
||||||
|
CAIRO_FORMAT_ARGB32, surface_pixel_w, surface_pixel_h);
|
||||||
|
cairo_t *cr = cairo_create(surface);
|
||||||
|
|
||||||
|
// 清空为全透明
|
||||||
|
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_paint(cr);
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
|
|
||||||
|
// --- 计算关键坐标(像素) ---
|
||||||
|
double bg_x = border * scale;
|
||||||
|
double bg_y = border * scale;
|
||||||
|
double bg_w = box_logical_w * scale;
|
||||||
|
double bg_h = box_logical_h * scale;
|
||||||
|
|
||||||
|
double radius = node->corner_radius * scale;
|
||||||
|
// 如果 radius <
|
||||||
|
// 0,表示自动使用半宽半高形成胶囊形状(备选,这里保持简单,默认0不圆角)
|
||||||
|
if (radius < 0) {
|
||||||
|
radius = (bg_w < bg_h ? bg_w : bg_h) / 2.0;
|
||||||
|
}
|
||||||
|
if (radius > bg_w / 2.0)
|
||||||
|
radius = bg_w / 2.0;
|
||||||
|
if (radius > bg_h / 2.0)
|
||||||
|
radius = bg_h / 2.0;
|
||||||
|
|
||||||
|
// 1. 绘制背景
|
||||||
|
if (draw_bg) {
|
||||||
|
cairo_set_source_rgba(cr, node->bg_color[0], node->bg_color[1],
|
||||||
|
node->bg_color[2], node->bg_color[3]);
|
||||||
|
if (radius > 0.0) {
|
||||||
|
draw_rounded_rect(cr, bg_x, bg_y, bg_w, bg_h, radius);
|
||||||
|
cairo_fill(cr);
|
||||||
|
} else {
|
||||||
|
cairo_rectangle(cr, bg_x, bg_y, bg_w, bg_h);
|
||||||
|
cairo_fill(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 绘制文本(偏移 = 边框 + 内边距)
|
||||||
|
cairo_save(cr);
|
||||||
|
cairo_translate(cr, (border + pad_x) * scale, (border + pad_y) * scale);
|
||||||
|
|
||||||
|
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||||
|
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(ctx);
|
||||||
|
pango_layout_set_font_description(layout, desc);
|
||||||
|
pango_layout_set_text(layout, text, -1);
|
||||||
|
|
||||||
|
cairo_set_source_rgba(cr, node->fg_color[0], node->fg_color[1],
|
||||||
|
node->fg_color[2], node->fg_color[3]);
|
||||||
|
pango_cairo_show_layout(cr, layout);
|
||||||
|
|
||||||
|
g_object_unref(layout);
|
||||||
|
g_object_unref(ctx);
|
||||||
|
cairo_restore(cr); // 回到原坐标,方便画边框
|
||||||
|
|
||||||
|
// 3. 绘制边框
|
||||||
|
if (draw_border) {
|
||||||
|
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
|
||||||
|
node->border_color[2], node->border_color[3]);
|
||||||
|
cairo_set_line_width(cr, border * scale);
|
||||||
|
|
||||||
|
// 边框路径:比背景框外扩半个线宽,使得边框外缘恰好贴合 surface 边缘
|
||||||
|
double half_lw = border * scale * 0.5;
|
||||||
|
double bx = bg_x - half_lw;
|
||||||
|
double by = bg_y - half_lw;
|
||||||
|
double bw = bg_w + border * scale;
|
||||||
|
double bh = bg_h + border * scale;
|
||||||
|
|
||||||
|
if (radius > 0.0) {
|
||||||
|
// 圆角边框同样外扩半径(半径也需增加 half_lw)
|
||||||
|
double outer_radius = radius + half_lw;
|
||||||
|
if (outer_radius < 0.0)
|
||||||
|
outer_radius = 0.0;
|
||||||
|
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
} else {
|
||||||
|
cairo_rectangle(cr, bx, by, bw, bh);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_flush(surface);
|
||||||
|
|
||||||
|
// 包装成 wlr_buffer
|
||||||
|
struct mango_text_buffer *buf = calloc(1, sizeof(*buf));
|
||||||
|
if (!buf) {
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
cairo_destroy(cr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wlr_buffer_init(&buf->base, &text_buffer_impl, surface_pixel_w,
|
||||||
|
surface_pixel_h);
|
||||||
|
buf->surface = surface;
|
||||||
|
|
||||||
|
wlr_scene_buffer_set_buffer(node->scene_buffer, &buf->base);
|
||||||
|
wlr_buffer_drop(&buf->base);
|
||||||
|
|
||||||
|
// 最终逻辑大小 = 背景框逻辑尺寸 + 边框逻辑尺寸
|
||||||
|
node->logical_width = (int)(box_logical_w + 2.0f * border);
|
||||||
|
node->logical_height = (int)(box_logical_h + 2.0f * border);
|
||||||
|
wlr_scene_buffer_set_dest_size(node->scene_buffer, node->logical_width,
|
||||||
|
node->logical_height);
|
||||||
|
|
||||||
|
cairo_destroy(cr);
|
||||||
}
|
}
|
||||||
|
|
@ -1,34 +1,52 @@
|
||||||
#ifndef MANGO_TEXT_H
|
#ifndef MANGO_TEXT_NODE_H
|
||||||
#define MANGO_TEXT_H
|
#define MANGO_TEXT_NODE_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
struct mango_text_node {
|
struct mango_text_node {
|
||||||
struct wlr_scene_buffer *scene_buffer;
|
struct wlr_scene_buffer *scene_buffer;
|
||||||
int logical_width;
|
int logical_width;
|
||||||
int logical_height;
|
int logical_height;
|
||||||
|
const char *font_desc;
|
||||||
|
|
||||||
|
// 外观属性
|
||||||
|
float fg_color[4]; // 文本颜色 RGBA,默认白色
|
||||||
|
float bg_color[4]; // 背景色 RGBA,默认透明
|
||||||
|
float border_color[4]; // 边框色 RGBA,默认透明
|
||||||
|
int32_t border_width; // 边框宽度(逻辑像素),<=0 则不绘制
|
||||||
|
int32_t corner_radius; // 圆角半径(逻辑像素),<0 时自动取
|
||||||
|
// min(width,height)/2 形成胶囊
|
||||||
|
int32_t padding_x; // 文本左右内边距(逻辑像素)
|
||||||
|
int32_t padding_y; // 文本上下内边距(逻辑像素)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
typedef struct {
|
||||||
* 创建一个独立的文字场景节点
|
float fg_color[4];
|
||||||
* @param parent 父级场景树节点(例如窗口装饰树、OSD层树或状态栏树)
|
float bg_color[4];
|
||||||
*/
|
float border_color[4];
|
||||||
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent);
|
int32_t border_width;
|
||||||
|
int32_t corner_radius;
|
||||||
|
int32_t padding_x;
|
||||||
|
int32_t padding_y;
|
||||||
|
const char *font_desc;
|
||||||
|
} JumphitData;
|
||||||
|
|
||||||
/**
|
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent,
|
||||||
* 更新节点中的文字内容、字体、颜色和缩放
|
JumphitData data);
|
||||||
* @param node 文字节点指针
|
|
||||||
* @param text 要显示的文本内容
|
|
||||||
* @param font_desc Pango 字体描述字符串 (例如 "Sans 12" 或 "JetBrains Mono Bold 14")
|
|
||||||
* @param color RGBA 颜色数组,范围 0.0 ~ 1.0
|
|
||||||
* @param scale 当前输出设备的缩放比例 (HiDPI 支持)
|
|
||||||
*/
|
|
||||||
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
|
||||||
const char *font_desc, float color[4], float scale);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 销毁文字节点并释放相关场景图资源
|
|
||||||
*/
|
|
||||||
void mango_text_node_destroy(struct mango_text_node *node);
|
void mango_text_node_destroy(struct mango_text_node *node);
|
||||||
|
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
||||||
|
float scale);
|
||||||
|
|
||||||
#endif /* MANGO_TEXT_H */
|
// 外观设置接口
|
||||||
|
void mango_text_node_set_background(struct mango_text_node *node, float r,
|
||||||
|
float g, float b, float a);
|
||||||
|
void mango_text_node_set_border(struct mango_text_node *node, float r, float g,
|
||||||
|
float b, float a, float width, float radius);
|
||||||
|
void mango_text_node_set_padding(struct mango_text_node *node, float pad_x,
|
||||||
|
float pad_y);
|
||||||
|
|
||||||
|
void mango_text_node_destroy(struct mango_text_node *node);
|
||||||
|
void mango_text_global_finish(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -353,10 +353,65 @@ void overview_resize(Monitor *m) {
|
||||||
free(c_arr);
|
free(c_arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_jump_hints(Monitor *m) {
|
||||||
|
const char jump_labels[] = "HJKLASDFGQWERTYUIOPZXCVBNM";
|
||||||
|
int label_idx = 0;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (VISIBLEON(c, m) &&
|
||||||
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
||||||
|
if (label_idx >= 26)
|
||||||
|
break;
|
||||||
|
char c_char = jump_labels[label_idx];
|
||||||
|
c->jump_char = c_char;
|
||||||
|
|
||||||
|
// 把字符变成字符串
|
||||||
|
char label_text[2] = {c_char, '\0'};
|
||||||
|
|
||||||
|
mango_text_node_update(c->text_node, label_text, 1.0f);
|
||||||
|
wlr_scene_node_set_enabled(&c->text_node->scene_buffer->node, true);
|
||||||
|
wlr_scene_node_raise_to_top(&c->text_node->scene_buffer->node);
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
&c->text_node->scene_buffer->node,
|
||||||
|
c->geom.width / 2 - c->text_node->logical_width / 2,
|
||||||
|
c->geom.height / 2 - c->text_node->logical_height / 2);
|
||||||
|
label_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_jump_mode(Monitor *m) { m->is_jump_mode = 1; }
|
||||||
|
|
||||||
|
void finish_jump_mode(Monitor *m) {
|
||||||
|
Client *c = NULL;
|
||||||
|
|
||||||
|
if (!m->is_jump_mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (VISIBLEON(c, m)) {
|
||||||
|
if (c->text_node->scene_buffer->node.enabled) {
|
||||||
|
c->jump_char = '\0';
|
||||||
|
wlr_scene_node_set_enabled(&c->text_node->scene_buffer->node,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m->is_jump_mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void overview(Monitor *m) {
|
void overview(Monitor *m) {
|
||||||
|
|
||||||
if (config.ov_no_resize) {
|
if (config.ov_no_resize) {
|
||||||
overview_scale(m);
|
overview_scale(m);
|
||||||
} else {
|
} else {
|
||||||
overview_resize(m);
|
overview_resize(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m->is_jump_mode) {
|
||||||
|
create_jump_hints(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
33
src/mango.c
33
src/mango.c
|
|
@ -435,6 +435,7 @@ struct Client {
|
||||||
int32_t allow_shortcuts_inhibit;
|
int32_t allow_shortcuts_inhibit;
|
||||||
float scroller_proportion_single;
|
float scroller_proportion_single;
|
||||||
bool isfocusing;
|
bool isfocusing;
|
||||||
|
char jump_char;
|
||||||
bool enable_drop_area_draw;
|
bool enable_drop_area_draw;
|
||||||
int32_t drop_direction;
|
int32_t drop_direction;
|
||||||
struct wlr_box drag_tile_float_backup_geom;
|
struct wlr_box drag_tile_float_backup_geom;
|
||||||
|
|
@ -556,6 +557,7 @@ struct Monitor {
|
||||||
uint32_t ovbk_prev_tagset;
|
uint32_t ovbk_prev_tagset;
|
||||||
Client *sel, *prevsel;
|
Client *sel, *prevsel;
|
||||||
int32_t isoverview;
|
int32_t isoverview;
|
||||||
|
int32_t is_jump_mode;
|
||||||
int32_t is_in_hotarea;
|
int32_t is_in_hotarea;
|
||||||
int32_t asleep;
|
int32_t asleep;
|
||||||
uint32_t visible_clients;
|
uint32_t visible_clients;
|
||||||
|
|
@ -901,6 +903,10 @@ Client *scroll_get_stack_tail_client(Client *c);
|
||||||
static DwindleNode *dwindle_find_leaf(DwindleNode *node, Client *c);
|
static DwindleNode *dwindle_find_leaf(DwindleNode *node, Client *c);
|
||||||
static void overview_backup_surface(Client *c);
|
static void overview_backup_surface(Client *c);
|
||||||
|
|
||||||
|
static void create_jump_hints(Monitor *m);
|
||||||
|
static void finish_jump_mode(Monitor *m);
|
||||||
|
static void begin_jump_mode(Monitor *m);
|
||||||
|
|
||||||
#include "data/static_keymap.h"
|
#include "data/static_keymap.h"
|
||||||
#include "dispatch/bind_declare.h"
|
#include "dispatch/bind_declare.h"
|
||||||
#include "layout/layout.h"
|
#include "layout/layout.h"
|
||||||
|
|
@ -2563,6 +2569,8 @@ void cleanup(void) {
|
||||||
/* Destroy after the wayland display (when the monitors are already
|
/* Destroy after the wayland display (when the monitors are already
|
||||||
destroyed) to avoid destroying them with an invalid scene output. */
|
destroyed) to avoid destroying them with an invalid scene output. */
|
||||||
wlr_scene_node_destroy(&scene->tree.node);
|
wlr_scene_node_destroy(&scene->tree.node);
|
||||||
|
|
||||||
|
mango_text_global_finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupmon(struct wl_listener *listener, void *data) {
|
void cleanupmon(struct wl_listener *listener, void *data) {
|
||||||
|
|
@ -4256,6 +4264,27 @@ void keypress(struct wl_listener *listener, void *data) {
|
||||||
if (handled)
|
if (handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (selmon && selmon->is_jump_mode &&
|
||||||
|
event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
|
for (i = 0; i < nsyms; i++) {
|
||||||
|
xkb_keysym_t sym = xkb_keysym_to_lower(syms[i]);
|
||||||
|
if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) {
|
||||||
|
char c_char = 'A' + (sym - XKB_KEY_a);
|
||||||
|
Client *c;
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (c->mon == selmon && c->jump_char == c_char) {
|
||||||
|
focusclient(c, 1);
|
||||||
|
toggleoverview(&(Arg){.i = 1});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sym == XKB_KEY_Escape) {
|
||||||
|
togglejump(&(Arg){.i = 0});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* don't pass when popup is focused
|
/* don't pass when popup is focused
|
||||||
* this is better than having popups (like fuzzel or wmenu) closing
|
* this is better than having popups (like fuzzel or wmenu) closing
|
||||||
* while typing in a passed keybind */
|
* while typing in a passed keybind */
|
||||||
|
|
@ -4515,8 +4544,7 @@ mapnotify(struct wl_listener *listener, void *data) {
|
||||||
#endif
|
#endif
|
||||||
// extra node
|
// extra node
|
||||||
|
|
||||||
c->text_node = mango_text_node_create(c->scene);
|
c->text_node = mango_text_node_create(c->scene, config.jumhitdata);
|
||||||
mango_text_node_update(c->text_node, "hello world", "Sans 50", config.focuscolor, 1.0f);
|
|
||||||
wlr_scene_node_lower_to_bottom(&c->text_node->scene_buffer->node);
|
wlr_scene_node_lower_to_bottom(&c->text_node->scene_buffer->node);
|
||||||
wlr_scene_node_set_enabled(&c->text_node->scene_buffer->node, false);
|
wlr_scene_node_set_enabled(&c->text_node->scene_buffer->node, false);
|
||||||
|
|
||||||
|
|
@ -6517,6 +6545,7 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
c->stack_proportion = 0.0f;
|
c->stack_proportion = 0.0f;
|
||||||
|
|
||||||
|
mango_text_node_destroy(c->text_node);
|
||||||
wlr_scene_node_destroy(&c->scene->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
printstatus(IPC_WATCH_ARRANGGE);
|
printstatus(IPC_WATCH_ARRANGGE);
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue