Merge remote-tracking branch 'origin/main' into scenefx

This commit is contained in:
DreamMaoMao 2025-06-21 21:51:15 +08:00
commit 1f362a18da
14 changed files with 523 additions and 760 deletions

View file

@ -87,10 +87,7 @@
#include <wlr/xwayland.h>
#include <xcb/xcb_icccm.h>
#endif
#include "common/util.h"
#include "dwl-ipc-unstable-v2-protocol.h"
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
/* macros */
#define MAX(A, B) ((A) > (B) ? (A) : (B))
@ -151,11 +148,11 @@ enum {
enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* smartmovewin */
enum { NONE, OPEN, MOVE, CLOSE, TAG };
struct vec2 {
struct dvec2 {
double x, y;
};
struct uvec2 {
struct ivec2 {
int x, y;
};
@ -203,6 +200,7 @@ struct dwl_animation {
typedef struct Pertag Pertag;
typedef struct Monitor Monitor;
struct wlr_foreign_toplevel_handle_v1;
typedef struct {
float width_scale;
@ -502,38 +500,7 @@ static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir);
static void setcursorshape(struct wl_listener *listener, void *data);
static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
unsigned int version, unsigned int 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,
unsigned int 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);
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
static void dwl_ipc_output_set_client_tags(struct wl_client *client,
struct wl_resource *resource,
unsigned int and_tags,
unsigned int xor_tags);
static void dwl_ipc_output_set_layout(struct wl_client *client,
struct wl_resource *resource,
unsigned int index);
static void dwl_ipc_output_set_tags(struct wl_client *client,
struct wl_resource *resource,
unsigned int tagmask,
unsigned int 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);
static void focusclient(Client *c, int lift);
static void setborder_color(Client *c);
@ -636,14 +603,6 @@ static void show_scratchpad(Client *c);
static void show_hide_client(Client *c);
static void tag_client(const Arg *arg, Client *target_client);
static void handle_foreign_activate_request(struct wl_listener *listener,
void *data);
static void handle_foreign_fullscreen_request(struct wl_listener *listener,
void *data);
static void handle_foreign_close_request(struct wl_listener *listener,
void *data);
static void handle_foreign_destroy(struct wl_listener *listener, void *data);
static struct wlr_box setclient_coordinate_center(Client *c,
struct wlr_box geom,
int offsetx, int offsety);
@ -670,6 +629,7 @@ static int hidecursor(void *data);
static bool check_hit_no_border(Client *c);
static void reset_keyboard_layout(void);
static void client_update_oldmonname_record(Client *c, Monitor *m);
static void pending_kill_client(Client *c);
#include "data/static_keymap.h"
#include "dispatch/dispatch.h"
@ -683,7 +643,6 @@ static void *exclusive_focus;
static struct wl_display *dpy;
static struct wl_event_loop *event_loop;
static struct wlr_relative_pointer_manager_v1 *pointer_manager;
static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
static struct wlr_backend *backend;
static struct wlr_backend *headless_backend;
static struct wlr_scene *scene;
@ -745,10 +704,10 @@ static double swipe_dy = 0;
bool render_border = true;
struct vec2 *baked_points_move;
struct vec2 *baked_points_open;
struct vec2 *baked_points_tag;
struct vec2 *baked_points_close;
struct dvec2 *baked_points_move;
struct dvec2 *baked_points_open;
struct dvec2 *baked_points_tag;
struct dvec2 *baked_points_close;
static struct wl_event_source *hide_source;
static bool cursor_hidden = false;
@ -759,7 +718,7 @@ static struct {
int hotspot_y;
} last_cursor;
#include "config/preset_config.h"
#include "config/preset.h"
struct Pertag {
unsigned int curtag, prevtag; /* current and previous tag */
@ -770,18 +729,6 @@ struct Pertag {
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
};
/* 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};
static struct wl_listener cursor_axis = {.notify = axisnotify};
static struct wl_listener cursor_button = {.notify = buttonpress};
static struct wl_listener cursor_frame = {.notify = cursorframe};
@ -829,11 +776,11 @@ static struct wlr_xwayland *xwayland;
#include "client/client.h"
#include "config/parse_config.h"
#include "ext-protocol/all.h"
#include "layout/layout.h"
#include "text_input/ime.h"
struct vec2 calculate_animation_curve_at(double t, int type) {
struct vec2 point;
struct dvec2 calculate_animation_curve_at(double t, int type) {
struct dvec2 point;
double *animation_curve;
if (type == MOVE) {
animation_curve = animation_curve_move;
@ -886,7 +833,7 @@ double find_animation_curve_at(double t, int type) {
unsigned int up = BAKED_POINTS_COUNT - 1;
unsigned int middle = (up + down) / 2;
struct vec2 *baked_points;
struct dvec2 *baked_points;
if (type == MOVE) {
baked_points = baked_points_move;
} else if (type == OPEN) {
@ -1247,10 +1194,10 @@ enum corner_location set_client_corner_location(Client *c) {
return current_corner_location;
}
struct uvec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
int offsetx = 0;
int offsety = 0;
struct uvec2 offset;
struct ivec2 offset;
offset.x = 0;
offset.y = 0;
@ -1315,8 +1262,8 @@ void client_apply_clip(Client *c) {
if (c->iskilling || !client_surface(c)->mapped)
return;
struct wlr_box clip_box;
struct uvec2 offset;
bool should_render_client_surface = false;
struct ivec2 offset;
animationScale scale_data;
struct wlr_box surface_clip;
enum corner_location current_corner_location =
@ -1564,51 +1511,6 @@ void show_scratchpad(Client *c) {
setborder_color(c);
}
void remove_foreign_topleve(Client *c) {
wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
c->foreign_toplevel = NULL;
}
void add_foreign_toplevel(Client *c) {
if (!c || !c->mon || !c->mon->wlr_output || !c->mon->wlr_output->enabled)
return;
c->foreign_toplevel =
wlr_foreign_toplevel_handle_v1_create(foreign_toplevel_manager);
// 监听来自外部对于窗口的事件请求
if (c->foreign_toplevel) {
LISTEN(&(c->foreign_toplevel->events.request_activate),
&c->foreign_activate_request, handle_foreign_activate_request);
LISTEN(&(c->foreign_toplevel->events.request_fullscreen),
&c->foreign_fullscreen_request,
handle_foreign_fullscreen_request);
LISTEN(&(c->foreign_toplevel->events.request_close),
&c->foreign_close_request, handle_foreign_close_request);
LISTEN(&(c->foreign_toplevel->events.destroy), &c->foreign_destroy,
handle_foreign_destroy);
// 设置外部顶层句柄的id为应用的id
const char *appid;
appid = client_get_appid(c);
if (appid)
wlr_foreign_toplevel_handle_v1_set_app_id(c->foreign_toplevel,
appid);
// 设置外部顶层句柄的title为应用的title
const char *title;
title = client_get_title(c);
if (title)
wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel,
title);
// 设置外部顶层句柄的显示监视器为当前监视器
wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel,
c->mon->wlr_output);
}
}
void reset_foreign_tolevel(Client *c) {
remove_foreign_topleve(c);
add_foreign_toplevel(c);
}
pid_t getparentprocess(pid_t p) {
unsigned int v = 0;
@ -1643,9 +1545,12 @@ Client *termforwin(Client *w) {
if (!w->pid || w->isterm || w->noswallow)
return NULL;
wl_list_for_each(c, &fstack,
flink) if (c->isterm && !c->swallowing && c->pid &&
isdescprocess(c->pid, w->pid)) return c;
wl_list_for_each(c, &fstack, flink) {
if (c->isterm && !c->swallowing && c->pid &&
isdescprocess(c->pid, w->pid)) {
return c;
}
}
return NULL;
}
@ -3014,7 +2919,7 @@ void cleanup(void) {
destroykeyboardgroup(&kb_group->destroy, NULL);
input_method_relay_finish(input_method_relay);
dwl_im_relay_finish(dwl_input_method_relay);
/* If it's not destroyed manually it will cause a use-after-free of
* wlr_seat. Destroy it until it's fixed in the wlroots side */
@ -3876,227 +3781,6 @@ Monitor *dirtomon(enum wlr_direction dir) {
return selmon;
}
void dwl_ipc_manager_bind(struct wl_client *client, void *data,
unsigned int version, unsigned int 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 (unsigned int 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, unsigned int 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);
}
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);
}
void dwl_ipc_output_printstatus(Monitor *monitor) {
DwlIpcOutput *ipc_output;
wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
dwl_ipc_output_printstatus_to(ipc_output);
}
void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
Monitor *monitor = ipc_output->mon;
Client *c, *focused;
int tagmask, state, numclients, focused_client, tag;
const char *title, *appid, *symbol;
focused = focustop(monitor);
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
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;
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);
}
title = focused ? client_get_title(focused) : "";
appid = focused ? client_get_appid(focused) : "";
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
zdwl_ipc_output_v2_send_layout(
ipc_output->resource,
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);
zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, symbol);
if (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 (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);
}
if (wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_x(ipc_output->resource,
focused ? focused->geom.x : 0);
}
if (wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_y(ipc_output->resource,
focused ? focused->geom.y : 0);
}
if (wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_width(ipc_output->resource,
focused ? focused->geom.width : 0);
}
if (wl_resource_get_version(ipc_output->resource) >=
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_height(ipc_output->resource,
focused ? focused->geom.height : 0);
}
zdwl_ipc_output_v2_send_frame(ipc_output->resource);
}
void dwl_ipc_output_set_client_tags(struct wl_client *client,
struct wl_resource *resource,
unsigned int and_tags,
unsigned int xor_tags) {
DwlIpcOutput *ipc_output;
Monitor *monitor;
Client *selected_client;
unsigned int 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();
}
void dwl_ipc_output_set_layout(struct wl_client *client,
struct wl_resource *resource,
unsigned int index) {
DwlIpcOutput *ipc_output;
Monitor *monitor;
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];
arrange(monitor, false);
printstatus();
}
void dwl_ipc_output_set_tags(struct wl_client *client,
struct wl_resource *resource, unsigned int tagmask,
unsigned int toggle_tagset) {
DwlIpcOutput *ipc_output;
Monitor *monitor;
unsigned int 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);
}
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) {
void (*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);
}
}
void dwl_ipc_output_release(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
void focusclient(Client *c, int lift) {
struct wlr_surface *old_keyboard_focus_surface =
seat->keyboard_state.focused_surface;
@ -4196,7 +3880,7 @@ void focusclient(Client *c, int lift) {
NULL; // 这个很关键,因为很多地方用到当前窗口做计算,不重置成NULL就会到处有野指针
// clear text input focus state
input_method_relay_set_focus(input_method_relay, NULL);
dwl_im_relay_set_focus(dwl_input_method_relay, NULL);
wlr_seat_keyboard_notify_clear_focus(seat);
return;
}
@ -4208,7 +3892,7 @@ void focusclient(Client *c, int lift) {
client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat));
// set text input focus
input_method_relay_set_focus(input_method_relay, client_surface(c));
dwl_im_relay_set_focus(dwl_input_method_relay, client_surface(c));
/* Activate the new client */
client_activate_surface(client_surface(c), 1);
}
@ -4558,7 +4242,7 @@ void keypress(struct wl_listener *listener, void *data) {
if (hit_global) {
return;
}
if (!input_method_keyboard_grab_forward_key(group, event)) {
if (!dwl_im_keyboard_grab_forward_key(group, event)) {
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
/* Pass unhandled keycodes along to the client. */
wlr_seat_keyboard_notify_key(seat, event->time_msec, event->keycode,
@ -4571,7 +4255,7 @@ void keypressmod(struct wl_listener *listener, void *data) {
* pressed. We simply communicate this to the client. */
KeyboardGroup *group = wl_container_of(listener, group, modifiers);
if (!input_method_keyboard_grab_forward_modifiers(group)) {
if (!dwl_im_keyboard_grab_forward_modifiers(group)) {
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
/* Send modifiers to the client. */
wlr_seat_keyboard_notify_modifiers(
@ -6463,55 +6147,6 @@ void show_hide_client(Client *c) {
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
}
void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_activate_request);
unsigned int target;
if (c && c->swallowing)
return;
if (c && !c->isminied && c == selmon->sel) {
set_minized(c);
return;
}
if (c->isminied) {
c->is_in_scratchpad = 0;
c->isnamedscratchpand = 0;
c->is_scratchpad_show = 0;
setborder_color(c);
show_hide_client(c);
return;
}
target = get_tags_first_tag(c->tags);
view(&(Arg){.ui = target}, true);
focusclient(c, 1);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
}
void handle_foreign_fullscreen_request(struct wl_listener *listener,
void *data) {
return;
}
void handle_foreign_close_request(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_close_request);
if (c) {
pending_kill_client(c);
}
}
void handle_foreign_destroy(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_destroy);
if (c) {
wl_list_remove(&c->foreign_activate_request.link);
wl_list_remove(&c->foreign_fullscreen_request.link);
wl_list_remove(&c->foreign_close_request.link);
wl_list_remove(&c->foreign_destroy.link);
}
}
void create_output(struct wlr_backend *backend, void *data) {
bool *done = data;
if (*done) {
@ -6821,8 +6456,8 @@ void setup(void) {
input_method_manager = wlr_input_method_manager_v2_create(dpy);
text_input_manager = wlr_text_input_manager_v3_create(dpy);
input_method_relay = calloc(1, sizeof(*input_method_relay));
input_method_relay = input_method_relay_create();
dwl_input_method_relay = calloc(1, sizeof(*dwl_input_method_relay));
dwl_input_method_relay = dwl_im_relay_create();
wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL,
dwl_ipc_manager_bind);