feat: use keyboard group and support select close animaiton type

This commit is contained in:
DreamMaoMao 2025-03-12 10:53:30 +08:00
parent 8b8437fd3c
commit e1cf7db447
6 changed files with 856 additions and 767 deletions

1062
IM.h

File diff suppressed because it is too large Load diff

View file

@ -41,7 +41,8 @@ See below for more features.
- isfloating: type-num(0 or 1) - isfloating: type-num(0 or 1)
- isfullscreen: type-num(0 or 1) - isfullscreen: type-num(0 or 1)
- scroller_proportion: type-float(0.1-1.0) - scroller_proportion: type-float(0.1-1.0)
- animation_type : type-string(zoom,slide) - animation_type_open : type-string(zoom,slide)
- animation_type_close : type-string(zoom,slide)
- isnoborder : type-num(0 or 1) - isnoborder : type-num(0 or 1)
- monitor : type-num(0-99999) - monitor : type-num(0-99999)
- width : type-num(0-9999) - width : type-num(0-9999)
@ -62,17 +63,15 @@ See below for more features.
- alt-tab switch window like gnome - alt-tab switch window like gnome
- niri like scroller layout - niri like scroller layout
## suggest tools
```
yay -S rofi foot xdg-desktop-portal-wlr swaybg waybar wl-clip-persist cliphist wl-clipboard wlsunset
```
# install # install
## stable - wlroots(0.17) ## stable - wlroots(0.17)
Since 0.18 has some bugs that affect the experience, Since 0.18 has some bugs that affect the experience,
I chose the more stable 0.17.4. I chose the more stable 0.17.4.
- Arch
```
yay -S maomaowm-git
```
- Other
``` ```
yay -S libinput yay -S libinput
git clone -b 0.17.4 https://gitlab.freedesktop.org/wlroots/wlroots.git git clone -b 0.17.4 https://gitlab.freedesktop.org/wlroots/wlroots.git
@ -99,7 +98,18 @@ meson build -Dprefix=/usr
sudo ninja -C build install sudo ninja -C build install
``` ```
## suggest tools
```
yay -S rofi foot xdg-desktop-portal-wlr swaybg waybar wl-clip-persist cliphist wl-clipboard wlsunset
```
# config # config
```
cp /etc/maomao/config.conf ~/.config/maomao/config.conf
touch ~/.config/maomao/autostart.sh
chmod +x ~/.config/maomao/autostart.sh
```
you can use `MAOMAOCONFIG` env to set the config-folder-path and the autostart-folder-patch you can use `MAOMAOCONFIG` env to set the config-folder-path and the autostart-folder-patch
like `MAOMAOCONFIG=/home/xxx/maomao` like `MAOMAOCONFIG=/home/xxx/maomao`
@ -162,7 +172,7 @@ ov_tab_mode=0
### notice ### notice
when you in ov mode, you can use right mouse button to close window, and left mouse button to jump to a window. when you in ov mode, you can use right mouse button to close window, and left mouse button to jump to a window.
# About warbar # About waybar
- you can also use the dwl moudle in waybar to show tags and window title - you can also use the dwl moudle in waybar to show tags and window title
refer to waybar wiki: [dwl-module](https://github.com/Alexays/Waybar/wiki/Module:-Dwl) refer to waybar wiki: [dwl-module](https://github.com/Alexays/Waybar/wiki/Module:-Dwl)

View file

@ -1,12 +1,13 @@
# Animation Configuration # Animation Configuration
animations=1 animations=1
animation_type=slide animation_type_open=zoom
animation_type_close=slide
animation_fade_in=1 animation_fade_in=1
zoom_initial_ratio=0.5 zoom_initial_ratio=0.5
fadein_begin_opacity=0.5 fadein_begin_opacity=0.5
fadeout_begin_opacity=0.8 fadeout_begin_opacity=0.8
animation_duration_move=400 animation_duration_move=500
animation_duration_open=350 animation_duration_open=400
animation_duration_tag=350 animation_duration_tag=350
animation_duration_close=800 animation_duration_close=800
animation_curve_open=0.46,1.0,0.29,1 animation_curve_open=0.46,1.0,0.29,1
@ -94,7 +95,8 @@ tags=id:9,layout_name:tile
# isfloating: type-num(0 or 1) # isfloating: type-num(0 or 1)
# isfullscreen: type-num(0 or 1) # isfullscreen: type-num(0 or 1)
# scroller_proportion: type-float(0.1-1.0) # scroller_proportion: type-float(0.1-1.0)
# animation_type : type-string(zoom,slide) # animation_type_open : type-string(zoom,slide)
# animation_type_close : type-string(zoom,slide)
# isnoborder : type-num(0 or 1) # isnoborder : type-num(0 or 1)
# monitor : type-int(0-99999) # monitor : type-int(0-99999)
# width : type-num(0-9999) # width : type-num(0-9999)
@ -110,7 +112,7 @@ tags=id:9,layout_name:tile
# windowrule=isfloating:1,appid:Rofi # windowrule=isfloating:1,appid:Rofi
# windowrule=isfloating:1,appid:wofi # windowrule=isfloating:1,appid:wofi
# windowrule=isnoborder:1,appid:wofi # windowrule=isnoborder:1,appid:wofi
# windowrule=animation_type:zoom,appid:wofi # windowrule=animation_type_open:zoom,appid:wofi
# open in specific tag # open in specific tag
# windowrule=tags:4,appid:Google-chrome # windowrule=tags:4,appid:Google-chrome

487
maomao.c
View file

@ -15,9 +15,11 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/backend.h> #include <wlr/backend.h>
#include <wlr/backend/libinput.h> #include <wlr/backend/libinput.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/render/allocator.h> #include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_alpha_modifier_v1.h> #include <wlr/types/wlr_alpha_modifier_v1.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_control_v1.h> #include <wlr/types/wlr_data_control_v1.h>
@ -232,7 +234,8 @@ struct Client {
struct wl_listener destroy_decoration; struct wl_listener destroy_decoration;
unsigned int ignore_clear_fullscreen; unsigned int ignore_clear_fullscreen;
const char *animation_type; const char *animation_type_open;
const char *animation_type_close;
int is_in_scratchpad; int is_in_scratchpad;
int is_scratchpad_show; int is_scratchpad_show;
int isglobal; int isglobal;
@ -266,6 +269,19 @@ typedef struct {
const Arg arg; const Arg arg;
} Key; } Key;
typedef struct {
struct wlr_keyboard_group *wlr_group;
int nsyms;
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
uint32_t mods; /* invalid if nsyms == 0 */
struct wl_event_source *key_repeat_source;
struct wl_listener modifiers;
struct wl_listener key;
struct wl_listener destroy;
} KeyboardGroup;
typedef struct { typedef struct {
struct wl_list link; struct wl_list link;
struct wlr_keyboard *wlr_keyboard; struct wlr_keyboard *wlr_keyboard;
@ -357,7 +373,8 @@ typedef struct {
int isfloating; int isfloating;
int isfullscreen; int isfullscreen;
float scroller_proportion; float scroller_proportion;
const char *animation_type; const char *animation_type_open;
const char *animation_type_close;
int isnoborder; int isnoborder;
int monitor; int monitor;
unsigned int width; unsigned int width;
@ -425,6 +442,7 @@ static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data);
static void destroypointerconstraint(struct wl_listener *listener, void *data); static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data); 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 Monitor *dirtomon(enum wlr_direction dir);
static void setcursorshape(struct wl_listener *listener, void *data); static void setcursorshape(struct wl_listener *listener, void *data);
static void dwl_ipc_manager_bind(struct wl_client *client, void *data, static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
@ -589,6 +607,7 @@ static const char broken[] = "broken";
// static const char *cursor_image = "left_ptr"; // static const char *cursor_image = "left_ptr";
static pid_t child_pid = -1; static pid_t child_pid = -1;
static int locked; static int locked;
static uint32_t locked_mods = 0;
static void *exclusive_focus; static void *exclusive_focus;
static struct wl_display *dpy; static struct wl_display *dpy;
static struct wl_event_loop *event_loop; static struct wl_event_loop *event_loop;
@ -633,6 +652,7 @@ static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
static struct wlr_pointer_constraint_v1 *active_constraint; static struct wlr_pointer_constraint_v1 *active_constraint;
static struct wlr_seat *seat; static struct wlr_seat *seat;
static KeyboardGroup *kb_group;
static struct wl_list keyboards; static struct wl_list keyboards;
static unsigned int cursor_mode; static unsigned int cursor_mode;
static Client *grabc; static Client *grabc;
@ -897,8 +917,8 @@ void fadeout_client_animation_next_tick(Client *c) {
apply_opacity_to_rect_nodes(c, &c->scene->node, animation_passed); apply_opacity_to_rect_nodes(c, &c->scene->node, animation_passed);
if ((c->animation_type && strcmp(c->animation_type, "zoom") == 0) || if ((c->animation_type_close && strcmp(c->animation_type_close, "zoom") == 0) ||
(!c->animation_type && strcmp(animation_type, "zoom") == 0)) { (!c->animation_type_close && strcmp(animation_type_close, "zoom") == 0)) {
scale_data.width = width; scale_data.width = width;
scale_data.height = height; scale_data.height = height;
@ -1015,12 +1035,12 @@ void apply_border(Client *c, struct wlr_box clip_box, int offsetx,
if (c->animation.running && c->animation.action != MOVE) { if (c->animation.running && c->animation.action != MOVE) {
if (c->animation.current.x < c->mon->m.x) { if (c->animation.current.x < c->mon->m.x) {
wlr_scene_rect_set_size(c->border[2], 0, 0); wlr_scene_rect_set_size(c->border[2], 0, 0);
} else if (c->animation.current.x + c->geom.width > } else if (c->animation.current.x + c->animation.current.width >
c->mon->m.x + c->mon->m.width) { c->mon->m.x + c->mon->m.width) {
wlr_scene_rect_set_size(c->border[3], 0, 0); wlr_scene_rect_set_size(c->border[3], 0, 0);
} else if (c->animation.current.y < c->mon->m.y) { } else if (c->animation.current.y < c->mon->m.y) {
wlr_scene_rect_set_size(c->border[0], 0, 0); wlr_scene_rect_set_size(c->border[0], 0, 0);
} else if (c->animation.current.y + c->geom.height > } else if (c->animation.current.y + c->animation.current.height >
c->mon->m.y + c->mon->m.height) { c->mon->m.y + c->mon->m.height) {
wlr_scene_rect_set_size(c->border[1], 0, 0); wlr_scene_rect_set_size(c->border[1], 0, 0);
} }
@ -1070,13 +1090,13 @@ void client_apply_clip(Client *c) {
clip_box.y = 0; clip_box.y = 0;
} }
// make tagout tagin animations not visible in other monitors // // make tagout tagin animations not visible in other monitors
if (c->animation.running && c->animation.action != MOVE) { if (c->animation.running && c->animation.action != MOVE) {
if (c->animation.current.x <= c->mon->m.x) { if (c->animation.current.x <= c->mon->m.x) {
offsetx = c->mon->m.x - c->animation.current.x; offsetx = c->mon->m.x - c->animation.current.x;
clip_box.x = clip_box.x + offsetx; clip_box.x = clip_box.x + offsetx;
clip_box.width = clip_box.width - offsetx; clip_box.width = clip_box.width - offsetx;
} else if (c->animation.current.x + c->geom.width >= } else if (c->animation.current.x + c->animation.current.width >=
c->mon->m.x + c->mon->m.width) { c->mon->m.x + c->mon->m.width) {
clip_box.width = clip_box.width - clip_box.width = clip_box.width -
(c->animation.current.x + c->animation.current.width - (c->animation.current.x + c->animation.current.width -
@ -1087,7 +1107,7 @@ void client_apply_clip(Client *c) {
offsety = c->mon->m.y - c->animation.current.y; offsety = c->mon->m.y - c->animation.current.y;
clip_box.y = clip_box.y + offsety; clip_box.y = clip_box.y + offsety;
clip_box.height = clip_box.height - offsety; clip_box.height = clip_box.height - offsety;
} else if (c->animation.current.y + c->geom.height >= } else if (c->animation.current.y + c->animation.current.height >=
c->mon->m.y + c->mon->m.height) { c->mon->m.y + c->mon->m.height) {
clip_box.height = clip_box.height - clip_box.height = clip_box.height -
(c->animation.current.y + c->animation.current.height - (c->animation.current.y + c->animation.current.height -
@ -1504,8 +1524,10 @@ applyrules(Client *c) {
c->isterm = r->isterm > 0 ? r->isterm : c->isterm; c->isterm = r->isterm > 0 ? r->isterm : c->isterm;
c->noswallow = r->noswallow > 0? r->noswallow : c->noswallow; c->noswallow = r->noswallow > 0? r->noswallow : c->noswallow;
c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating; c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating;
c->animation_type = c->animation_type_open =
r->animation_type == NULL ? c->animation_type : r->animation_type; r->animation_type_open == NULL ? c->animation_type_open : r->animation_type_open;
c->animation_type_close =
r->animation_type_close == NULL ? c->animation_type_close : r->animation_type_close;
c->scroller_proportion = r->scroller_proportion > 0 c->scroller_proportion = r->scroller_proportion > 0
? r->scroller_proportion ? r->scroller_proportion
: scroller_default_proportion; : scroller_default_proportion;
@ -2133,6 +2155,7 @@ cleanup(void) {
waitpid(child_pid, NULL, 0); waitpid(child_pid, NULL, 0);
} }
destroykeyboardgroup(&kb_group->destroy, NULL);
wlr_backend_destroy(backend); wlr_backend_destroy(backend);
wlr_scene_node_destroy(&scene->tree.node); wlr_scene_node_destroy(&scene->tree.node);
wlr_renderer_destroy(drw); wlr_renderer_destroy(drw);
@ -2381,50 +2404,72 @@ void createidleinhibitor(struct wl_listener *listener, void *data) {
checkidleinhibitor(NULL); checkidleinhibitor(NULL);
} }
void // 17 void
createkeyboard(struct wlr_keyboard *keyboard) { createkeyboard(struct wlr_keyboard *keyboard)
struct xkb_context *context; {
struct xkb_keymap *keymap;
Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb));
kb->wlr_keyboard = keyboard;
/* Prepare an XKB keymap and assign it to the keyboard. */
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
keymap = xkb_keymap_new_from_names(context, &xkb_rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
wlr_keyboard_set_keymap(keyboard, keymap); /* Set the keymap to match the group keymap */
xkb_keymap_unref(keymap); wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
xkb_context_unref(context);
wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
if (numlockon == 1) { wlr_keyboard_notify_modifiers(keyboard, 0, 0, locked_mods, 0);
uint32_t leds = 0;
xkb_mod_mask_t locked_mods = 0;
leds = leds | WLR_LED_NUM_LOCK;
// 获取numlock所在的位置
xkb_mod_index_t mod_index = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_NUM);
if (mod_index != XKB_MOD_INVALID) {
locked_mods |= (uint32_t)1
<< mod_index; // 将该位置设置为1,默认为0表示锁住小键盘
}
// 设置numlock为on
xkb_state_update_mask(keyboard->xkb_state, 0, 0, locked_mods, 0, 0, 0);
wlr_keyboard_led_update(keyboard, leds); // 将表示numlockon的灯打开
}
/* Here we set up listeners for keyboard events. */ /* Add the new keyboard to the group */
LISTEN(&keyboard->events.modifiers, &kb->modifiers, keypressmod); wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard);
LISTEN(&keyboard->events.key, &kb->key, keypress); }
LISTEN(&keyboard->base.events.destroy, &kb->destroy, cleanupkeyboard);
wlr_seat_set_keyboard(seat, keyboard);
kb->key_repeat_source = KeyboardGroup *
wl_event_loop_add_timer(wl_display_get_event_loop(dpy), keyrepeat, kb); createkeyboardgroup(void)
{
KeyboardGroup *group = ecalloc(1, sizeof(*group));
struct xkb_context *context;
struct xkb_keymap *keymap;
/* And add the keyboard to our list of keyboards */ group->wlr_group = wlr_keyboard_group_create();
wl_list_insert(&keyboards, &kb->link); group->wlr_group->data = group;
/* Prepare an XKB keymap and assign it to the keyboard group. */
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
XKB_KEYMAP_COMPILE_NO_FLAGS)))
die("failed to compile keymap");
wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap);
if (numlockon) {
xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
if (mod_index != XKB_MOD_INVALID)
locked_mods |= (uint32_t)1 << mod_index;
}
if (capslock) {
xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
if (mod_index != XKB_MOD_INVALID)
locked_mods |= (uint32_t)1 << mod_index;
}
if (locked_mods)
wlr_keyboard_notify_modifiers(&group->wlr_group->keyboard, 0, 0, locked_mods, 0);
xkb_keymap_unref(keymap);
xkb_context_unref(context);
wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay);
/* Set up listeners for keyboard events */
LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress);
LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod);
group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group);
/* A seat can only have one keyboard, but this is a limitation of the
* Wayland protocol - not wlroots. We assign all connected keyboards to the
* same wlr_keyboard_group, which provides a single wlr_keyboard interface for
* all of them. Set this combined wlr_keyboard as the seat keyboard.
*/
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
return group;
} }
void createlayersurface(struct wl_listener *listener, void *data) { void createlayersurface(struct wl_listener *listener, void *data) {
@ -2839,6 +2884,18 @@ void destroysessionlock(struct wl_listener *listener, void *data) {
destroylock(lock, 0); destroylock(lock, 0);
} }
void
destroykeyboardgroup(struct wl_listener *listener, void *data)
{
KeyboardGroup *group = wl_container_of(listener, group, destroy);
wl_event_source_remove(group->key_repeat_source);
wl_list_remove(&group->key.link);
wl_list_remove(&group->modifiers.link);
wl_list_remove(&group->destroy.link);
wlr_keyboard_group_destroy(group->wlr_group);
free(group);
}
Monitor *dirtomon(enum wlr_direction dir) { Monitor *dirtomon(enum wlr_direction dir) {
struct wlr_output *next; struct wlr_output *next;
if (!wlr_output_layout_get(output_layout, selmon->wlr_output)) if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
@ -3278,49 +3335,51 @@ void incovgaps(const Arg *arg) {
setgaps(selmon->gappoh, selmon->gappov + arg->i, selmon->gappih, setgaps(selmon->gappoh, selmon->gappov + arg->i, selmon->gappih,
selmon->gappiv); selmon->gappiv);
} }
void
inputdevice(struct wl_listener *listener, void *data)
{
/* This event is raised by the backend when a new input device becomes
* available. */
struct wlr_input_device *device = data;
uint32_t caps;
void // 17 switch (device->type) {
inputdevice(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_KEYBOARD:
/* This event is raised by the backend when a new input device becomes createkeyboard(wlr_keyboard_from_input_device(device));
* available. */ break;
struct wlr_input_device *device = data; case WLR_INPUT_DEVICE_POINTER:
uint32_t caps; createpointer(wlr_pointer_from_input_device(device));
break;
default:
/* TODO handle other input device types */
break;
}
switch (device->type) { /* We need to let the wlr_seat know what our capabilities are, which is
case WLR_INPUT_DEVICE_KEYBOARD: * communiciated to the client. In dwl we always have a cursor, even if
createkeyboard(wlr_keyboard_from_input_device(device)); * there are no pointer devices, so we always include that capability. */
break; /* TODO do we actually require a cursor? */
case WLR_INPUT_DEVICE_POINTER: caps = WL_SEAT_CAPABILITY_POINTER;
createpointer(wlr_pointer_from_input_device(device)); if (!wl_list_empty(&kb_group->wlr_group->devices))
break; caps |= WL_SEAT_CAPABILITY_KEYBOARD;
default: wlr_seat_set_capabilities(seat, caps);
/* TODO handle other input device types */
break;
}
/* 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. */
/* TODO do we actually require a cursor? */
caps = WL_SEAT_CAPABILITY_POINTER;
if (!wl_list_empty(&keyboards))
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
wlr_seat_set_capabilities(seat, caps);
} }
int keyrepeat(void *data) { int
Keyboard *kb = data; keyrepeat(void *data)
int i; {
if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0) KeyboardGroup *group = data;
return 0; int i;
if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)
return 0;
wl_event_source_timer_update(kb->key_repeat_source, wl_event_source_timer_update(group->key_repeat_source,
1000 / kb->wlr_keyboard->repeat_info.rate); 1000 / group->wlr_group->keyboard.repeat_info.rate);
for (i = 0; i < kb->nsyms; i++) for (i = 0; i < group->nsyms; i++)
keybinding(kb->mods, kb->keysyms[i]); keybinding(group->mods, group->keysyms[i]);
return 0; return 0;
} }
int // 17 int // 17
@ -3345,31 +3404,32 @@ keybinding(uint32_t mods, xkb_keysym_t sym) {
return handled; return handled;
} }
void // 17 void
keypress(struct wl_listener *listener, void *data) { keypress(struct wl_listener *listener, void *data)
int i; {
/* This event is raised when a key is pressed or released. */ int i;
Keyboard *kb = wl_container_of(listener, kb, key); /* This event is raised when a key is pressed or released. */
struct wlr_keyboard_key_event *event = data; KeyboardGroup *group = wl_container_of(listener, group, key);
struct wlr_keyboard_key_event *event = data;
/* Translate libinput keycode -> xkbcommon */ /* Translate libinput keycode -> xkbcommon */
uint32_t keycode = event->keycode + 8; uint32_t keycode = event->keycode + 8;
/* Get a list of keysyms based on the keymap for this keyboard */ /* Get a list of keysyms based on the keymap for this keyboard */
const xkb_keysym_t *syms; const xkb_keysym_t *syms;
int nsyms = int nsyms = xkb_state_key_get_syms(
xkb_state_key_get_syms(kb->wlr_keyboard->xkb_state, keycode, &syms); group->wlr_group->keyboard.xkb_state, keycode, &syms);
int handled = 0; int handled = 0;
uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard); uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
// ov tab mode detect moe key release // ov tab mode detect moe key release
if (ov_tab_mode && !locked && if (ov_tab_mode && !locked &&
event->state == WL_KEYBOARD_KEY_STATE_RELEASED && event->state == WL_KEYBOARD_KEY_STATE_RELEASED &&
(keycode == 133 || keycode == 37 || keycode == 64 || keycode == 50 || (keycode == 133 || keycode == 37 || keycode == 64 || keycode == 50 ||
keycode == 134 || keycode == 105 || keycode == 108 || keycode == 62) && keycode == 134 || keycode == 105 || keycode == 108 || keycode == 62) &&
selmon->sel) { selmon->sel) {
if (selmon->isoverview && selmon->sel) { if (selmon->isoverview && selmon->sel) {
toggleoverview(&(Arg){.i = -1}); toggleoverview(&(Arg){.i = -1});
} }
@ -3384,68 +3444,66 @@ keypress(struct wl_listener *listener, void *data) {
} }
#endif #endif
/* On _press_ if there is no active screen locker,
* attempt to process a compositor keybinding. */
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
for (i = 0; i < nsyms; i++)
handled = keybinding(mods, syms[i]) || handled;
if (handled && kb->wlr_keyboard->repeat_info.delay > 0) { /* On _press_ if there is no active screen locker,
kb->mods = mods; * attempt to process a compositor keybinding. */
kb->keysyms = syms; if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
kb->nsyms = nsyms; for (i = 0; i < nsyms; i++)
wl_event_source_timer_update(kb->key_repeat_source, handled = keybinding(mods, syms[i]) || handled;
kb->wlr_keyboard->repeat_info.delay); }
} else {
kb->nsyms = 0;
wl_event_source_timer_update(kb->key_repeat_source, 0);
}
if (handled) if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
return; group->mods = mods;
group->keysyms = syms;
group->nsyms = nsyms;
wl_event_source_timer_update(group->key_repeat_source,
group->wlr_group->keyboard.repeat_info.delay);
} else {
group->nsyms = 0;
wl_event_source_timer_update(group->key_repeat_source, 0);
}
if (handled)
return;
#ifdef IM #ifdef IM
/* if there is a keyboard grab, we send the key there */ /* if there is a keyboard grab, we send the key there */
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(kb); struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(group);
if (kb_grab) { if (kb_grab) {
wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, kb->wlr_keyboard); wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab,&(group->wlr_group->keyboard));
wlr_input_method_keyboard_grab_v2_send_key(kb_grab, event->time_msec, wlr_input_method_keyboard_grab_v2_send_key(kb_grab,event->time_msec, event->keycode, event->state);
event->keycode, event->state); wlr_log(WLR_DEBUG, "keypress send to IM:%u mods %u state %u",event->keycode, mods,event->state);
wlr_log(WLR_DEBUG, "keypress send to IM:%u mods %u state %u", return;
event->keycode, mods, event->state); }
return;
}
#endif #endif
/* Pass unhandled keycodes along to the client. */ wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
wlr_seat_set_keyboard(seat, kb->wlr_keyboard); /* Pass unhandled keycodes along to the client. */
wlr_seat_keyboard_notify_key(seat, event->time_msec, event->keycode, wlr_seat_keyboard_notify_key(seat, event->time_msec,
event->state); event->keycode, event->state);
} }
void // 17
keypressmod(struct wl_listener *listener, void *data) { void
/* This event is raised when a modifier key, such as shift or alt, is keypressmod(struct wl_listener *listener, void *data)
* pressed. We simply communicate this to the client. */ {
Keyboard *kb = wl_container_of(listener, kb, modifiers); /* This event is raised when a modifier key, such as shift or alt, is
* pressed. We simply communicate this to the client. */
KeyboardGroup *group = wl_container_of(listener, group, modifiers);
#ifdef IM #ifdef IM
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(kb); struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(group);
if (kb_grab) { if (kb_grab) {
wlr_input_method_keyboard_grab_v2_send_modifiers( wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab,
kb_grab, &kb->wlr_keyboard->modifiers); &group->wlr_group->keyboard.modifiers);
wlr_log(WLR_DEBUG, "keypressmod send to IM"); wlr_log(WLR_DEBUG, "keypressmod send to IM");
return; return;
} }
#endif #endif
/* wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
* A seat can only have one keyboard, but this is a limitation of the /* Send modifiers to the client. */
* Wayland protocol - not wlroots. We assign all connected keyboards to the wlr_seat_keyboard_notify_modifiers(seat,
* same seat. You can swap out the underlying wlr_keyboard like this and &group->wlr_group->keyboard.modifiers);
* wlr_seat handles this transparently.
*/
wlr_seat_set_keyboard(seat, kb->wlr_keyboard);
/* Send modifiers to the client. */
wlr_seat_keyboard_notify_modifiers(seat, &kb->wlr_keyboard->modifiers);
} }
static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly,
@ -3981,38 +4039,32 @@ void outputmgrtest(struct wl_listener *listener, void *data) {
outputmgrapplyortest(config, 1); outputmgrapplyortest(config, 1);
} }
void // 17 void
pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
uint32_t time) { uint32_t time)
struct timespec now; {
int internal_call = !time; struct timespec now;
if (surface != seat->pointer_state.focused_surface && sloppyfocus && time && if (surface != seat->pointer_state.focused_surface &&
c && !client_is_unmanaged(c)) sloppyfocus && time && c && !client_is_unmanaged(c))
focusclient(c, 0); focusclient(c, 0);
/* If surface is NULL, try use the focused client surface to set pointer foucs /* If surface is NULL, clear pointer focus */
*/ if (!surface) {
if (time == 0 && !surface && selmon && selmon->sel) { wlr_seat_pointer_notify_clear_focus(seat);
surface = client_surface(selmon->sel); return;
} }
/* If surface is still NULL, clear pointer focus */ if (!time) {
if (!surface) { clock_gettime(CLOCK_MONOTONIC, &now);
wlr_seat_pointer_notify_clear_focus(seat); time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
return; }
}
if (internal_call) { /* Let the client know that the mouse cursor has entered one
clock_gettime(CLOCK_MONOTONIC, &now); * of its surfaces, and make keyboard focus follow if desired.
time = now.tv_sec * 1000 + now.tv_nsec / 1000000; * wlroots makes this a no-op if surface is already focused */
} wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
/* Let the client know that the mouse cursor has entered one
* of its surfaces, and make keyboard focus follow if desired.
* wlroots makes this a no-op if surface is already focused */
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
} }
void // 17 void // 17
@ -4254,8 +4306,8 @@ void set_open_animaiton(Client *c, struct wlr_box geo) {
int vertical, vertical_value; int vertical, vertical_value;
int special_direction; int special_direction;
int center_x, center_y; int center_x, center_y;
if (strcmp(animation_type, "zoom") == 0 || if (strcmp(animation_type_open, "zoom") == 0 ||
(c->animation_type && strcmp(c->animation_type, "zoom") == 0)) { (c->animation_type_open && strcmp(c->animation_type_open, "zoom") == 0)) {
c->animainit_geom.width = geo.width * zoom_initial_ratio; c->animainit_geom.width = geo.width * zoom_initial_ratio;
c->animainit_geom.height = geo.height * zoom_initial_ratio; c->animainit_geom.height = geo.height * zoom_initial_ratio;
c->animainit_geom.x = geo.x + (geo.width - c->animainit_geom.width) / 2; c->animainit_geom.x = geo.x + (geo.width - c->animainit_geom.width) / 2;
@ -4746,24 +4798,26 @@ void setmon(Client *c, Monitor *m, uint32_t newtags) {
focusclient(focustop(selmon), 1); focusclient(focustop(selmon), 1);
} }
void // 17 void
setpsel(struct wl_listener *listener, void *data) { setpsel(struct wl_listener *listener, void *data)
/* This event is raised by the seat when a client wants to set the selection, {
* usually when the user copies something. wlroots allows compositors to /* This event is raised by the seat when a client wants to set the selection,
* ignore such requests if they so choose, but in dwl we always honor * usually when the user copies something. wlroots allows compositors to
*/ * ignore such requests if they so choose, but in dwl we always honor
struct wlr_seat_request_set_primary_selection_event *event = data; */
wlr_seat_set_primary_selection(seat, event->source, event->serial); struct wlr_seat_request_set_primary_selection_event *event = data;
wlr_seat_set_primary_selection(seat, event->source, event->serial);
} }
void // 17 void
setsel(struct wl_listener *listener, void *data) { setsel(struct wl_listener *listener, void *data)
/* This event is raised by the seat when a client wants to set the selection, {
* usually when the user copies something. wlroots allows compositors to /* This event is raised by the seat when a client wants to set the selection,
* ignore such requests if they so choose, but in dwl we always honor * usually when the user copies something. wlroots allows compositors to
*/ * ignore such requests if they so choose, but in dwl we always honor
struct wlr_seat_request_set_selection_event *event = data; */
wlr_seat_set_selection(seat, event->source, event->serial); struct wlr_seat_request_set_selection_event *event = data;
wlr_seat_set_selection(seat, event->source, event->serial);
} }
// 获取tags中最坐标的tag的tagmask // 获取tags中最坐标的tag的tagmask
@ -5107,6 +5161,9 @@ void setup(void) {
wl_signal_add(&seat->events.request_start_drag, &request_start_drag); wl_signal_add(&seat->events.request_start_drag, &request_start_drag);
wl_signal_add(&seat->events.start_drag, &start_drag); wl_signal_add(&seat->events.start_drag, &start_drag);
kb_group = createkeyboardgroup();
wl_list_init(&kb_group->destroy.link);
output_mgr = wlr_output_manager_v1_create(dpy); output_mgr = wlr_output_manager_v1_create(dpy);
wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.apply, &output_mgr_apply);
wl_signal_add(&output_mgr->events.test, &output_mgr_test); wl_signal_add(&output_mgr->events.test, &output_mgr_test);
@ -5922,7 +5979,7 @@ void init_fadeout_client(Client *c) {
fadeout_cient->geom = fadeout_cient->current = fadeout_cient->animainit_geom = fadeout_cient->geom = fadeout_cient->current = fadeout_cient->animainit_geom =
fadeout_cient->animation.initial = c->animation.current; fadeout_cient->animation.initial = c->animation.current;
fadeout_cient->mon = c->mon; fadeout_cient->mon = c->mon;
fadeout_cient->animation_type = c->animation_type; fadeout_cient->animation_type_close = c->animation_type_close;
fadeout_cient->animation.action = CLOSE; fadeout_cient->animation.action = CLOSE;
fadeout_cient->bw = c->bw; fadeout_cient->bw = c->bw;
@ -5931,8 +5988,8 @@ void init_fadeout_client(Client *c) {
fadeout_cient->animation.initial.x = 0; fadeout_cient->animation.initial.x = 0;
fadeout_cient->animation.initial.y = 0; fadeout_cient->animation.initial.y = 0;
if ((c->animation_type && strcmp(c->animation_type, "slide") == 0) || if ((c->animation_type_close && strcmp(c->animation_type_close, "slide") == 0) ||
(!c->animation_type && strcmp(animation_type, "slide") == 0)) { (!c->animation_type_close && strcmp(animation_type_close, "slide") == 0)) {
fadeout_cient->current.y = fadeout_cient->current.y =
c->geom.y + c->geom.height / 2 > c->mon->m.y + c->mon->m.height / 2 c->geom.y + c->geom.height / 2 > c->mon->m.y + c->mon->m.height / 2
? c->mon->m.height - ? c->mon->m.height -
@ -5941,11 +5998,11 @@ void init_fadeout_client(Client *c) {
fadeout_cient->current.x = 0; // x无偏差垂直划出 fadeout_cient->current.x = 0; // x无偏差垂直划出
} else { } else {
fadeout_cient->current.y = fadeout_cient->current.y =
(c->geom.height - c->geom.height * zoom_initial_ratio) / 2; (fadeout_cient->geom.height - fadeout_cient->geom.height * zoom_initial_ratio) / 2;
fadeout_cient->current.x = fadeout_cient->current.x =
(c->geom.width - c->geom.width * zoom_initial_ratio) / 2; (fadeout_cient->geom.width - fadeout_cient->geom.width * zoom_initial_ratio) / 2;
fadeout_cient->current.width = c->geom.width * zoom_initial_ratio; fadeout_cient->current.width = fadeout_cient->geom.width * zoom_initial_ratio;
fadeout_cient->current.height = c->geom.height * zoom_initial_ratio; fadeout_cient->current.height = fadeout_cient->geom.height * zoom_initial_ratio;
} }
fadeout_cient->animation.passed_frames = 0; fadeout_cient->animation.passed_frames = 0;
@ -5956,6 +6013,7 @@ void init_fadeout_client(Client *c) {
wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link); wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link);
} }
void unmapnotify(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); Client *c = wl_container_of(listener, c, unmap);
@ -6375,9 +6433,18 @@ void tagtoright(const Arg *arg) {
} }
} }
void virtualkeyboard(struct wl_listener *listener, void *data) { void
struct wlr_virtual_keyboard_v1 *keyboard = data; virtualkeyboard(struct wl_listener *listener, void *data)
createkeyboard(&keyboard->keyboard); {
struct wlr_virtual_keyboard_v1 *kb = data;
/* virtual keyboards shouldn't share keyboard group */
KeyboardGroup *group = createkeyboardgroup();
/* Set the keymap to match the group keymap */
wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap);
LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup);
/* Add the new keyboard to the group */
wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard);
} }
void warp_cursor(const Client *c) { void warp_cursor(const Client *c) {

View file

@ -14,7 +14,8 @@ typedef struct {
int isfloating; int isfloating;
int isfullscreen; int isfullscreen;
float scroller_proportion; float scroller_proportion;
const char *animation_type; const char *animation_type_open;
const char *animation_type_close;
int isnoborder; int isnoborder;
int monitor; int monitor;
int width; int width;
@ -71,7 +72,8 @@ typedef struct {
typedef struct { typedef struct {
int animations; int animations;
char animation_type[10]; char animation_type_open[10];
char animation_type_close[10];
char animation_fade_in; char animation_fade_in;
float zoom_initial_ratio; float zoom_initial_ratio;
float fadein_begin_opacity; float fadein_begin_opacity;
@ -481,8 +483,10 @@ void parse_config_line(Config *config, const char *line) {
if (strcmp(key, "animations") == 0) { if (strcmp(key, "animations") == 0) {
config->animations = atoi(value); config->animations = atoi(value);
} else if (strcmp(key, "animation_type") == 0) { } else if (strcmp(key, "animation_type_open") == 0) {
strncpy(config->animation_type, value, sizeof(config->animation_type)); strncpy(config->animation_type_open, value, sizeof(config->animation_type_open));
} else if (strcmp(key, "animation_type_close") == 0) {
strncpy(config->animation_type_close, value, sizeof(config->animation_type_close));
} else if (strcmp(key, "animation_fade_in") == 0) { } else if (strcmp(key, "animation_fade_in") == 0) {
config->animation_fade_in = atoi(value); config->animation_fade_in = atoi(value);
} else if (strcmp(key, "zoom_initial_ratio") == 0) { } else if (strcmp(key, "zoom_initial_ratio") == 0) {
@ -792,7 +796,8 @@ void parse_config_line(Config *config, const char *line) {
rule->monitor = -1; rule->monitor = -1;
rule->width = -1; rule->width = -1;
rule->height = -1; rule->height = -1;
rule->animation_type = NULL; rule->animation_type_open = NULL;
rule->animation_type_close = NULL;
rule->scroller_proportion = -1; rule->scroller_proportion = -1;
rule->id = NULL; rule->id = NULL;
rule->title = NULL; rule->title = NULL;
@ -812,8 +817,10 @@ void parse_config_line(Config *config, const char *line) {
rule->title = strdup(val); rule->title = strdup(val);
} else if (strcmp(key, "appid") == 0) { } else if (strcmp(key, "appid") == 0) {
rule->id = strdup(val); rule->id = strdup(val);
} else if (strcmp(key, "animation_type") == 0) { } else if (strcmp(key, "animation_type_open") == 0) {
rule->animation_type = strdup(val); rule->animation_type_open = strdup(val);
} else if (strcmp(key, "animation_type_close") == 0) {
rule->animation_type_close = strdup(val);
} else if (strcmp(key, "tags") == 0) { } else if (strcmp(key, "tags") == 0) {
rule->tags = 1 << (atoi(val) - 1); rule->tags = 1 << (atoi(val) - 1);
} else if (strcmp(key, "monitor") == 0) { } else if (strcmp(key, "monitor") == 0) {
@ -1029,8 +1036,10 @@ void free_config(void) {
free((void *)rule->id); free((void *)rule->id);
if (rule->title) if (rule->title)
free((void *)rule->title); free((void *)rule->title);
if (rule->animation_type) if (rule->animation_type_open)
free((void *)rule->animation_type); free((void *)rule->animation_type_open);
if (rule->animation_type_close)
free((void *)rule->animation_type_close);
} }
free(config.window_rules); free(config.window_rules);
@ -1076,7 +1085,8 @@ void free_config(void) {
void override_config(void) { void override_config(void) {
animations = config.animations; animations = config.animations;
animation_type = config.animation_type; animation_type_open = config.animation_type_open;
animation_type_close = config.animation_type_close;
animation_fade_in = config.animation_fade_in; animation_fade_in = config.animation_fade_in;
zoom_initial_ratio = config.zoom_initial_ratio; zoom_initial_ratio = config.zoom_initial_ratio;
fadein_begin_opacity = config.fadein_begin_opacity; fadein_begin_opacity = config.fadein_begin_opacity;

View file

@ -5,7 +5,8 @@
((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f} ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f}
/* animaion */ /* animaion */
char *animation_type = "slide"; // 是否启用动画 //slide,zoom char *animation_type_open = "slide"; // 是否启用动画 //slide,zoom
char *animation_type_close = "slide"; // 是否启用动画 //slide,zoom
int animations = 1; // 是否启用动画 int animations = 1; // 是否启用动画
char animation_fade_in = 1; // Enable animation fade in char animation_fade_in = 1; // Enable animation fade in
float zoom_initial_ratio = 0.5; // 动画起始窗口比例 float zoom_initial_ratio = 0.5; // 动画起始窗口比例
@ -30,6 +31,7 @@ unsigned int default_nmaster = 1; // 默认master数量
/* logging */ /* logging */
int log_level = WLR_ERROR; int log_level = WLR_ERROR;
unsigned int numlockon = 1; // 是否打开右边小键盘 unsigned int numlockon = 1; // 是否打开右边小键盘
unsigned int capslock = 0; // 是否打开大写锁定
unsigned int ov_tab_mode = 0; // alt tab切换模式 unsigned int ov_tab_mode = 0; // alt tab切换模式
unsigned int hotarea_size = 10; // 热区大小,10x10 unsigned int hotarea_size = 10; // 热区大小,10x10