mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-19 14:33:16 -04:00
Merge 0fc7559c3c into adc1239075
This commit is contained in:
commit
7d7b239368
13 changed files with 330 additions and 1208 deletions
|
|
@ -8,7 +8,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
|
|||
| Setting | Default | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `xwayland_persistence` | `1` | Keep XWayland running even when no X11 apps are open (reduces startup lag). |
|
||||
| `syncobj_enable` | `0` | Enable `drm_syncobj` timeline support (helps with gaming stutter/lag). **Requires restart.** |
|
||||
| `syncobj_enable` | `1` | Enable `drm_syncobj` timeline support (helps with gaming stutter/lag). **Requires restart.** |
|
||||
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
||||
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
||||
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ windowrule=Parameter:Values,Parameter:Values,appid:Values,title:Values
|
|||
| `single_scratchpad` | integer | `0` / `1` (default 1) | Only show one out of named scratchpads or the normal scratchpad |
|
||||
| `allow_shortcuts_inhibit` | integer | `0` / `1` (default 1) | Allow shortcuts to be inhibited by clients |
|
||||
| `idleinhibit_when_focus` | integer | `0` / `1` (default 0) | Automatically keep idle inhibit active when this window is focused |
|
||||
| `shield_when_capture` | integer | `0` / `1` | Shield window when captured |
|
||||
|
||||
|
||||
### Geometry & Position
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ libdrm = dependency('libdrm')
|
|||
xcb = dependency('xcb', required : get_option('xwayland'))
|
||||
xlibs = dependency('xcb-icccm', required : get_option('xwayland'))
|
||||
wayland_server_dep = dependency('wayland-server',version: '>=1.23.1')
|
||||
wlroots_dep = dependency('wlroots-0.19',version: '>=0.19.0')
|
||||
wlroots_dep = dependency('wlroots-0.20',version: '>=0.20.0')
|
||||
xkbcommon_dep = dependency('xkbcommon')
|
||||
libinput_dep = dependency('libinput',version: '>=1.27.1')
|
||||
libwayland_client_dep = dependency('wayland-client')
|
||||
pcre2_dep = dependency('libpcre2-8')
|
||||
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
||||
libscenefx_dep = dependency('scenefx-0.5',version: '>=0.5.0')
|
||||
pixman_dep = dependency('pixman-1')
|
||||
cjson_dep = dependency('libcjson')
|
||||
pangocairo_dep = dependency('pangocairo')
|
||||
|
|
@ -97,7 +97,7 @@ executable('mango',
|
|||
'src/mango.c',
|
||||
'src/common/util.c',
|
||||
'src/draw/text-node.c',
|
||||
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
||||
|
||||
wayland_sources,
|
||||
dependencies : [
|
||||
libm,
|
||||
|
|
|
|||
|
|
@ -9,23 +9,28 @@ void set_rect_size(struct wlr_scene_rect *rect, int32_t width, int32_t height) {
|
|||
wlr_scene_rect_set_size(rect, GEZERO(width), GEZERO(height));
|
||||
}
|
||||
|
||||
enum corner_location set_client_corner_location(Client *c) {
|
||||
enum corner_location current_corner_location = CORNER_LOCATION_ALL;
|
||||
struct fx_corner_radii set_client_corner_location(Client *c) {
|
||||
struct fx_corner_radii current_corner_location =
|
||||
corner_radii_all(config.border_radius);
|
||||
struct wlr_box target_geom =
|
||||
config.animations ? c->animation.current : c->geom;
|
||||
if (target_geom.x + config.border_radius <= c->mon->m.x) {
|
||||
current_corner_location &= ~CORNER_LOCATION_LEFT;
|
||||
current_corner_location.top_left = 0; // 清除左标志位
|
||||
current_corner_location.bottom_left = 0; // 清除左标志位
|
||||
}
|
||||
if (target_geom.x + target_geom.width - config.border_radius >=
|
||||
c->mon->m.x + c->mon->m.width) {
|
||||
current_corner_location &= ~CORNER_LOCATION_RIGHT;
|
||||
current_corner_location.top_right = 0; // 清除右标志位
|
||||
current_corner_location.bottom_right = 0; // 清除右标志位
|
||||
}
|
||||
if (target_geom.y + config.border_radius <= c->mon->m.y) {
|
||||
current_corner_location &= ~CORNER_LOCATION_TOP;
|
||||
current_corner_location.top_left = 0; // 清除上标志位
|
||||
current_corner_location.top_right = 0; // 清除上标志位
|
||||
}
|
||||
if (target_geom.y + target_geom.height - config.border_radius >=
|
||||
c->mon->m.y + c->mon->m.height) {
|
||||
current_corner_location &= ~CORNER_LOCATION_BOTTOM;
|
||||
current_corner_location.bottom_left = 0; // 清除下标志位
|
||||
current_corner_location.bottom_right = 0; // 清除下标志位
|
||||
}
|
||||
return current_corner_location;
|
||||
}
|
||||
|
|
@ -235,8 +240,7 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
|||
if (wlr_xdg_popup_try_from_wlr_surface(surface) != NULL)
|
||||
return;
|
||||
|
||||
wlr_scene_buffer_set_corner_radius(buffer, config.border_radius,
|
||||
buffer_data->corner_location);
|
||||
wlr_scene_buffer_set_corner_radii(buffer, buffer_data->corner_location);
|
||||
}
|
||||
|
||||
void scene_buffer_apply_overview_effect(struct wlr_scene_buffer *buffer,
|
||||
|
|
@ -268,8 +272,7 @@ void scene_buffer_apply_overview_effect(struct wlr_scene_buffer *buffer,
|
|||
if (is_subsurface)
|
||||
return;
|
||||
|
||||
wlr_scene_buffer_set_corner_radius(buffer, config.border_radius,
|
||||
buffer_data->corner_location);
|
||||
wlr_scene_buffer_set_corner_radii(buffer, buffer_data->corner_location);
|
||||
}
|
||||
|
||||
void buffer_set_effect(Client *c, BufferData data) {
|
||||
|
|
@ -285,10 +288,13 @@ void buffer_set_effect(Client *c, BufferData data) {
|
|||
if (c == grabc)
|
||||
data.should_scale = false;
|
||||
|
||||
if (c->isnoradius || c->isfullscreen ||
|
||||
(config.no_radius_when_single && c->mon &&
|
||||
c->mon->visible_tiling_clients == 1)) {
|
||||
data.corner_location = CORNER_LOCATION_NONE;
|
||||
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||
c->mon->visible_tiling_clients == 1)) {
|
||||
data.corner_location = corner_radii_none();
|
||||
}
|
||||
|
||||
if (config.blur && !c->noblur) {
|
||||
wlr_scene_blur_set_corner_radii(c->blur, data.corner_location);
|
||||
}
|
||||
|
||||
if (c->overview_scene_surface) {
|
||||
|
|
@ -316,11 +322,11 @@ void client_draw_shadow(Client *c) {
|
|||
}
|
||||
|
||||
bool hit_no_border = check_hit_no_border(c);
|
||||
enum corner_location current_corner_location =
|
||||
struct fx_corner_radii current_corner_location =
|
||||
c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||
c->mon->visible_tiling_clients == 1)
|
||||
? CORNER_LOCATION_NONE
|
||||
: CORNER_LOCATION_ALL;
|
||||
? corner_radii_none()
|
||||
: set_client_corner_location(c);
|
||||
|
||||
int32_t bwoffset = c->bw != 0 && hit_no_border ? (int32_t)c->bw : 0;
|
||||
|
||||
|
|
@ -350,7 +356,6 @@ void client_draw_shadow(Client *c) {
|
|||
|
||||
struct clipped_region clipped_region = {
|
||||
.area = intersection_box,
|
||||
.corner_radius = config.border_radius,
|
||||
.corners = current_corner_location,
|
||||
};
|
||||
|
||||
|
|
@ -398,6 +403,46 @@ void client_draw_shadow(Client *c) {
|
|||
wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region);
|
||||
}
|
||||
|
||||
void apply_shield(Client *c, struct wlr_box clip_box) {
|
||||
|
||||
if (clip_box.width <= 0 || clip_box.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_capture_count > 0 && c->shield_when_capture) {
|
||||
wlr_scene_node_raise_to_top(&c->shield->node);
|
||||
wlr_scene_node_set_position(&c->shield->node, clip_box.x, clip_box.y);
|
||||
wlr_scene_rect_set_size(c->shield, clip_box.width, clip_box.height);
|
||||
wlr_scene_node_set_enabled(&c->shield->node, true);
|
||||
} else {
|
||||
if (c->shield->node.enabled) {
|
||||
wlr_scene_node_lower_to_bottom(&c->shield->node);
|
||||
wlr_scene_rect_set_size(c->shield, c->animation.current.width,
|
||||
c->animation.current.height);
|
||||
wlr_scene_node_set_enabled(&c->shield->node, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void client_draw_blur(Client *c, struct wlr_box clip_box, struct ivec2 offset) {
|
||||
|
||||
if (c->isfullscreen) {
|
||||
if (c->blur->node.enabled) {
|
||||
wlr_scene_node_set_enabled(&c->blur->node, false);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (config.blur && !c->noblur) {
|
||||
wlr_scene_node_set_enabled(&c->blur->node, true);
|
||||
wlr_scene_node_set_position(&c->blur->node, offset.x, offset.y);
|
||||
wlr_scene_blur_set_size(c->blur, clip_box.width - c->bw,
|
||||
clip_box.height - c->bw);
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&c->blur->node, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void global_draw_tab_bar(Client *c, int32_t x, int32_t y, int32_t width,
|
||||
int32_t height) {
|
||||
if (!c->tab_bar_node)
|
||||
|
|
@ -509,7 +554,8 @@ void apply_border(Client *c) {
|
|||
|
||||
if (c->isfullscreen) {
|
||||
if (c->border->node.enabled) {
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, 0, 0);
|
||||
wlr_scene_node_set_enabled(&c->splitindicator[0]->node, false);
|
||||
wlr_scene_node_set_enabled(&c->splitindicator[1]->node, false);
|
||||
wlr_scene_node_set_enabled(&c->border->node, false);
|
||||
}
|
||||
return;
|
||||
|
|
@ -520,16 +566,13 @@ void apply_border(Client *c) {
|
|||
}
|
||||
|
||||
bool hit_no_border = check_hit_no_border(c);
|
||||
|
||||
apply_split_border(c, hit_no_border);
|
||||
|
||||
enum corner_location current_corner_location;
|
||||
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||
c->mon->visible_tiling_clients == 1)) {
|
||||
current_corner_location = CORNER_LOCATION_NONE;
|
||||
} else {
|
||||
current_corner_location = set_client_corner_location(c);
|
||||
}
|
||||
struct fx_corner_radii current_corner_location =
|
||||
c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
||||
c->mon->visible_tiling_clients == 1)
|
||||
? corner_radii_none()
|
||||
: set_client_corner_location(c);
|
||||
|
||||
if (hit_no_border && config.smartgaps) {
|
||||
c->bw = 0;
|
||||
|
|
@ -602,15 +645,13 @@ void apply_border(Client *c) {
|
|||
struct clipped_region clipped_region = {
|
||||
.area = {inner_surface_x, inner_surface_y, inner_surface_width,
|
||||
inner_surface_height},
|
||||
.corner_radius = config.border_radius,
|
||||
.corners = current_corner_location,
|
||||
};
|
||||
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border, rect_width, rect_height);
|
||||
wlr_scene_node_set_position(&c->border->node, rect_x, rect_y);
|
||||
wlr_scene_rect_set_corner_radius(c->border, config.border_radius,
|
||||
current_corner_location);
|
||||
wlr_scene_rect_set_corner_radii(c->border, current_corner_location);
|
||||
wlr_scene_rect_set_clipped_region(c->border, clipped_region);
|
||||
}
|
||||
|
||||
|
|
@ -882,7 +923,7 @@ void client_apply_clip(Client *c, float factor) {
|
|||
struct ivec2 offset;
|
||||
BufferData buffer_data;
|
||||
|
||||
enum corner_location current_corner_location =
|
||||
struct fx_corner_radii current_corner_location =
|
||||
set_client_corner_location(c);
|
||||
|
||||
if (!config.animations && !c->overview_scene_surface) {
|
||||
|
|
@ -897,6 +938,8 @@ void client_apply_clip(Client *c, float factor) {
|
|||
|
||||
apply_border(c);
|
||||
client_draw_shadow(c);
|
||||
client_draw_blur(c, clip_box, offset);
|
||||
apply_shield(c, clip_box);
|
||||
|
||||
if (clip_box.width <= 0 || clip_box.height <= 0) {
|
||||
return;
|
||||
|
|
@ -938,6 +981,8 @@ void client_apply_clip(Client *c, float factor) {
|
|||
// 应用窗口装饰
|
||||
apply_border(c);
|
||||
client_draw_shadow(c);
|
||||
apply_shield(c, clip_box);
|
||||
client_draw_blur(c, clip_box, offset);
|
||||
|
||||
// 如果窗口剪切区域已经剪切到0,则不渲染窗口表面
|
||||
if (clip_box.width <= 0 || clip_box.height <= 0) {
|
||||
|
|
@ -1135,6 +1180,10 @@ void init_fadeout_client(Client *c) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (c->shield_when_capture && active_capture_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((c->animation_type_close &&
|
||||
strcmp(c->animation_type_close, "none") == 0) ||
|
||||
(!c->animation_type_close &&
|
||||
|
|
@ -1379,10 +1428,15 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
|||
c->geom;
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
|
||||
client_draw_shadow(c);
|
||||
apply_border(c);
|
||||
client_get_clip(c, &clip);
|
||||
apply_shield(c, clip);
|
||||
client_draw_shadow(c);
|
||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
||||
if (config.blur && !c->noblur)
|
||||
wlr_scene_blur_set_size(c->blur,
|
||||
c->animation.current.width - 2 * c->bw,
|
||||
c->animation.current.height - 2 * c->bw);
|
||||
return;
|
||||
}
|
||||
// 如果不是工作区切换时划出去的窗口,就让动画的结束位置,就是上面的真实位置和大小
|
||||
|
|
@ -1512,6 +1566,16 @@ bool client_apply_focus_opacity(Client *c) {
|
|||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.current_opacity = target_opacity;
|
||||
client_set_opacity(c, target_opacity);
|
||||
if (config.blur && !c->noblur && !config.blur_optimized) {
|
||||
wlr_scene_blur_set_strength(
|
||||
c->blur, MIN(percent * (1.0 - config.fadein_begin_opacity) +
|
||||
config.fadein_begin_opacity,
|
||||
1.0));
|
||||
wlr_scene_blur_set_alpha(
|
||||
c->blur, MIN(percent * (1.0 - config.fadein_begin_opacity) +
|
||||
config.fadein_begin_opacity,
|
||||
1.0));
|
||||
}
|
||||
client_set_border_color(c, c->opacity_animation.target_border_color);
|
||||
} else if (config.animations && c->opacity_animation.running) {
|
||||
|
||||
|
|
|
|||
|
|
@ -212,11 +212,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|||
|
||||
// Effects
|
||||
wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity);
|
||||
wlr_scene_buffer_set_corner_radius(snapshot_buffer,
|
||||
scene_buffer->corner_radius,
|
||||
scene_buffer->corners);
|
||||
|
||||
wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false);
|
||||
wlr_scene_buffer_set_corner_radii(snapshot_buffer,
|
||||
scene_buffer->corners);
|
||||
|
||||
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
||||
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
||||
|
|
@ -248,6 +245,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|||
|
||||
break;
|
||||
}
|
||||
case WLR_SCENE_NODE_BLUR:
|
||||
break;
|
||||
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,8 +187,7 @@ void layer_draw_shadow(LayerSurface *l) {
|
|||
|
||||
struct clipped_region clipped_region = {
|
||||
.area = intersection_box,
|
||||
.corner_radius = config.border_radius,
|
||||
.corners = config.border_radius_location_default,
|
||||
.corners = corner_radii_all(config.border_radius),
|
||||
};
|
||||
|
||||
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
||||
|
|
@ -328,9 +327,14 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||
(1.0 - config.fadein_begin_opacity),
|
||||
1.0f);
|
||||
|
||||
if (config.animation_fade_in)
|
||||
if (config.animation_fade_in) {
|
||||
if (config.blur && !l->noblur && !config.blur_optimized) {
|
||||
wlr_scene_blur_set_strength(l->blur, opacity);
|
||||
wlr_scene_blur_set_alpha(l->blur, opacity);
|
||||
}
|
||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||
scene_buffer_apply_opacity, &opacity);
|
||||
}
|
||||
|
||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||
|
||||
|
|
@ -358,6 +362,10 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||
.height = height,
|
||||
};
|
||||
|
||||
if (config.blur && config.blur_layer && !l->noblur && l->blur)
|
||||
wlr_scene_blur_set_size(l->blur, l->animation.current.width,
|
||||
l->animation.current.height);
|
||||
|
||||
if (animation_passed >= 1.0) {
|
||||
l->animation.running = false;
|
||||
l->need_output_flush = false;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ typedef struct {
|
|||
int32_t isunglobal;
|
||||
int32_t isglobal;
|
||||
int32_t isoverlay;
|
||||
int32_t shield_when_capture;
|
||||
int32_t allow_shortcuts_inhibit;
|
||||
int32_t ignore_maximize;
|
||||
int32_t ignore_minimize;
|
||||
|
|
@ -2349,6 +2350,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->isunglobal = -1;
|
||||
rule->isglobal = -1;
|
||||
rule->isoverlay = -1;
|
||||
rule->shield_when_capture = -1;
|
||||
rule->allow_shortcuts_inhibit = -1;
|
||||
rule->ignore_maximize = -1;
|
||||
rule->ignore_minimize = -1;
|
||||
|
|
@ -2456,6 +2458,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->focused_opacity = atof(val);
|
||||
} else if (strcmp(key, "isoverlay") == 0) {
|
||||
rule->isoverlay = atoi(val);
|
||||
} else if (strcmp(key, "shield_when_capture") == 0) {
|
||||
rule->shield_when_capture = atoi(val);
|
||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||
rule->allow_shortcuts_inhibit = atoi(val);
|
||||
} else if (strcmp(key, "ignore_maximize") == 0) {
|
||||
|
|
@ -3683,7 +3687,7 @@ void set_value_default() {
|
|||
config.view_current_to_back = 0;
|
||||
config.single_scratchpad = 1;
|
||||
config.xwayland_persistence = 1;
|
||||
config.syncobj_enable = 0;
|
||||
config.syncobj_enable = 1;
|
||||
config.tag_carousel = 0;
|
||||
config.drag_tile_refresh_interval = 8.0f;
|
||||
config.drag_floating_refresh_interval = 8.0f;
|
||||
|
|
@ -3738,7 +3742,6 @@ void set_value_default() {
|
|||
config.blur_layer = 0;
|
||||
config.blur_optimized = 1;
|
||||
config.border_radius = 0;
|
||||
config.border_radius_location_default = CORNER_LOCATION_ALL;
|
||||
config.blur_params.num_passes = 1;
|
||||
config.blur_params.radius = 5;
|
||||
config.blur_params.noise = 0.02f;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "wlr_ext_workspace_v1.h"
|
||||
#include <wlr/types/wlr_ext_workspace_v1.h>
|
||||
|
||||
#define EXT_WORKSPACE_ENABLE_CAPS \
|
||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
||||
|
|
|
|||
|
|
@ -292,9 +292,8 @@ static void handle_input_method_commit(struct wl_listener *listener,
|
|||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_commit);
|
||||
struct wlr_input_method_v2 *input_method = data;
|
||||
struct text_input *text_input;
|
||||
assert(relay->input_method == input_method);
|
||||
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||
|
||||
text_input = relay->active_text_input;
|
||||
if (!text_input) {
|
||||
|
|
@ -324,7 +323,8 @@ static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
|||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||
relay->input_method->keyboard_grab;
|
||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||
|
||||
if (keyboard_grab->keyboard) {
|
||||
|
|
@ -356,7 +356,6 @@ static void handle_input_method_destroy(struct wl_listener *listener,
|
|||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_destroy);
|
||||
assert(relay->input_method == data);
|
||||
wl_list_remove(&relay->input_method_commit.link);
|
||||
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
||||
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
||||
|
|
@ -562,11 +561,11 @@ struct dwl_input_method_relay *dwl_im_relay_create() {
|
|||
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
||||
|
||||
relay->new_text_input.notify = handle_new_text_input;
|
||||
wl_signal_add(&text_input_manager->events.text_input,
|
||||
wl_signal_add(&text_input_manager->events.new_text_input,
|
||||
&relay->new_text_input);
|
||||
|
||||
relay->new_input_method.notify = handle_new_input_method;
|
||||
wl_signal_add(&input_method_manager->events.input_method,
|
||||
wl_signal_add(&input_method_manager->events.new_input_method,
|
||||
&relay->new_input_method);
|
||||
|
||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||
|
|
|
|||
|
|
@ -1,975 +0,0 @@
|
|||
#include "wlr_ext_workspace_v1.h"
|
||||
#include "ext-workspace-v1-protocol.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
||||
#define EXT_WORKSPACE_V1_VERSION 1
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output {
|
||||
struct wlr_output *output;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
struct wl_listener output_bind;
|
||||
struct wl_listener output_destroy;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
// These structs wrap wl_resource of each interface to access the request queue
|
||||
// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager
|
||||
// resource
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
struct wl_list requests; // wlr_ext_workspace_v1_request.link
|
||||
struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link
|
||||
struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.resources
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
||||
struct wl_list link; // wlr_ext_workspace_group_v1.resources
|
||||
struct wl_list
|
||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
||||
struct wl_list link; // wlr_ext_workspace_v1.resources
|
||||
struct wl_list
|
||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
||||
};
|
||||
|
||||
static const struct ext_workspace_group_handle_v1_interface group_impl;
|
||||
|
||||
static struct wlr_ext_workspace_group_v1_resource *
|
||||
group_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(
|
||||
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_handle_v1_interface workspace_impl;
|
||||
|
||||
static struct wlr_ext_workspace_v1_resource *
|
||||
workspace_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
||||
&workspace_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_manager_v1_interface manager_impl;
|
||||
|
||||
static struct wlr_ext_workspace_manager_v1_resource *
|
||||
manager_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(
|
||||
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void workspace_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void workspace_handle_activate(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
||||
req->activate.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_handle_deactivate(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
||||
req->deactivate.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void workspace_handle_assign(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource,
|
||||
struct wl_resource *group_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(group_resource);
|
||||
if (!workspace_res || !group_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
||||
req->assign.group = group_res->group;
|
||||
req->assign.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void workspace_handle_remove(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
||||
req->remove.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
||||
.destroy = workspace_handle_destroy,
|
||||
.activate = workspace_handle_activate,
|
||||
.deactivate = workspace_handle_deactivate,
|
||||
.assign = workspace_handle_assign,
|
||||
.remove = workspace_handle_remove,
|
||||
};
|
||||
|
||||
static void group_handle_create_workspace(struct wl_client *client,
|
||||
struct wl_resource *group_resource,
|
||||
const char *name) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(group_resource);
|
||||
if (!group_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(group_resource);
|
||||
return;
|
||||
}
|
||||
req->create_workspace.name = strdup(name);
|
||||
if (!req->create_workspace.name) {
|
||||
free(req);
|
||||
wl_resource_post_no_memory(group_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
||||
req->create_workspace.group = group_res->group;
|
||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void group_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_group_handle_v1_interface group_impl = {
|
||||
.create_workspace = group_handle_create_workspace,
|
||||
.destroy = group_handle_destroy,
|
||||
};
|
||||
|
||||
static void destroy_workspace_resource(
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||
wl_list_remove(&workspace_res->link);
|
||||
wl_list_remove(&workspace_res->manager_resource_link);
|
||||
wl_resource_set_user_data(workspace_res->resource, NULL);
|
||||
free(workspace_res);
|
||||
}
|
||||
|
||||
static void workspace_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(resource);
|
||||
if (workspace_res) {
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
calloc(1, sizeof(*workspace_res));
|
||||
if (!workspace_res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
||||
workspace_res->resource =
|
||||
wl_resource_create(client, &ext_workspace_handle_v1_interface,
|
||||
wl_resource_get_version(manager_res->resource), 0);
|
||||
if (!workspace_res->resource) {
|
||||
free(workspace_res);
|
||||
return NULL;
|
||||
}
|
||||
wl_resource_set_implementation(workspace_res->resource, &workspace_impl,
|
||||
workspace_res, workspace_resource_destroy);
|
||||
|
||||
workspace_res->workspace = workspace;
|
||||
workspace_res->manager = manager_res;
|
||||
wl_list_insert(&workspace->resources, &workspace_res->link);
|
||||
wl_list_insert(&manager_res->workspace_resources,
|
||||
&workspace_res->manager_resource_link);
|
||||
|
||||
return workspace_res;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||
wl_list_remove(&group_res->link);
|
||||
wl_list_remove(&group_res->manager_resource_link);
|
||||
wl_resource_set_user_data(group_res->resource, NULL);
|
||||
free(group_res);
|
||||
}
|
||||
|
||||
static void group_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(resource);
|
||||
if (group_res) {
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
calloc(1, sizeof(*group_res));
|
||||
if (!group_res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
||||
uint32_t version = wl_resource_get_version(manager_res->resource);
|
||||
group_res->resource = wl_resource_create(
|
||||
client, &ext_workspace_group_handle_v1_interface, version, 0);
|
||||
if (group_res->resource == NULL) {
|
||||
free(group_res);
|
||||
return NULL;
|
||||
}
|
||||
wl_resource_set_implementation(group_res->resource, &group_impl, group_res,
|
||||
group_handle_resource_destroy);
|
||||
|
||||
group_res->group = group;
|
||||
group_res->manager = manager_res;
|
||||
wl_list_insert(&group->resources, &group_res->link);
|
||||
wl_list_insert(&manager_res->group_resources,
|
||||
&group_res->manager_resource_link);
|
||||
|
||||
return group_res;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_requests(struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||
if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE) {
|
||||
free(req->create_workspace.name);
|
||||
}
|
||||
wl_list_remove(&req->link);
|
||||
free(req);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_requests_by(struct wlr_ext_workspace_manager_v1_resource *manager_res,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||
switch (req->type) {
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:
|
||||
if (group && req->create_workspace.group == group) {
|
||||
req->create_workspace.group = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
||||
if (workspace && req->activate.workspace == workspace) {
|
||||
req->activate.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
||||
if (workspace && req->deactivate.workspace == workspace) {
|
||||
req->deactivate.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
||||
if (workspace && req->assign.workspace == workspace) {
|
||||
req->assign.workspace = NULL;
|
||||
}
|
||||
if (group && req->assign.group == group) {
|
||||
req->assign.group = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
||||
if (workspace && req->remove.workspace == workspace) {
|
||||
req->remove.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_handle_commit(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
manager_resource_from_resource(resource);
|
||||
if (!manager_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_commit_event commit_event = {
|
||||
.requests = &manager_res->requests,
|
||||
};
|
||||
wl_signal_emit_mutable(&manager_res->manager->events.commit, &commit_event);
|
||||
destroy_requests(manager_res);
|
||||
}
|
||||
|
||||
static void handle_idle(void *data) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
||||
}
|
||||
manager->idle_source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
||||
if (!manager->idle_source) {
|
||||
manager->idle_source =
|
||||
wl_event_loop_add_idle(manager->event_loop, handle_idle, manager);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
||||
struct wl_resource *resource = workspace_res->resource;
|
||||
|
||||
ext_workspace_handle_v1_send_capabilities(resource, workspace->caps);
|
||||
if (workspace->coordinates.size > 0) {
|
||||
ext_workspace_handle_v1_send_coordinates(resource,
|
||||
&workspace->coordinates);
|
||||
}
|
||||
if (workspace->name) {
|
||||
ext_workspace_handle_v1_send_name(resource, workspace->name);
|
||||
}
|
||||
if (workspace->id) {
|
||||
ext_workspace_handle_v1_send_id(resource, workspace->id);
|
||||
}
|
||||
ext_workspace_handle_v1_send_state(resource, workspace->state);
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void manager_handle_stop(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
ext_workspace_manager_v1_send_finished(resource);
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_manager_v1_interface manager_impl = {
|
||||
.commit = manager_handle_commit,
|
||||
.stop = manager_handle_stop,
|
||||
};
|
||||
|
||||
static void destroy_manager_resource(
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
destroy_requests(manager_res);
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
||||
wl_list_for_each_safe(workspace_res, tmp2,
|
||||
&manager_res->workspace_resources,
|
||||
manager_resource_link) {
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3;
|
||||
wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources,
|
||||
manager_resource_link) {
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
|
||||
wl_list_remove(&manager_res->link);
|
||||
wl_resource_set_user_data(manager_res->resource, NULL);
|
||||
free(manager_res);
|
||||
}
|
||||
|
||||
static void manager_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
manager_resource_from_resource(resource);
|
||||
if (manager_res) {
|
||||
destroy_manager_resource(manager_res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
||||
struct wl_resource *resource = group_res->resource;
|
||||
struct wl_client *client = wl_resource_get_client(resource);
|
||||
|
||||
ext_workspace_group_handle_v1_send_capabilities(resource, group->caps);
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
||||
wl_list_for_each(group_output, &group->outputs, link) {
|
||||
struct wl_resource *output_resource;
|
||||
wl_resource_for_each(output_resource,
|
||||
&group_output->output->resources) {
|
||||
if (wl_resource_get_client(output_resource) == client) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(
|
||||
resource, output_resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
}
|
||||
|
||||
static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
||||
uint32_t id) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
calloc(1, sizeof(*manager_res));
|
||||
if (!manager_res) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
manager_res->manager = manager;
|
||||
wl_list_init(&manager_res->requests);
|
||||
wl_list_init(&manager_res->workspace_resources);
|
||||
wl_list_init(&manager_res->group_resources);
|
||||
|
||||
manager_res->resource = wl_resource_create(
|
||||
client, &ext_workspace_manager_v1_interface, version, id);
|
||||
if (!manager_res->resource) {
|
||||
free(manager_res);
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(manager_res->resource, &manager_impl,
|
||||
manager_res, manager_resource_destroy);
|
||||
wl_list_insert(&manager->resources, &manager_res->link);
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
wl_list_for_each(group, &manager->groups, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
create_group_resource(group, manager_res);
|
||||
if (!group_res) {
|
||||
wl_resource_post_no_memory(manager_res->resource);
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
||||
group_res->resource);
|
||||
group_send_details(group_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
wl_list_for_each(workspace, &manager->workspaces, link) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
create_workspace_resource(workspace, manager_res);
|
||||
if (!workspace_res) {
|
||||
wl_resource_post_no_memory(manager_res->resource);
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
||||
workspace_res->resource);
|
||||
workspace_send_details(workspace_res);
|
||||
|
||||
if (!workspace->group) {
|
||||
continue;
|
||||
}
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &workspace->group->resources, link) {
|
||||
if (group_res->manager == manager_res) {
|
||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
||||
group_res->resource, workspace_res->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
||||
}
|
||||
|
||||
static void manager_handle_display_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, display_destroy);
|
||||
|
||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
||||
assert(wl_list_empty(&manager->events.commit.listener_list));
|
||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
||||
wl_list_for_each_safe(group, tmp, &manager->groups, link) {
|
||||
wlr_ext_workspace_group_handle_v1_destroy(group);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, *tmp2;
|
||||
wl_list_for_each_safe(workspace, tmp2, &manager->workspaces, link) {
|
||||
wlr_ext_workspace_handle_v1_destroy(workspace);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3;
|
||||
wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) {
|
||||
destroy_manager_resource(manager_res);
|
||||
}
|
||||
|
||||
if (manager->idle_source) {
|
||||
wl_event_source_remove(manager->idle_source);
|
||||
}
|
||||
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
free(manager);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *
|
||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
||||
uint32_t version) {
|
||||
assert(version <= EXT_WORKSPACE_V1_VERSION);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *manager = calloc(1, sizeof(*manager));
|
||||
if (!manager) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->global =
|
||||
wl_global_create(display, &ext_workspace_manager_v1_interface, version,
|
||||
manager, manager_bind);
|
||||
if (!manager->global) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->event_loop = wl_display_get_event_loop(display);
|
||||
|
||||
manager->display_destroy.notify = manager_handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||
|
||||
wl_list_init(&manager->groups);
|
||||
wl_list_init(&manager->workspaces);
|
||||
wl_list_init(&manager->resources);
|
||||
wl_signal_init(&manager->events.commit);
|
||||
wl_signal_init(&manager->events.destroy);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *
|
||||
wlr_ext_workspace_group_handle_v1_create(
|
||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps) {
|
||||
struct wlr_ext_workspace_group_handle_v1 *group = calloc(1, sizeof(*group));
|
||||
if (!group) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
group->manager = manager;
|
||||
group->caps = caps;
|
||||
|
||||
wl_list_init(&group->outputs);
|
||||
wl_list_init(&group->resources);
|
||||
wl_signal_init(&group->events.destroy);
|
||||
|
||||
wl_list_insert(manager->groups.prev, &group->link);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
create_group_resource(group, manager_res);
|
||||
if (!group_res) {
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
||||
group_res->resource);
|
||||
group_send_details(group_res);
|
||||
}
|
||||
|
||||
manager_schedule_done(manager);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
bool enter) {
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group->resources, link) {
|
||||
if (group_res->manager != workspace_res->manager) {
|
||||
continue;
|
||||
}
|
||||
if (enter) {
|
||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
||||
group_res->resource, workspace_res->resource);
|
||||
} else {
|
||||
ext_workspace_group_handle_v1_send_workspace_leave(
|
||||
group_res->resource, workspace_res->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
||||
wl_list_remove(&group_output->output_bind.link);
|
||||
wl_list_remove(&group_output->output_destroy.link);
|
||||
wl_list_remove(&group_output->link);
|
||||
free(group_output);
|
||||
}
|
||||
|
||||
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output, bool enter) {
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group->resources, link) {
|
||||
struct wl_client *client = wl_resource_get_client(group_res->resource);
|
||||
|
||||
struct wl_resource *output_resource;
|
||||
wl_resource_for_each(output_resource, &output->resources) {
|
||||
if (wl_resource_get_client(output_resource) != client) {
|
||||
continue;
|
||||
}
|
||||
if (enter) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(
|
||||
group_res->resource, output_resource);
|
||||
} else {
|
||||
ext_workspace_group_handle_v1_send_output_leave(
|
||||
group_res->resource, output_resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&group->events.destroy.listener_list));
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
wl_list_for_each(workspace, &group->manager->workspaces, link) {
|
||||
if (workspace->group == group) {
|
||||
workspace_send_group(workspace, group, false);
|
||||
workspace->group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp;
|
||||
wl_list_for_each_safe(group_res, tmp, &group->resources, link) {
|
||||
ext_workspace_group_handle_v1_send_removed(group_res->resource);
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
||||
clear_requests_by(manager_res, group, NULL);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
||||
wl_list_for_each_safe(group_output, tmp3, &group->outputs, link) {
|
||||
group_send_output(group, group_output->output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
|
||||
wl_list_remove(&group->link);
|
||||
free(group);
|
||||
}
|
||||
|
||||
static void handle_output_bind(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
wl_container_of(listener, group_output, output_bind);
|
||||
struct wlr_output_event_bind *event = data;
|
||||
struct wl_client *client = wl_resource_get_client(event->resource);
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group_output->group->resources, link) {
|
||||
if (wl_resource_get_client(group_res->resource) == client) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(group_res->resource,
|
||||
event->resource);
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group_output->group->manager);
|
||||
}
|
||||
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
wl_container_of(listener, group_output, output_destroy);
|
||||
group_send_output(group_output->group, group_output->output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_v1_group_output *
|
||||
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
||||
wl_list_for_each(group_output, &group->outputs, link) {
|
||||
if (group_output->output == output) {
|
||||
return group_output;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
if (get_group_output(group, output)) {
|
||||
return;
|
||||
}
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
calloc(1, sizeof(*group_output));
|
||||
if (!group_output) {
|
||||
return;
|
||||
}
|
||||
group_output->output = output;
|
||||
group_output->group = group;
|
||||
wl_list_insert(&group->outputs, &group_output->link);
|
||||
|
||||
group_output->output_bind.notify = handle_output_bind;
|
||||
wl_signal_add(&output->events.bind, &group_output->output_bind);
|
||||
group_output->output_destroy.notify = handle_output_destroy;
|
||||
wl_signal_add(&output->events.destroy, &group_output->output_destroy);
|
||||
|
||||
group_send_output(group, output, true);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
get_group_output(group, output);
|
||||
if (!group_output) {
|
||||
return;
|
||||
}
|
||||
|
||||
group_send_output(group, output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *
|
||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
||||
const char *id, uint32_t caps) {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace =
|
||||
calloc(1, sizeof(*workspace));
|
||||
if (!workspace) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
workspace->manager = manager;
|
||||
workspace->caps = caps;
|
||||
|
||||
if (id) {
|
||||
workspace->id = strdup(id);
|
||||
if (!workspace->id) {
|
||||
free(workspace);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_init(&workspace->resources);
|
||||
wl_array_init(&workspace->coordinates);
|
||||
wl_signal_init(&workspace->events.destroy);
|
||||
|
||||
wl_list_insert(manager->workspaces.prev, &workspace->link);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
create_workspace_resource(workspace, manager_res);
|
||||
if (!workspace_res) {
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
||||
workspace_res->resource);
|
||||
workspace_send_details(workspace_res);
|
||||
}
|
||||
|
||||
manager_schedule_done(manager);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
||||
|
||||
if (workspace->group) {
|
||||
workspace_send_group(workspace, workspace->group, false);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp;
|
||||
wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_removed(workspace_res->resource);
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
||||
clear_requests_by(manager_res, NULL, workspace);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
|
||||
wl_list_remove(&workspace->link);
|
||||
wl_array_release(&workspace->coordinates);
|
||||
free(workspace->id);
|
||||
free(workspace->name);
|
||||
free(workspace);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_group(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
||||
if (workspace->group == group) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workspace->group) {
|
||||
workspace_send_group(workspace, workspace->group, false);
|
||||
}
|
||||
workspace->group = group;
|
||||
if (group) {
|
||||
workspace_send_group(workspace, group, true);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_name(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name) {
|
||||
assert(name);
|
||||
|
||||
if (workspace->name && strcmp(workspace->name, name) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(workspace->name);
|
||||
workspace->name = strdup(name);
|
||||
if (workspace->name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_name(workspace_res->resource,
|
||||
workspace->name);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||
size_t coords_len) {
|
||||
size_t size = coords_len * sizeof(coords[0]);
|
||||
if (size == workspace->coordinates.size &&
|
||||
(size == 0 || memcmp(workspace->coordinates.data, coords, size) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_array_release(&workspace->coordinates);
|
||||
wl_array_init(&workspace->coordinates);
|
||||
struct wl_array arr = {
|
||||
.data = (void *)coords,
|
||||
.size = size,
|
||||
};
|
||||
wl_array_copy(&workspace->coordinates, &arr);
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_coordinates(workspace_res->resource,
|
||||
&workspace->coordinates);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
enum ext_workspace_handle_v1_state state,
|
||||
bool enabled) {
|
||||
uint32_t old_state = workspace->state;
|
||||
if (enabled) {
|
||||
workspace->state |= state;
|
||||
} else {
|
||||
workspace->state &= ~state;
|
||||
}
|
||||
if (old_state == workspace->state) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_state(workspace_res->resource,
|
||||
workspace->state);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_active(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE,
|
||||
enabled);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT,
|
||||
enabled);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN,
|
||||
enabled);
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||
|
||||
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_output;
|
||||
|
||||
enum wlr_ext_workspace_v1_request_type {
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_request {
|
||||
enum wlr_ext_workspace_v1_request_type type;
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
||||
union {
|
||||
struct {
|
||||
char *name;
|
||||
struct wlr_ext_workspace_group_handle_v1
|
||||
*group; // NULL if destroyed
|
||||
} create_workspace;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} activate;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} deactivate;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
struct wlr_ext_workspace_group_handle_v1
|
||||
*group; // NULL if destroyed
|
||||
} assign;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} remove;
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_commit_event {
|
||||
struct wl_list *requests; // wlr_ext_workspace_v1_request.link
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 {
|
||||
struct wl_global *global;
|
||||
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
||||
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
||||
|
||||
struct {
|
||||
struct wl_signal commit; // wlr_ext_workspace_v1_commit_event
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||
struct wl_event_source *idle_source;
|
||||
struct wl_event_loop *event_loop;
|
||||
struct wl_listener display_destroy;
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 {
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 {
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL
|
||||
char *id;
|
||||
char *name;
|
||||
struct wl_array coordinates;
|
||||
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
|
||||
uint32_t state; // ext_workspace_handle_v1_state
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *
|
||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
||||
uint32_t version);
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *
|
||||
wlr_ext_workspace_group_handle_v1_create(
|
||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps);
|
||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *
|
||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
||||
const char *id, uint32_t caps);
|
||||
void wlr_ext_workspace_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace);
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_group(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
||||
void wlr_ext_workspace_handle_v1_set_name(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||
size_t coords_len);
|
||||
void wlr_ext_workspace_handle_v1_set_active(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
|
||||
#endif
|
||||
230
src/mango.c
230
src/mango.c
|
|
@ -11,7 +11,6 @@
|
|||
#include <scenefx/render/fx_renderer/fx_renderer.h>
|
||||
#include <scenefx/types/fx/blur_data.h>
|
||||
#include <scenefx/types/fx/clipped_region.h>
|
||||
#include <scenefx/types/fx/corner_location.h>
|
||||
#include <scenefx/types/wlr_scene.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -41,8 +40,10 @@
|
|||
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||
#include <wlr/types/wlr_fixes.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
|
|
@ -319,7 +320,7 @@ typedef struct {
|
|||
float height_scale;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
enum corner_location corner_location;
|
||||
struct fx_corner_radii corner_location;
|
||||
bool should_scale;
|
||||
} BufferData;
|
||||
|
||||
|
|
@ -335,7 +336,13 @@ struct Client {
|
|||
struct wlr_scene_rect *droparea;
|
||||
struct wlr_scene_rect *splitindicator[4];
|
||||
struct wlr_scene_shadow *shadow;
|
||||
struct wlr_scene_rect *shield;
|
||||
struct wlr_scene_blur *blur;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wlr_scene_tree *image_capture_tree;
|
||||
struct wlr_scene *image_capture_scene;
|
||||
struct wlr_ext_image_capture_source_v1 *image_capture_source;
|
||||
struct wlr_scene_surface *image_capture_scene_surface;
|
||||
struct wlr_scene_tree *overview_scene_surface;
|
||||
struct mango_jump_label_node *jump_label_node;
|
||||
struct mango_tab_bar_node *tab_bar_node;
|
||||
|
|
@ -406,6 +413,7 @@ struct Client {
|
|||
int32_t iskilling;
|
||||
int32_t istagswitching;
|
||||
int32_t isnamedscratchpad;
|
||||
int32_t shield_when_capture;
|
||||
bool is_monocle_hide;
|
||||
bool is_pending_open_animation;
|
||||
bool is_restoring_from_ov;
|
||||
|
|
@ -434,6 +442,7 @@ struct Client {
|
|||
float unfocused_opacity;
|
||||
char oldmonname[128];
|
||||
int32_t noblur;
|
||||
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
|
||||
double master_mfact_per, master_inner_per, stack_inner_per;
|
||||
double old_master_mfact_per, old_master_inner_per, old_stack_inner_per;
|
||||
double old_scroller_pproportion;
|
||||
|
|
@ -502,6 +511,7 @@ typedef struct {
|
|||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_tree *popups;
|
||||
struct wlr_scene_shadow *shadow;
|
||||
struct wlr_scene_blur *blur;
|
||||
struct wlr_scene_layer_surface_v1 *scene_layer;
|
||||
struct wl_list link;
|
||||
struct wl_list fadeout_link;
|
||||
|
|
@ -596,6 +606,11 @@ typedef struct {
|
|||
struct wl_listener destroy;
|
||||
} SessionLock;
|
||||
|
||||
struct capture_session_tracker {
|
||||
struct wl_listener session_destroy;
|
||||
struct wlr_ext_image_copy_capture_session_v1 *session;
|
||||
};
|
||||
|
||||
typedef struct DwindleNode DwindleNode;
|
||||
struct DwindleNode {
|
||||
bool is_split;
|
||||
|
|
@ -780,6 +795,9 @@ static void virtualkeyboard(struct wl_listener *listener, void *data);
|
|||
static void virtualpointer(struct wl_listener *listener, void *data);
|
||||
static void warp_cursor(const Client *c);
|
||||
static Monitor *xytomon(double x, double y);
|
||||
static Monitor *get_monitor_nearest_to(int32_t x, int32_t y);
|
||||
static void handle_iamge_copy_capture_new_session(struct wl_listener *listener,
|
||||
void *data);
|
||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||
static void clear_fullscreen_flag(Client *c);
|
||||
|
|
@ -846,7 +864,7 @@ static double find_animation_curve_at(double t, int32_t type);
|
|||
|
||||
static void apply_opacity_to_rect_nodes(Client *c, struct wlr_scene_node *node,
|
||||
double animation_passed);
|
||||
static enum corner_location set_client_corner_location(Client *c);
|
||||
static struct fx_corner_radii set_client_corner_location(Client *c);
|
||||
static double all_output_frame_duration_ms();
|
||||
static struct wlr_scene_tree *
|
||||
wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||
|
|
@ -955,6 +973,7 @@ static struct wlr_keyboard_shortcuts_inhibit_manager_v1
|
|||
*keyboard_shortcuts_inhibit;
|
||||
static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
|
||||
static struct wlr_output_power_manager_v1 *power_mgr;
|
||||
static struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_mgr;
|
||||
static struct wlr_pointer_gestures_v1 *pointer_gestures;
|
||||
static struct wlr_drm_lease_v1_manager *drm_lease_manager;
|
||||
struct mango_print_status_manager *print_status_manager;
|
||||
|
|
@ -981,7 +1000,13 @@ static struct wl_list keyboard_shortcut_inhibitors;
|
|||
static uint32_t cursor_mode;
|
||||
static Client *grabc, *dropc;
|
||||
static int32_t rzcorner;
|
||||
static int32_t grabcx, grabcy; /* client-relative */
|
||||
static int32_t grabcx, grabcy; /* client-relative */
|
||||
|
||||
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1
|
||||
*ext_foreign_toplevel_image_capture_source_manager_v1;
|
||||
static struct wl_listener new_foreign_toplevel_capture_request;
|
||||
static struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
||||
|
||||
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
||||
static bool start_drag_window = false;
|
||||
static int32_t last_apply_drap_time = 0;
|
||||
|
|
@ -1019,6 +1044,7 @@ static struct wl_event_source *keep_idle_inhibit_source;
|
|||
static bool cursor_hidden = false;
|
||||
static bool tag_combo = false;
|
||||
static const char *cli_config_path = NULL;
|
||||
static int active_capture_count = 0;
|
||||
static bool cli_debug_log = false;
|
||||
static KeyMode keymode = {
|
||||
.mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'},
|
||||
|
|
@ -1084,6 +1110,8 @@ static struct wl_listener output_mgr_apply = {.notify = outputmgrapply};
|
|||
static struct wl_listener output_mgr_test = {.notify = outputmgrtest};
|
||||
static struct wl_listener output_power_mgr_set_mode = {.notify =
|
||||
powermgrsetmode};
|
||||
static struct wl_listener ext_image_copy_capture_mgr_new_session = {
|
||||
.notify = handle_iamge_copy_capture_new_session};
|
||||
static struct wl_listener request_activate = {.notify = urgent};
|
||||
static struct wl_listener request_cursor = {.notify = setcursor};
|
||||
static struct wl_listener request_set_psel = {.notify = setpsel};
|
||||
|
|
@ -1548,6 +1576,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
|
|||
APPLY_INT_PROP(c, r, isnamedscratchpad);
|
||||
APPLY_INT_PROP(c, r, isglobal);
|
||||
APPLY_INT_PROP(c, r, isoverlay);
|
||||
APPLY_INT_PROP(c, r, shield_when_capture);
|
||||
APPLY_INT_PROP(c, r, ignore_maximize);
|
||||
APPLY_INT_PROP(c, r, ignore_minimize);
|
||||
APPLY_INT_PROP(c, r, isnosizehint);
|
||||
|
|
@ -2560,6 +2589,7 @@ void cleanuplisteners(void) {
|
|||
wl_list_remove(&request_start_drag.link);
|
||||
wl_list_remove(&start_drag.link);
|
||||
wl_list_remove(&new_session_lock.link);
|
||||
wl_list_remove(&new_foreign_toplevel_capture_request.link);
|
||||
wl_list_remove(&tearing_new_object.link);
|
||||
wl_list_remove(&keyboard_shortcuts_inhibit_new_inhibitor.link);
|
||||
if (drm_lease_manager) {
|
||||
|
|
@ -2700,12 +2730,16 @@ static void iter_layer_scene_buffers(struct wlr_scene_buffer *buffer,
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_scene_buffer_set_backdrop_blur(buffer, true);
|
||||
wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true);
|
||||
LayerSurface *l = (LayerSurface *)user_data;
|
||||
|
||||
wlr_scene_node_set_enabled(&l->blur->node, true);
|
||||
wlr_scene_blur_set_transparency_mask_source(l->blur, buffer);
|
||||
wlr_scene_blur_set_size(l->blur, l->geom.width, l->geom.height);
|
||||
|
||||
if (config.blur_optimized) {
|
||||
wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true);
|
||||
wlr_scene_blur_set_should_only_blur_bottom_layer(l->blur, true);
|
||||
} else {
|
||||
wlr_scene_buffer_set_backdrop_blur_optimized(buffer, false);
|
||||
wlr_scene_blur_set_should_only_blur_bottom_layer(l->blur, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2763,14 +2797,18 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
// 初始化阴影
|
||||
if (layer_surface->current.exclusive_zone == 0 &&
|
||||
layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM &&
|
||||
if (layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM &&
|
||||
layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
|
||||
l->shadow =
|
||||
wlr_scene_shadow_create(l->scene, 0, 0, config.border_radius,
|
||||
config.shadows_blur, config.shadowscolor);
|
||||
wlr_scene_node_lower_to_bottom(&l->shadow->node);
|
||||
wlr_scene_node_set_enabled(&l->shadow->node, true);
|
||||
if (layer_surface->current.exclusive_zone == 0) {
|
||||
l->shadow = wlr_scene_shadow_create(
|
||||
l->scene, 0, 0, config.border_radius, config.shadows_blur,
|
||||
config.shadowscolor);
|
||||
wlr_scene_node_lower_to_bottom(&l->shadow->node);
|
||||
wlr_scene_node_set_enabled(&l->shadow->node, true);
|
||||
}
|
||||
|
||||
l->blur = wlr_scene_blur_create(l->scene, 0, 0);
|
||||
wlr_scene_node_lower_to_bottom(&l->blur->node);
|
||||
}
|
||||
|
||||
// 初始化动画
|
||||
|
|
@ -2842,7 +2880,8 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
if (!l->noblur &&
|
||||
layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM &&
|
||||
layer_surface->current.layer !=
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND &&
|
||||
l->blur) {
|
||||
|
||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||
iter_layer_scene_buffers, l);
|
||||
|
|
@ -4408,15 +4447,11 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int32_t sx,
|
|||
return;
|
||||
|
||||
if (config.blur && c && !c->noblur) {
|
||||
wlr_scene_buffer_set_backdrop_blur(buffer, true);
|
||||
wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, false);
|
||||
if (config.blur_optimized) {
|
||||
wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true);
|
||||
wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, true);
|
||||
} else {
|
||||
wlr_scene_buffer_set_backdrop_blur_optimized(buffer, false);
|
||||
wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, false);
|
||||
}
|
||||
} else {
|
||||
wlr_scene_buffer_set_backdrop_blur(buffer, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4512,6 +4547,11 @@ void init_client_properties(Client *c) {
|
|||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.initial_opacity = c->unfocused_opacity;
|
||||
c->opacity_animation.current_opacity = c->unfocused_opacity;
|
||||
c->animation.tagining = false;
|
||||
c->animation.running = false;
|
||||
c->animation.overining = false;
|
||||
c->animation.tagouting = false;
|
||||
c->animation.tagouted = false;
|
||||
}
|
||||
|
||||
void // old fix to 0.5
|
||||
|
|
@ -4554,6 +4594,18 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
c->geom.height += 2 * c->bw;
|
||||
c->overview_backup_geom = c->geom;
|
||||
|
||||
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
|
||||
.app_id = client_get_appid(c),
|
||||
.title = client_get_title(c),
|
||||
};
|
||||
|
||||
c->image_capture_scene = wlr_scene_create();
|
||||
c->ext_foreign_toplevel = wlr_ext_foreign_toplevel_handle_v1_create(
|
||||
foreign_toplevel_list, &foreign_toplevel_state);
|
||||
c->ext_foreign_toplevel->data = c;
|
||||
c->image_capture_scene_surface = wlr_scene_surface_create(
|
||||
&c->image_capture_scene->tree, client_surface(c));
|
||||
|
||||
/* Handle unmanaged clients first so we can return prior create borders
|
||||
*/
|
||||
#ifdef XWAYLAND
|
||||
|
|
@ -4594,17 +4646,26 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
c->scene, 0, 0, c->isurgent ? config.urgentcolor : config.bordercolor);
|
||||
wlr_scene_node_lower_to_bottom(&c->border->node);
|
||||
wlr_scene_node_set_position(&c->border->node, 0, 0);
|
||||
wlr_scene_rect_set_corner_radius(c->border, config.border_radius,
|
||||
config.border_radius_location_default);
|
||||
wlr_scene_rect_set_corner_radii(c->border,
|
||||
corner_radii_all(config.border_radius));
|
||||
wlr_scene_node_set_enabled(&c->border->node, true);
|
||||
|
||||
c->shadow =
|
||||
wlr_scene_shadow_create(c->scene, 0, 0, config.border_radius,
|
||||
config.shadows_blur, config.shadowscolor);
|
||||
|
||||
c->blur = wlr_scene_blur_create(c->scene_surface, 0, 0);
|
||||
wlr_scene_node_lower_to_bottom(&c->blur->node);
|
||||
|
||||
wlr_scene_node_lower_to_bottom(&c->shadow->node);
|
||||
wlr_scene_node_set_enabled(&c->shadow->node, true);
|
||||
|
||||
c->shield = wlr_scene_rect_create(c->scene_surface, 0, 0,
|
||||
(float[4]){0, 0, 0, 0xff});
|
||||
c->shield->node.data = c;
|
||||
wlr_scene_node_lower_to_bottom(&c->shield->node);
|
||||
wlr_scene_node_set_enabled(&c->shield->node, false);
|
||||
|
||||
if (config.new_is_master && selmon && !is_scroller_layout(selmon))
|
||||
// tile at the top
|
||||
wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈
|
||||
|
|
@ -4950,6 +5011,29 @@ void outputmgrapply(struct wl_listener *listener, void *data) {
|
|||
outputmgrapplyortest(config, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_new_foreign_toplevel_capture_request(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request
|
||||
*request = data;
|
||||
Client *c = request->toplevel_handle->data;
|
||||
|
||||
if (c->shield_when_capture)
|
||||
return;
|
||||
|
||||
if (c->image_capture_source == NULL) {
|
||||
c->image_capture_source =
|
||||
wlr_ext_image_capture_source_v1_create_with_scene_node(
|
||||
&c->image_capture_scene->tree.node, event_loop, alloc, drw);
|
||||
if (c->image_capture_source == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||
request, c->image_capture_source);
|
||||
}
|
||||
|
||||
void // 0.7 custom
|
||||
outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int32_t test) {
|
||||
/*
|
||||
|
|
@ -5058,6 +5142,53 @@ void printstatus(enum ipc_watch_type type) {
|
|||
wl_signal_emit(&mango_print_status, &type);
|
||||
}
|
||||
|
||||
// 会话销毁时的回调
|
||||
void handle_session_destroy(struct wl_listener *listener, void *data) {
|
||||
struct capture_session_tracker *tracker =
|
||||
wl_container_of(listener, tracker, session_destroy);
|
||||
active_capture_count--;
|
||||
wl_list_remove(&tracker->session_destroy.link);
|
||||
|
||||
Client *c = NULL;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->shield_when_capture && !c->iskilling && VISIBLEON(c, c->mon)) {
|
||||
arrange(c->mon, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "Capture session ended, active count: %d",
|
||||
active_capture_count);
|
||||
free(tracker);
|
||||
}
|
||||
|
||||
// 新会话创建时的回调
|
||||
void handle_iamge_copy_capture_new_session(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_ext_image_copy_capture_session_v1 *session = data;
|
||||
|
||||
struct capture_session_tracker *tracker = calloc(1, sizeof(*tracker));
|
||||
if (!tracker) {
|
||||
wlr_log(WLR_ERROR, "Failed to allocate capture session tracker");
|
||||
return;
|
||||
}
|
||||
tracker->session = session;
|
||||
tracker->session_destroy.notify = handle_session_destroy;
|
||||
// 监听会话的 destroy 信号,以便在会话结束时减少计数
|
||||
wl_signal_add(&session->events.destroy, &tracker->session_destroy);
|
||||
|
||||
active_capture_count++;
|
||||
|
||||
Client *c = NULL;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->shield_when_capture && !c->iskilling && VISIBLEON(c, c->mon)) {
|
||||
arrange(c->mon, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "New capture session started, active count: %d",
|
||||
active_capture_count);
|
||||
}
|
||||
|
||||
void powermgrsetmode(struct wl_listener *listener, void *data) {
|
||||
struct wlr_output_power_v1_set_mode_event *event = data;
|
||||
struct wlr_output_state state = {0};
|
||||
|
|
@ -6000,11 +6131,17 @@ void setup(void) {
|
|||
wlr_subcompositor_create(dpy);
|
||||
wlr_alpha_modifier_v1_create(dpy);
|
||||
wlr_ext_data_control_manager_v1_create(dpy, 1);
|
||||
wlr_fixes_create(dpy, 1);
|
||||
|
||||
// 在 setup 函数中
|
||||
wl_signal_init(&mango_print_status);
|
||||
wl_signal_add(&mango_print_status, &print_status_listener);
|
||||
|
||||
ext_image_copy_capture_mgr =
|
||||
wlr_ext_image_copy_capture_manager_v1_create(dpy, 1);
|
||||
wl_signal_add(&ext_image_copy_capture_mgr->events.new_session,
|
||||
&ext_image_copy_capture_mgr_new_session);
|
||||
|
||||
/* Initializes the interface used to implement urgency hints */
|
||||
activation = wlr_xdg_activation_v1_create(dpy);
|
||||
wl_signal_add(&activation->events.request_activate, &request_activate);
|
||||
|
|
@ -6015,6 +6152,15 @@ void setup(void) {
|
|||
power_mgr = wlr_output_power_manager_v1_create(dpy);
|
||||
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode);
|
||||
|
||||
foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(dpy, 1);
|
||||
ext_foreign_toplevel_image_capture_source_manager_v1 =
|
||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(dpy, 1);
|
||||
new_foreign_toplevel_capture_request.notify =
|
||||
handle_new_foreign_toplevel_capture_request;
|
||||
wl_signal_add(&ext_foreign_toplevel_image_capture_source_manager_v1->events
|
||||
.new_request,
|
||||
&new_foreign_toplevel_capture_request);
|
||||
|
||||
tearing_control = wlr_tearing_control_manager_v1_create(dpy, 1);
|
||||
tearing_new_object.notify = handle_tearing_new_object;
|
||||
wl_signal_add(&tearing_control->events.new_object, &tearing_new_object);
|
||||
|
|
@ -6303,6 +6449,11 @@ void overview_backup_surface(Client *c) {
|
|||
wlr_scene_tree_snapshot(&c->scene_surface->node, c->scene);
|
||||
wlr_scene_node_set_enabled(&c->overview_scene_surface->node, false);
|
||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||
|
||||
wlr_scene_node_reparent(&c->blur->node, c->scene_surface);
|
||||
wlr_scene_node_lower_to_bottom(&c->blur->node);
|
||||
wlr_scene_node_reparent(&c->shield->node, c->scene_surface);
|
||||
wlr_scene_node_raise_to_top(&c->shield->node);
|
||||
}
|
||||
|
||||
// 普通视图切换到overview时保存窗口的旧状态
|
||||
|
|
@ -6348,6 +6499,10 @@ void overview_restore(Client *c, const Arg *arg) {
|
|||
c->is_restoring_from_ov = (arg->ui & c->tags & TAGMASK) == 0 ? true : false;
|
||||
|
||||
if (c->overview_scene_surface) {
|
||||
wlr_scene_node_reparent(&c->blur->node, c->overview_scene_surface);
|
||||
wlr_scene_node_lower_to_bottom(&c->blur->node);
|
||||
wlr_scene_node_reparent(&c->shield->node, c->overview_scene_surface);
|
||||
wlr_scene_node_raise_to_top(&c->shield->node);
|
||||
wlr_scene_node_destroy(&c->scene_surface->node);
|
||||
c->scene_surface = c->overview_scene_surface;
|
||||
c->overview_scene_surface = NULL;
|
||||
|
|
@ -6486,6 +6641,11 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
(!c->mon || VISIBLEON(c, c->mon)))
|
||||
init_fadeout_client(c);
|
||||
|
||||
if (c->ext_foreign_toplevel) {
|
||||
wlr_ext_foreign_toplevel_handle_v1_destroy(c->ext_foreign_toplevel);
|
||||
c->ext_foreign_toplevel = NULL;
|
||||
}
|
||||
|
||||
// If the client is in a stack, remove it from the stack
|
||||
|
||||
if (c->swallowedby) {
|
||||
|
|
@ -6582,6 +6742,8 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
c->tab_bar_node = NULL;
|
||||
}
|
||||
|
||||
wlr_scene_node_destroy(&c->image_capture_scene_surface->buffer->node);
|
||||
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus(IPC_WATCH_ARRANGGE);
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
|
|
@ -6737,6 +6899,14 @@ void updatetitle(struct wl_listener *listener, void *data) {
|
|||
mango_tab_bar_node_update(c->tab_bar_node, title, 1.0);
|
||||
if (title && c->foreign_toplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title);
|
||||
if (title && c->ext_foreign_toplevel) {
|
||||
wlr_ext_foreign_toplevel_handle_v1_update_state(
|
||||
c->ext_foreign_toplevel,
|
||||
&(struct wlr_ext_foreign_toplevel_handle_v1_state){
|
||||
.title = title,
|
||||
.app_id = c->ext_foreign_toplevel->app_id,
|
||||
});
|
||||
}
|
||||
if (c == focustop(c->mon))
|
||||
printstatus(IPC_WATCH_ARRANGGE);
|
||||
}
|
||||
|
|
@ -7107,11 +7277,13 @@ void xwaylandready(struct wl_listener *listener, void *data) {
|
|||
wlr_xwayland_set_seat(xwayland, seat);
|
||||
|
||||
/* Set the default XWayland cursor to match the rest of dwl. */
|
||||
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
|
||||
wlr_xwayland_set_cursor(
|
||||
xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
|
||||
xcursor->images[0]->width, xcursor->images[0]->height,
|
||||
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
|
||||
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1))) {
|
||||
struct wlr_xcursor_image *image = xcursor->images[0];
|
||||
struct wlr_buffer *buffer = wlr_xcursor_image_get_buffer(image);
|
||||
wlr_xwayland_set_cursor(xwayland, buffer, xcursor->images[0]->hotspot_x,
|
||||
xcursor->images[0]->hotspot_y);
|
||||
}
|
||||
|
||||
/* xwayland can't auto sync the keymap, so we do it manually
|
||||
and we need to wait the xwayland completely inited
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue