mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-10-29 05:40:21 -04:00
feat: support switchbind
This commit is contained in:
parent
a3ae2cea47
commit
03ce91572a
2 changed files with 265 additions and 83 deletions
|
|
@ -115,6 +115,12 @@ typedef struct {
|
|||
Arg arg;
|
||||
} AxisBinding;
|
||||
|
||||
typedef struct {
|
||||
unsigned int fold;
|
||||
void (*func)(const Arg *);
|
||||
Arg arg;
|
||||
} SwitchBinding;
|
||||
|
||||
typedef struct {
|
||||
unsigned int mod;
|
||||
unsigned int motion;
|
||||
|
|
@ -279,6 +285,9 @@ typedef struct {
|
|||
AxisBinding *axis_bindings;
|
||||
int axis_bindings_count;
|
||||
|
||||
SwitchBinding *switch_bindings;
|
||||
int switch_bindings_count;
|
||||
|
||||
GestureBinding *gesture_bindings;
|
||||
int gesture_bindings_count;
|
||||
|
||||
|
|
@ -407,6 +416,25 @@ int parse_direction(const char *str) {
|
|||
}
|
||||
}
|
||||
|
||||
int parse_fold_state(const char *str) {
|
||||
// 将输入字符串转换为小写
|
||||
char lowerStr[10];
|
||||
int i = 0;
|
||||
while (str[i] && i < 9) {
|
||||
lowerStr[i] = tolower(str[i]);
|
||||
i++;
|
||||
}
|
||||
lowerStr[i] = '\0';
|
||||
|
||||
// 根据转换后的小写字符串返回对应的枚举值
|
||||
if (strcmp(lowerStr, "fold") == 0) {
|
||||
return FOLD;
|
||||
} else if (strcmp(lowerStr, "unfold") == 0) {
|
||||
return UNFOLD;
|
||||
} else {
|
||||
return INVALIDFOLD;
|
||||
}
|
||||
}
|
||||
long int parse_color(const char *hex_str) {
|
||||
char *endptr;
|
||||
long int hex_num = strtol(hex_str, &endptr, 16);
|
||||
|
|
@ -1834,6 +1862,62 @@ void parse_config_line(Config *config, const char *line) {
|
|||
config->axis_bindings_count++;
|
||||
}
|
||||
|
||||
} else if (strncmp(key, "switchbind", 10) == 0) {
|
||||
config->switch_bindings = realloc(config->switch_bindings,
|
||||
(config->switch_bindings_count + 1) *
|
||||
sizeof(SwitchBinding));
|
||||
if (!config->switch_bindings) {
|
||||
fprintf(stderr,
|
||||
"Error: Failed to allocate memory for switch bindings\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchBinding *binding =
|
||||
&config->switch_bindings[config->switch_bindings_count];
|
||||
memset(binding, 0, sizeof(SwitchBinding));
|
||||
|
||||
char fold_str[256], func_name[256],
|
||||
arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
fold_str, func_name, arg_value, arg_value2, arg_value3,
|
||||
arg_value4, arg_value5) < 3) {
|
||||
fprintf(stderr, "Error: Invalid switchbind format: %s\n", value);
|
||||
return;
|
||||
}
|
||||
trim_whitespace(fold_str);
|
||||
trim_whitespace(func_name);
|
||||
trim_whitespace(arg_value);
|
||||
trim_whitespace(arg_value2);
|
||||
trim_whitespace(arg_value3);
|
||||
trim_whitespace(arg_value4);
|
||||
trim_whitespace(arg_value5);
|
||||
|
||||
binding->fold = parse_fold_state(fold_str);
|
||||
binding->func =
|
||||
parse_func_name(func_name, &binding->arg, arg_value, arg_value2,
|
||||
arg_value3, arg_value4, arg_value5);
|
||||
|
||||
if (!binding->func) {
|
||||
if (binding->arg.v) {
|
||||
free(binding->arg.v);
|
||||
binding->arg.v = NULL;
|
||||
}
|
||||
if (binding->arg.v2) {
|
||||
free(binding->arg.v2);
|
||||
binding->arg.v2 = NULL;
|
||||
}
|
||||
if (binding->arg.v3) {
|
||||
free(binding->arg.v3);
|
||||
binding->arg.v3 = NULL;
|
||||
}
|
||||
fprintf(stderr, "Error: Unknown function in switchbind: %s\n",
|
||||
func_name);
|
||||
} else {
|
||||
config->switch_bindings_count++;
|
||||
}
|
||||
|
||||
} else if (strncmp(key, "gesturebind", 11) == 0) {
|
||||
config->gesture_bindings = realloc(
|
||||
config->gesture_bindings,
|
||||
|
|
@ -2086,6 +2170,27 @@ void free_config(void) {
|
|||
config.axis_bindings_count = 0;
|
||||
}
|
||||
|
||||
// 释放 switch_bindings
|
||||
if (config.switch_bindings) {
|
||||
for (i = 0; i < config.switch_bindings_count; i++) {
|
||||
if (config.switch_bindings[i].arg.v) {
|
||||
free((void *)config.switch_bindings[i].arg.v);
|
||||
config.switch_bindings[i].arg.v = NULL;
|
||||
}
|
||||
if (config.switch_bindings[i].arg.v2) {
|
||||
free((void *)config.switch_bindings[i].arg.v2);
|
||||
config.switch_bindings[i].arg.v2 = NULL;
|
||||
}
|
||||
if (config.switch_bindings[i].arg.v3) {
|
||||
free((void *)config.switch_bindings[i].arg.v3);
|
||||
config.switch_bindings[i].arg.v3 = NULL;
|
||||
}
|
||||
}
|
||||
free(config.switch_bindings);
|
||||
config.switch_bindings = NULL;
|
||||
config.switch_bindings_count = 0;
|
||||
}
|
||||
|
||||
// 释放 gesture_bindings
|
||||
if (config.gesture_bindings) {
|
||||
for (i = 0; i < config.gesture_bindings_count; i++) {
|
||||
|
|
@ -2404,8 +2509,8 @@ void set_value_default() {
|
|||
|
||||
config.inhibit_regardless_of_visibility =
|
||||
inhibit_regardless_of_visibility; /* 1 means idle inhibitors will
|
||||
disable idle tracking even if it's surface
|
||||
isn't visible
|
||||
disable idle tracking even if it's
|
||||
surface isn't visible
|
||||
*/
|
||||
|
||||
config.borderpx = borderpx;
|
||||
|
|
@ -2522,6 +2627,8 @@ void parse_config(void) {
|
|||
config.mouse_bindings_count = 0;
|
||||
config.axis_bindings = NULL;
|
||||
config.axis_bindings_count = 0;
|
||||
config.switch_bindings = NULL;
|
||||
config.switch_bindings_count = 0;
|
||||
config.gesture_bindings = NULL;
|
||||
config.gesture_bindings_count = 0;
|
||||
config.exec = NULL;
|
||||
|
|
|
|||
237
src/mango.c
237
src/mango.c
|
|
@ -67,6 +67,7 @@
|
|||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_switch.h>
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
|
|
@ -159,7 +160,7 @@ enum {
|
|||
#endif
|
||||
enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* smartmovewin */
|
||||
enum { NONE, OPEN, MOVE, CLOSE, TAG };
|
||||
|
||||
enum { UNFOLD, FOLD, INVALIDFOLD };
|
||||
struct dvec2 {
|
||||
double x, y;
|
||||
};
|
||||
|
|
@ -201,6 +202,12 @@ struct input_device {
|
|||
struct wl_listener destroy_listener; // 用于监听设备销毁事件
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct wl_list link;
|
||||
struct wlr_switch *wlr_switch;
|
||||
struct wl_listener toggle;
|
||||
} Switch;
|
||||
|
||||
struct dwl_animation {
|
||||
bool should_animate;
|
||||
bool running;
|
||||
|
|
@ -509,6 +516,9 @@ static void createnotify(struct wl_listener *listener, void *data);
|
|||
static void createpointer(struct wlr_pointer *pointer);
|
||||
static void configure_pointer(struct libinput_device *device);
|
||||
static void destroypointer(struct wl_listener *listener, void *data);
|
||||
static void createswitch(struct wlr_switch *switch_device);
|
||||
static void switch_toggle(struct wl_listener *listener, void *data);
|
||||
static void cleanupswitches();
|
||||
static void createpointerconstraint(struct wl_listener *listener, void *data);
|
||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||
static void commitpopup(struct wl_listener *listener, void *data);
|
||||
|
|
@ -737,6 +747,7 @@ static struct wlr_seat *seat;
|
|||
static KeyboardGroup *kb_group;
|
||||
static struct wl_list keyboards;
|
||||
static struct wl_list pointers;
|
||||
static struct wl_list switches;
|
||||
static unsigned int cursor_mode;
|
||||
static Client *grabc;
|
||||
static int grabcx, grabcy; /* client-relative */
|
||||
|
|
@ -1988,6 +1999,8 @@ void cleanup(void) {
|
|||
|
||||
dwl_im_relay_finish(dwl_input_method_relay);
|
||||
|
||||
cleanupswitches();
|
||||
|
||||
/* 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 */
|
||||
wlr_backend_destroy(backend);
|
||||
|
|
@ -2758,6 +2771,50 @@ void createpointer(struct wlr_pointer *pointer) {
|
|||
wlr_cursor_attach_input_device(cursor, &pointer->base);
|
||||
}
|
||||
|
||||
void switch_toggle(struct wl_listener *listener, void *data) {
|
||||
// 获取包含监听器的结构体
|
||||
Switch *sw = wl_container_of(listener, sw, toggle);
|
||||
|
||||
// 处理切换事件
|
||||
struct wlr_switch_toggle_event *event = data;
|
||||
SwitchBinding *a;
|
||||
int ji;
|
||||
|
||||
for (ji = 0; ji < config.switch_bindings_count; ji++) {
|
||||
if (config.switch_bindings_count < 1)
|
||||
break;
|
||||
a = &config.switch_bindings[ji];
|
||||
if (event->switch_state == a->fold && a->func) {
|
||||
a->func(&a->arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createswitch(struct wlr_switch *switch_device) {
|
||||
Switch *sw = calloc(1, sizeof(Switch));
|
||||
sw->wlr_switch = switch_device;
|
||||
sw->toggle.notify = switch_toggle;
|
||||
wl_signal_add(&switch_device->events.toggle, &sw->toggle);
|
||||
|
||||
// 添加到全局列表(可选,用于统一管理)
|
||||
wl_list_insert(&switches, &sw->link);
|
||||
}
|
||||
|
||||
void cleanupswitches() {
|
||||
Switch *sw, *tmp;
|
||||
wl_list_for_each_safe(sw, tmp, &switches, link) {
|
||||
// 移除事件监听
|
||||
wl_list_remove(&sw->toggle.link);
|
||||
|
||||
// 从列表中移除
|
||||
wl_list_remove(&sw->link);
|
||||
|
||||
// 释放内存
|
||||
free(sw);
|
||||
}
|
||||
}
|
||||
|
||||
void createpointerconstraint(struct wl_listener *listener, void *data) {
|
||||
PointerConstraint *pointer_constraint =
|
||||
ecalloc(1, sizeof(*pointer_constraint));
|
||||
|
|
@ -2787,8 +2844,9 @@ void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) {
|
|||
void cursorframe(struct wl_listener *listener, void *data) {
|
||||
/* This event is forwarded by the cursor when a pointer emits an frame
|
||||
* event. Frame events are sent after regular pointer events to group
|
||||
* multiple events together. For instance, two axis events may happen at the
|
||||
* same time, in which case a frame event won't be sent in between. */
|
||||
* multiple events together. For instance, two axis events may happen at
|
||||
* the same time, in which case a frame event won't be sent in between.
|
||||
*/
|
||||
/* Notify the client with pointer focus of the frame event. */
|
||||
wlr_seat_pointer_notify_frame(seat);
|
||||
}
|
||||
|
|
@ -2816,7 +2874,8 @@ void destroydragicon(struct wl_listener *listener, void *data) {
|
|||
|
||||
void destroyidleinhibitor(struct wl_listener *listener, void *data) {
|
||||
/* `data` is the wlr_surface of the idle inhibitor being destroyed,
|
||||
* at this point the idle inhibitor is still in the list of the manager */
|
||||
* at this point the idle inhibitor is still in the list of the manager
|
||||
*/
|
||||
checkidleinhibitor(wlr_surface_get_root_surface(data));
|
||||
wl_list_remove(&listener->link);
|
||||
free(listener);
|
||||
|
|
@ -3002,10 +3061,10 @@ void focusclient(Client *c, int lift) {
|
|||
/* Deactivate old client if focus is changing */
|
||||
if (old_keyboard_focus_surface &&
|
||||
(!c || client_surface(c) != old_keyboard_focus_surface)) {
|
||||
/* If an exclusive_focus layer is focused, don't focus or activate the
|
||||
* client, but only update its position in fstack to render its border
|
||||
* with focuscolor and focus it after the exclusive_focus layer is
|
||||
* closed. */
|
||||
/* If an exclusive_focus layer is focused, don't focus or activate
|
||||
* the client, but only update its position in fstack to render its
|
||||
* border with focuscolor and focus it after the exclusive_focus
|
||||
* layer is closed. */
|
||||
Client *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
int type =
|
||||
|
|
@ -3016,9 +3075,9 @@ void focusclient(Client *c, int lift) {
|
|||
return;
|
||||
} else if (w && w == exclusive_focus && client_wants_focus(w)) {
|
||||
return;
|
||||
/* Don't deactivate old_keyboard_focus_surface client if the new one
|
||||
* wants focus, as this causes issues with winecfg and probably
|
||||
* other clients */
|
||||
/* Don't deactivate old_keyboard_focus_surface client if the new
|
||||
* one wants focus, as this causes issues with winecfg and
|
||||
* probably other clients */
|
||||
} else if (w && !client_is_unmanaged(w) &&
|
||||
(!c || !client_wants_focus(c))) {
|
||||
setborder_color(w);
|
||||
|
|
@ -3081,6 +3140,9 @@ void inputdevice(struct wl_listener *listener, void *data) {
|
|||
case WLR_INPUT_DEVICE_POINTER:
|
||||
createpointer(wlr_pointer_from_input_device(device));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_SWITCH:
|
||||
createswitch(wlr_switch_from_input_device(device));
|
||||
break;
|
||||
default:
|
||||
/* TODO handle other input device types */
|
||||
break;
|
||||
|
|
@ -3088,7 +3150,8 @@ void inputdevice(struct wl_listener *listener, void *data) {
|
|||
|
||||
/* We need to let the wlr_seat know what our capabilities are, which is
|
||||
* communiciated to the client. In dwl we always have a cursor, even if
|
||||
* there are no pointer devices, so we always include that capability. */
|
||||
* there are no pointer devices, so we always include that capability.
|
||||
*/
|
||||
/* TODO do we actually require a cursor? */
|
||||
caps = WL_SEAT_CAPABILITY_POINTER;
|
||||
if (!wl_list_empty(&kb_group->wlr_group->devices))
|
||||
|
|
@ -3116,8 +3179,8 @@ int // 17
|
|||
keybinding(unsigned int mods, xkb_keysym_t sym, unsigned int keycode) {
|
||||
/*
|
||||
* Here we handle compositor keybindings. This is when the compositor is
|
||||
* processing keys, rather than passing them on to the client for its own
|
||||
* processing.
|
||||
* processing keys, rather than passing them on to the client for its
|
||||
* own processing.
|
||||
*/
|
||||
int handled = 0;
|
||||
const KeyBinding *k;
|
||||
|
|
@ -3263,8 +3326,8 @@ void keypress(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
|
||||
/* don't pass when popup is focused
|
||||
* this is better than having popups (like fuzzel or wmenu) closing while
|
||||
* typing in a passed keybind */
|
||||
* this is better than having popups (like fuzzel or wmenu) closing
|
||||
* while typing in a passed keybind */
|
||||
pass = (xdg_surface && xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) ||
|
||||
!last_surface
|
||||
#ifdef XWAYLAND
|
||||
|
|
@ -3425,7 +3488,8 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
c->geom.width += 2 * c->bw;
|
||||
c->geom.height += 2 * c->bw;
|
||||
|
||||
/* Handle unmanaged clients first so we can return prior create borders */
|
||||
/* Handle unmanaged clients first so we can return prior create borders
|
||||
*/
|
||||
if (client_is_unmanaged(c)) {
|
||||
/* Unmanaged clients always are floating */
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]);
|
||||
|
|
@ -3507,7 +3571,8 @@ maximizenotify(struct wl_listener *listener, void *data) {
|
|||
* Since xdg-shell protocol v5 we should ignore request of unsupported
|
||||
* capabilities, just schedule a empty configure when the client uses <5
|
||||
* protocol version
|
||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
|
||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply.
|
||||
*/
|
||||
// Client *c = wl_container_of(listener, c, maximize);
|
||||
// if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
|
||||
// < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||
|
|
@ -3553,7 +3618,8 @@ minimizenotify(struct wl_listener *listener, void *data) {
|
|||
* Since xdg-shell protocol v5 we should ignore request of unsupported
|
||||
* capabilities, just schedule a empty configure when the client uses <5
|
||||
* protocol version
|
||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
|
||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply.
|
||||
*/
|
||||
// Client *c = wl_container_of(listener, c, maximize);
|
||||
// if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
|
||||
// < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||
|
|
@ -3575,12 +3641,12 @@ minimizenotify(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void motionabsolute(struct wl_listener *listener, void *data) {
|
||||
/* This event is forwarded by the cursor when a pointer emits an _absolute_
|
||||
* motion event, from 0..1 on each axis. This happens, for example, when
|
||||
* wlroots is running under a Wayland window rather than KMS+DRM, and you
|
||||
* move the mouse over the window. You could enter the window from any edge,
|
||||
* so we have to warp the mouse there. There is also some hardware which
|
||||
* emits these events. */
|
||||
/* This event is forwarded by the cursor when a pointer emits an
|
||||
* _absolute_ motion event, from 0..1 on each axis. This happens, for
|
||||
* example, when wlroots is running under a Wayland window rather than
|
||||
* KMS+DRM, and you move the mouse over the window. You could enter the
|
||||
* window from any edge, so we have to warp the mouse there. There is
|
||||
* also some hardware which emits these events. */
|
||||
struct wlr_pointer_motion_absolute_event *event = data;
|
||||
double lx, ly, dx, dy;
|
||||
|
||||
|
|
@ -3681,9 +3747,9 @@ void motionnotify(unsigned int time, struct wlr_input_device *device, double dx,
|
|||
return;
|
||||
}
|
||||
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
* default. This is what makes the cursor image appear when you move it
|
||||
* off of a client or over its border. */
|
||||
/* If there's no client surface under the cursor, set the cursor image
|
||||
* to a default. This is what makes the cursor image appear when you
|
||||
* move it off of a client or over its border. */
|
||||
if (!surface && !seat->drag && !cursor_hidden)
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
|
||||
|
|
@ -3725,14 +3791,14 @@ void motionnotify(unsigned int time, struct wlr_input_device *device, double dx,
|
|||
}
|
||||
|
||||
void motionrelative(struct wl_listener *listener, void *data) {
|
||||
/* This event is forwarded by the cursor when a pointer emits a _relative_
|
||||
* pointer motion event (i.e. a delta) */
|
||||
/* This event is forwarded by the cursor when a pointer emits a
|
||||
* _relative_ pointer motion event (i.e. a delta) */
|
||||
struct wlr_pointer_motion_event *event = data;
|
||||
/* The cursor doesn't move unless we tell it to. The cursor automatically
|
||||
* handles constraining the motion to the output layout, as well as any
|
||||
* special configuration applied for the specific input device which
|
||||
* generated the event. You can pass NULL for the device if you want to move
|
||||
* the cursor around without any input. */
|
||||
/* The cursor doesn't move unless we tell it to. The cursor
|
||||
* automatically handles constraining the motion to the output layout,
|
||||
* as well as any special configuration applied for the specific input
|
||||
* device which generated the event. You can pass NULL for the device if
|
||||
* you want to move the cursor around without any input. */
|
||||
|
||||
if (check_trackpad_disabled(event->pointer)) {
|
||||
return;
|
||||
|
|
@ -3764,8 +3830,8 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) {
|
|||
Monitor *m = wlr_output->data;
|
||||
struct wlr_output_state state;
|
||||
|
||||
/* Ensure displays previously disabled by wlr-output-power-management-v1
|
||||
* are properly handled*/
|
||||
/* Ensure displays previously disabled by
|
||||
* wlr-output-power-management-v1 are properly handled*/
|
||||
m->asleep = 0;
|
||||
|
||||
wlr_output_state_init(&state);
|
||||
|
|
@ -4030,13 +4096,13 @@ run(char *startup_cmd) {
|
|||
die("startup: display_add_socket_auto");
|
||||
setenv("WAYLAND_DISPLAY", socket, 1);
|
||||
|
||||
/* Start the backend. This will enumerate outputs and inputs, become the DRM
|
||||
* master, etc */
|
||||
/* Start the backend. This will enumerate outputs and inputs, become the
|
||||
* DRM master, etc */
|
||||
if (!wlr_backend_start(backend))
|
||||
die("startup: backend_start");
|
||||
|
||||
/* Now that the socket exists and the backend is started, run the startup
|
||||
* command */
|
||||
/* Now that the socket exists and the backend is started, run the
|
||||
* startup command */
|
||||
if (!startup_cmd)
|
||||
startup_cmd = get_autostart_path(autostart_temp_path,
|
||||
sizeof(autostart_temp_path));
|
||||
|
|
@ -4066,8 +4132,8 @@ run(char *startup_cmd) {
|
|||
|
||||
printstatus();
|
||||
|
||||
/* At this point the outputs are initialized, choose initial selmon based on
|
||||
* cursor position, and set default cursor image */
|
||||
/* At this point the outputs are initialized, choose initial selmon
|
||||
* based on cursor position, and set default cursor image */
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
|
||||
/* TODO hack to get cursor to display in its initial location (100, 100)
|
||||
|
|
@ -4090,11 +4156,13 @@ run(char *startup_cmd) {
|
|||
}
|
||||
|
||||
void setcursor(struct wl_listener *listener, void *data) {
|
||||
/* This event is raised by the seat when a client provides a cursor image */
|
||||
/* This event is raised by the seat when a client provides a cursor
|
||||
* image */
|
||||
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
||||
/* If we're "grabbing" the cursor, don't use the client's image, we will
|
||||
* restore it after "grabbing" sending a leave event, followed by a enter
|
||||
* event, which will result in the client requesting set the cursor surface
|
||||
* restore it after "grabbing" sending a leave event, followed by a
|
||||
* enter event, which will result in the client requesting set the
|
||||
* cursor surface
|
||||
*/
|
||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
return;
|
||||
|
|
@ -4499,14 +4567,14 @@ void setup(void) {
|
|||
dpy = wl_display_create();
|
||||
event_loop = wl_display_get_event_loop(dpy);
|
||||
pointer_manager = wlr_relative_pointer_manager_v1_create(dpy);
|
||||
/* The backend is a wlroots feature which abstracts the underlying input and
|
||||
* output hardware. The autocreate option will choose the most suitable
|
||||
* backend based on the current environment, such as opening an X11 window
|
||||
* if an X11 server is running. The NULL argument here optionally allows you
|
||||
* to pass in a custom renderer if wlr_renderer doesn't meet your needs. The
|
||||
* backend uses the renderer, for example, to fall back to software cursors
|
||||
* if the backend does not support hardware cursors (some older GPUs
|
||||
* don't). */
|
||||
/* The backend is a wlroots feature which abstracts the underlying input
|
||||
* and output hardware. The autocreate option will choose the most
|
||||
* suitable backend based on the current environment, such as opening an
|
||||
* X11 window if an X11 server is running. The NULL argument here
|
||||
* optionally allows you to pass in a custom renderer if wlr_renderer
|
||||
* doesn't meet your needs. The backend uses the renderer, for example,
|
||||
* to fall back to software cursors if the backend does not support
|
||||
* hardware cursors (some older GPUs don't). */
|
||||
if (!(backend = wlr_backend_autocreate(event_loop, &session)))
|
||||
die("couldn't create backend");
|
||||
|
||||
|
|
@ -4534,8 +4602,8 @@ void setup(void) {
|
|||
/* Create shm, drm and linux_dmabuf interfaces by ourselves.
|
||||
* The simplest way is call:
|
||||
* wlr_renderer_init_wl_display(drw);
|
||||
* but we need to create manually the linux_dmabuf interface to integrate it
|
||||
* with wlr_scene. */
|
||||
* but we need to create manually the linux_dmabuf interface to
|
||||
* integrate it with wlr_scene. */
|
||||
wlr_renderer_init_wl_shm(drw, dpy);
|
||||
|
||||
if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) {
|
||||
|
|
@ -4553,11 +4621,11 @@ void setup(void) {
|
|||
die("couldn't create allocator");
|
||||
|
||||
/* This creates some hands-off wlroots interfaces. The compositor is
|
||||
* necessary for clients to allocate surfaces and the data device manager
|
||||
* handles the clipboard. Each of these wlroots interfaces has room for you
|
||||
* to dig your fingers in and play with their behavior if you want. Note
|
||||
* that the clients cannot set the selection directly without compositor
|
||||
* approval, see the setsel() function. */
|
||||
* necessary for clients to allocate surfaces and the data device
|
||||
* manager handles the clipboard. Each of these wlroots interfaces has
|
||||
* room for you to dig your fingers in and play with their behavior if
|
||||
* you want. Note that the clients cannot set the selection directly
|
||||
* without compositor approval, see the setsel() function. */
|
||||
compositor = wlr_compositor_create(dpy, 6, drw);
|
||||
wlr_export_dmabuf_manager_v1_create(dpy);
|
||||
wlr_screencopy_manager_v1_create(dpy);
|
||||
|
|
@ -4590,8 +4658,8 @@ void setup(void) {
|
|||
wl_signal_add(&output_layout->events.change, &layout_change);
|
||||
wlr_xdg_output_manager_v1_create(dpy, output_layout);
|
||||
|
||||
/* Configure a listener to be notified when new outputs are available on the
|
||||
* backend. */
|
||||
/* Configure a listener to be notified when new outputs are available on
|
||||
* the backend. */
|
||||
wl_list_init(&mons);
|
||||
wl_signal_add(&backend->events.new_output, &new_output);
|
||||
|
||||
|
|
@ -4648,23 +4716,25 @@ void setup(void) {
|
|||
wlr_cursor_attach_output_layout(cursor, output_layout);
|
||||
|
||||
/* Creates an xcursor manager, another wlroots utility which loads up
|
||||
* Xcursor themes to source cursor images from and makes sure that cursor
|
||||
* images are available at all scale factors on the screen (necessary for
|
||||
* HiDPI support). Scaled cursors will be loaded with each output. */
|
||||
* Xcursor themes to source cursor images from and makes sure that
|
||||
* cursor images are available at all scale factors on the screen
|
||||
* (necessary for HiDPI support). Scaled cursors will be loaded with
|
||||
* each output. */
|
||||
// cursor_mgr = wlr_xcursor_manager_create(cursor_theme, 24);
|
||||
cursor_mgr = wlr_xcursor_manager_create(config.cursor_theme, cursor_size);
|
||||
|
||||
/*
|
||||
* wlr_cursor *only* displays an image on screen. It does not move around
|
||||
* when the pointer moves. However, we can attach input devices to it, and
|
||||
* it will generate aggregate events for all of them. In these events, we
|
||||
* can choose how we want to process them, forwarding them to clients and
|
||||
* moving the cursor around. More detail on this process is described in my
|
||||
* input handling blog post:
|
||||
* wlr_cursor *only* displays an image on screen. It does not move
|
||||
* around when the pointer moves. However, we can attach input devices
|
||||
* to it, and it will generate aggregate events for all of them. In
|
||||
* these events, we can choose how we want to process them, forwarding
|
||||
* them to clients and moving the cursor around. More detail on this
|
||||
* process is described in my input handling blog post:
|
||||
*
|
||||
* https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html
|
||||
*
|
||||
* And more comments are sprinkled throughout the notify functions above.
|
||||
* And more comments are sprinkled throughout the notify functions
|
||||
* above.
|
||||
*/
|
||||
wl_signal_add(&cursor->events.motion, &cursor_motion);
|
||||
wl_signal_add(&cursor->events.motion_absolute, &cursor_motion_absolute);
|
||||
|
|
@ -4682,11 +4752,12 @@ void setup(void) {
|
|||
/*
|
||||
* Configures a seat, which is a single "seat" at which a user sits and
|
||||
* operates the computer. This conceptually includes up to one keyboard,
|
||||
* pointer, touch, and drawing tablet device. We also rig up a listener to
|
||||
* let us know when new input devices are available on the backend.
|
||||
* pointer, touch, and drawing tablet device. We also rig up a listener
|
||||
* to let us know when new input devices are available on the backend.
|
||||
*/
|
||||
wl_list_init(&keyboards);
|
||||
wl_list_init(&pointers);
|
||||
wl_list_init(&switches);
|
||||
wl_signal_add(&backend->events.new_input, &new_input_device);
|
||||
virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
|
||||
wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard,
|
||||
|
|
@ -4972,7 +5043,8 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void unmapnotify(struct wl_listener *listener, void *data) {
|
||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||
/* Called when the surface is unmapped, and should no longer be shown.
|
||||
*/
|
||||
Client *c = wl_container_of(listener, c, unmap);
|
||||
Monitor *m;
|
||||
c->iskilling = 1;
|
||||
|
|
@ -5078,7 +5150,8 @@ void updatemons(struct wl_listener *listener, void *data) {
|
|||
config_head =
|
||||
wlr_output_configuration_head_v1_create(config, m->wlr_output);
|
||||
config_head->state.enabled = 0;
|
||||
/* Remove this output from the layout to avoid cursor enter inside it */
|
||||
/* Remove this output from the layout to avoid cursor enter inside
|
||||
* it */
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
closemon(m);
|
||||
m->m = m->w = (struct wlr_box){0};
|
||||
|
|
@ -5158,7 +5231,8 @@ void updatemons(struct wl_listener *listener, void *data) {
|
|||
resize(c, m->m, 0);
|
||||
|
||||
/* Try to re-set the gamma LUT when updating monitors,
|
||||
* it's only really needed when enabling a disabled output, but meh. */
|
||||
* it's only really needed when enabling a disabled output, but meh.
|
||||
*/
|
||||
m->gamma_lut_changed = 1;
|
||||
|
||||
config_head->state.x = m->m.x;
|
||||
|
|
@ -5185,8 +5259,8 @@ void updatemons(struct wl_listener *listener, void *data) {
|
|||
/* FIXME: figure out why the cursor image is at 0,0 after turning all
|
||||
* the monitors on.
|
||||
* Move the cursor image where it used to be. It does not generate a
|
||||
* wl_pointer.motion event for the clients, it's only the image what it's
|
||||
* at the wrong position after all. */
|
||||
* wl_pointer.motion event for the clients, it's only the image what
|
||||
* it's at the wrong position after all. */
|
||||
wlr_cursor_move(cursor, NULL, 0, 0);
|
||||
|
||||
wlr_output_manager_v1_set_configuration(output_mgr, config);
|
||||
|
|
@ -5483,7 +5557,8 @@ int main(int argc, char *argv[]) {
|
|||
if (optind < argc)
|
||||
goto usage;
|
||||
|
||||
/* Wayland requires XDG_RUNTIME_DIR for creating its communications socket
|
||||
/* Wayland requires XDG_RUNTIME_DIR for creating its communications
|
||||
* socket
|
||||
*/
|
||||
if (!getenv("XDG_RUNTIME_DIR"))
|
||||
die("XDG_RUNTIME_DIR must be set");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue