maomaowm/src/ext-protocol/dwl-ipc.h
2025-12-02 16:58:04 +08:00

383 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dwl-ipc-unstable-v2-protocol.h"
static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
static void dwl_ipc_manager_destroy(struct wl_resource *resource);
static void dwl_ipc_manager_get_output(struct wl_client *client,
struct wl_resource *resource,
uint32_t id, struct wl_resource *output);
static void dwl_ipc_manager_release(struct wl_client *client,
struct wl_resource *resource);
static void dwl_ipc_output_destroy(struct wl_resource *resource);
static void dwl_ipc_output_printstatus(Monitor *monitor, uint32_t event_mask);
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output,
uint32_t event_mask);
static void dwl_ipc_output_set_client_tags(struct wl_client *client,
struct wl_resource *resource,
uint32_t and_tags,
uint32_t xor_tags);
static void dwl_ipc_output_set_layout(struct wl_client *client,
struct wl_resource *resource,
uint32_t index);
static void dwl_ipc_output_set_tags(struct wl_client *client,
struct wl_resource *resource,
uint32_t tagmask, uint32_t toggle_tagset);
static void dwl_ipc_output_quit(struct wl_client *client,
struct wl_resource *resource);
static void dwl_ipc_output_dispatch(struct wl_client *client,
struct wl_resource *resource,
const char *dispatch, const char *arg1,
const char *arg2, const char *arg3,
const char *arg4, const char *arg5);
static void dwl_ipc_output_release(struct wl_client *client,
struct wl_resource *resource);
/* global event handlers */
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {
.release = dwl_ipc_manager_release,
.get_output = dwl_ipc_manager_get_output};
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {
.release = dwl_ipc_output_release,
.set_tags = dwl_ipc_output_set_tags,
.quit = dwl_ipc_output_quit,
.dispatch = dwl_ipc_output_dispatch,
.set_layout = dwl_ipc_output_set_layout,
.set_client_tags = dwl_ipc_output_set_client_tags};
void dwl_ipc_manager_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id) {
struct wl_resource *manager_resource =
wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
if (!manager_resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(manager_resource,
&dwl_manager_implementation, NULL,
dwl_ipc_manager_destroy);
zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags));
for (uint32_t i = 0; i < LENGTH(layouts); i++)
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
}
void dwl_ipc_manager_destroy(struct wl_resource *resource) {
/* No state to destroy */
}
void dwl_ipc_manager_get_output(struct wl_client *client,
struct wl_resource *resource, uint32_t id,
struct wl_resource *output) {
DwlIpcOutput *ipc_output;
struct wlr_output *op = wlr_output_from_resource(output);
if (!op)
return;
Monitor *monitor = op->data;
struct wl_resource *output_resource =
wl_resource_create(client, &zdwl_ipc_output_v2_interface,
wl_resource_get_version(resource), id);
if (!output_resource)
return;
ipc_output = ecalloc(1, sizeof(*ipc_output));
ipc_output->resource = output_resource;
ipc_output->mon = monitor;
wl_resource_set_implementation(output_resource, &dwl_output_implementation,
ipc_output, dwl_ipc_output_destroy);
wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
dwl_ipc_output_printstatus_to(ipc_output, PRINT_ALL);
}
void dwl_ipc_manager_release(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static void dwl_ipc_output_destroy(struct wl_resource *resource) {
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
wl_list_remove(&ipc_output->link);
free(ipc_output);
}
// 修改IPC输出函数接受掩码参数
void dwl_ipc_output_printstatus(Monitor *monitor, uint32_t event_mask) {
DwlIpcOutput *ipc_output;
wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
dwl_ipc_output_printstatus_to(ipc_output, event_mask);
}
// 修改主IPC输出函数根据掩码发送相应事件
void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output,
uint32_t event_mask) {
Monitor *monitor = ipc_output->mon;
Client *c = NULL, *focused = NULL;
struct wlr_keyboard *keyboard;
xkb_layout_index_t current;
int tagmask, state, numclients, focused_client, tag;
const char *title, *appid, *symbol;
char kb_layout[32];
// 只在需要时才获取这些数据
if (event_mask & (PRINT_ACTIVE | PRINT_TAG | PRINT_TITLE | PRINT_APPID |
PRINT_FULLSCREEN | PRINT_FLOATING | PRINT_X | PRINT_Y |
PRINT_WIDTH | PRINT_HEIGHT)) {
focused = focustop(monitor);
}
// 发送活动状态
if (event_mask & PRINT_ACTIVE) {
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
}
// 发送标签状态
if (event_mask & PRINT_TAG) {
for (tag = 0; tag < LENGTH(tags); tag++) {
numclients = state = focused_client = 0;
tagmask = 1 << tag;
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
if (focused) {
wl_list_for_each(c, &clients, link) {
if (c->mon != monitor)
continue;
if (!(c->tags & tagmask))
continue;
if (c == focused)
focused_client = 1;
if (c->isurgent)
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
numclients++;
}
}
zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state,
numclients, focused_client);
}
}
// 只在需要时才获取标题和应用ID
if (event_mask & (PRINT_TITLE | PRINT_APPID)) {
title = focused ? client_get_title(focused) : "";
appid = focused ? client_get_appid(focused) : "";
}
// 获取布局符号
if (event_mask & PRINT_LAYOUT_SYMBOL) {
if (monitor->isoverview) {
symbol = overviewlayout.symbol;
} else {
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
}
}
// 发送布局索引
if (event_mask & PRINT_LAYOUT) {
zdwl_ipc_output_v2_send_layout(
ipc_output->resource,
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);
}
// 发送标题
if (event_mask & PRINT_TITLE) {
zdwl_ipc_output_v2_send_title(ipc_output->resource,
title ? title : broken);
}
// 发送应用ID
if (event_mask & PRINT_APPID) {
zdwl_ipc_output_v2_send_appid(ipc_output->resource,
appid ? appid : broken);
}
// 发送布局符号
if (event_mask & PRINT_LAYOUT_SYMBOL) {
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, symbol);
}
// 发送全屏状态
if ((event_mask & PRINT_FULLSCREEN) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource,
focused ? focused->isfullscreen : 0);
}
// 发送浮动状态
if ((event_mask & PRINT_FLOATING) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_floating(ipc_output->resource,
focused ? focused->isfloating : 0);
}
// 发送X坐标
if ((event_mask & PRINT_X) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_X_SINCE_VERSION) {
zdwl_ipc_output_v2_send_x(ipc_output->resource,
focused ? focused->geom.x : 0);
}
// 发送Y坐标
if ((event_mask & PRINT_Y) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_Y_SINCE_VERSION) {
zdwl_ipc_output_v2_send_y(ipc_output->resource,
focused ? focused->geom.y : 0);
}
// 发送宽度
if ((event_mask & PRINT_WIDTH) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_WIDTH_SINCE_VERSION) {
zdwl_ipc_output_v2_send_width(ipc_output->resource,
focused ? focused->geom.width : 0);
}
// 发送高度
if ((event_mask & PRINT_HEIGHT) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_HEIGHT_SINCE_VERSION) {
zdwl_ipc_output_v2_send_height(ipc_output->resource,
focused ? focused->geom.height : 0);
}
// 发送最后图层
if ((event_mask & PRINT_LAST_LAYER) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_LAST_LAYER_SINCE_VERSION) {
zdwl_ipc_output_v2_send_last_layer(ipc_output->resource,
monitor->last_surface_ws_name);
}
// 获取键盘布局(只在需要时)
if (event_mask & PRINT_KB_LAYOUT) {
keyboard = &kb_group->wlr_group->keyboard;
current = xkb_state_serialize_layout(keyboard->xkb_state,
XKB_STATE_LAYOUT_EFFECTIVE);
get_layout_abbr(kb_layout,
xkb_keymap_layout_get_name(keyboard->keymap, current));
}
// 发送键盘布局
if ((event_mask & PRINT_KB_LAYOUT) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_KB_LAYOUT_SINCE_VERSION) {
zdwl_ipc_output_v2_send_kb_layout(ipc_output->resource, kb_layout);
}
// 发送键模式
if ((event_mask & PRINT_KEYMODE) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_KEYMODE_SINCE_VERSION) {
zdwl_ipc_output_v2_send_keymode(ipc_output->resource, keymode.mode);
}
// 发送缩放因子
if ((event_mask & PRINT_SCALEFACTOR) &&
wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_SCALEFACTOR_SINCE_VERSION) {
zdwl_ipc_output_v2_send_scalefactor(ipc_output->resource,
monitor->wlr_output->scale * 100);
}
// 发送帧结束标记
if (event_mask & PRINT_FRAME) {
zdwl_ipc_output_v2_send_frame(ipc_output->resource);
}
}
void dwl_ipc_output_set_client_tags(struct wl_client *client,
struct wl_resource *resource,
uint32_t and_tags, uint32_t xor_tags) {
DwlIpcOutput *ipc_output;
Monitor *monitor = NULL;
Client *selected_client = NULL;
uint32_t newtags = 0;
ipc_output = wl_resource_get_user_data(resource);
if (!ipc_output)
return;
monitor = ipc_output->mon;
selected_client = focustop(monitor);
if (!selected_client)
return;
newtags = (selected_client->tags & and_tags) ^ xor_tags;
if (!newtags)
return;
selected_client->tags = newtags;
if (selmon == monitor)
focusclient(focustop(monitor), 1);
arrange(selmon, false);
printstatus(PRINT_ALL);
}
void dwl_ipc_output_set_layout(struct wl_client *client,
struct wl_resource *resource, uint32_t index) {
DwlIpcOutput *ipc_output;
Monitor *monitor = NULL;
ipc_output = wl_resource_get_user_data(resource);
if (!ipc_output)
return;
monitor = ipc_output->mon;
if (index >= LENGTH(layouts))
index = 0;
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
clear_fullscreen_and_maximized_state(monitor);
arrange(monitor, false);
printstatus(PRINT_ALL);
}
void dwl_ipc_output_set_tags(struct wl_client *client,
struct wl_resource *resource, uint32_t tagmask,
uint32_t toggle_tagset) {
DwlIpcOutput *ipc_output;
Monitor *monitor = NULL;
uint32_t newtags = tagmask & TAGMASK;
ipc_output = wl_resource_get_user_data(resource);
if (!ipc_output)
return;
monitor = ipc_output->mon;
view_in_mon(&(Arg){.ui = newtags}, true, monitor, true);
}
void dwl_ipc_output_quit(struct wl_client *client,
struct wl_resource *resource) {
quit(&(Arg){0});
}
void dwl_ipc_output_dispatch(struct wl_client *client,
struct wl_resource *resource, const char *dispatch,
const char *arg1, const char *arg2,
const char *arg3, const char *arg4,
const char *arg5) {
int (*func)(const Arg *);
Arg arg;
func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2,
(char *)arg3, (char *)arg4, (char *)arg5);
if (func) {
func(&arg);
}
if (arg.v)
free(arg.v);
if (arg.v2)
free(arg.v2);
if (arg.v3)
free(arg.v3);
}
void dwl_ipc_output_release(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}