feat: support config file and reload config without logout

This commit is contained in:
DreamMaoMao 2025-02-16 23:09:46 +08:00
parent 8d872968c7
commit 16fe8f6194
9 changed files with 1377 additions and 394 deletions

View file

@ -60,8 +60,9 @@ cp wallpaper ~/.config/maomao/ -r
```
# config
> [!NOTE]
> The configuration file is located in `config.h`. This file is generated every time the `meson build` command is executed. If the file already exists, it will not be regenerated. If you encounter compilation issues after updating, please try to remove this file and the `build folder`, then rerun the `meson build` command.
the config file is `~/.config/maomao/config.conf`
the autostart file is `~/.config/maomao/autostart.sh`
# thanks for some refer repo
- https://github.com/dqrk0jeste/owl - for basal window animaition

View file

@ -2,12 +2,14 @@
set +e
systemctl --user unmask xdg-desktop-portal-hyprland
systemctl --user mask xdg-desktop-portal-gnome
dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
/usr/lib/xdg-desktop-portal-hyprland &
wl-clip-persist --clipboard regular &
wl-paste --type text --watch cliphist store &
wlsunset -T 3501 -t 3500 &
swaybg -i ~/.config/maomao/wallpaper/wallpaper.png &
waybar -c ~/.config/maomao/waybar/config -s ~/.config/maomao/waybar/style.css &
echo "Xft.dpi: 140" | xrdb -merge # change x11 dpi

201
config.conf Normal file
View file

@ -0,0 +1,201 @@
# Animation Configuration
animations=1
animation_type=slide
animation_fade_in=1
zoom_initial_ratio=0.5
fadein_begin_opacity=0
animation_duration_move=500
animation_duration_open=400
animation_duration_tag=350
animation_curve=0.46,1.0,0.29,0.99
# Scroller Layout Setting
scroller_structs=20
scroller_default_proportion=0.8
scoller_focus_center=0
scroller_proportion_preset=0.5,0.8,1.0
# Master-Stack Layout Setting
new_is_master=1
default_mfact=0.55
default_nmaster=1
# Overview Setting
hotarea_size=10
enable_hotarea=1
ov_tab_mode=0
overviewgappi=5
overviewgappo=30
# Misc
axis_bind_apply_timeout=100
focus_on_activate=1
numlockon=1
bypass_surface_visibility=0
sloppyfocus=1
warpcursor=1
# Appearance
smartgaps=0
gappih=5
gappiv=5
gappoh=10
gappov=10
borderpx=4
rootcolor=0x323232ff
bordercolor=0x444444ff
focuscolor=0xad741fff
maxmizescreencolor=0x89aa61ff
urgentcolor=0xad401fff
scratchpadcolor=0x516c93ff
globalcolor=0xb153a7ff
# Window Rules
# appid: type-string if match it or title, the rule match
# title: type-string if match it or appid, the rule match
# tags: type-num(1-9)
# isfloating: type-num(0 or 1)
# isfullscreen: type-num(0 or 1)
# scroller_proportion: type-float(0.1-1.0)
# animation_type : type-string(zoom,slide)
# isnoborder : type-num(0 or 1)
# monitor : type-int(0-99999)
# width : type-num(0-9999)
# height : type-num(0-9999)
# example
# windowrule=isfloating:1,appid:yesplaymusic
# windowrule=width:1500,appid:yesplaymusic
# windowrule=height:900,appid:yesplaymusic
# windowrule=isfloating:1,title:qxdrag
# windowrule=isfloating:1,appid:Rofi
# windowrule=isfloating:1,appid:wofi
# windowrule=isnoborder:1,appid:wofi
# windowrule=animation_type:zoom,appid:wofi
# open in specific tag
# windowrule=tags:4,appid:Google-chrome
# windowrule=tags:3,appid:QQ
# windowrule=tags:5,appid:yesplaymusic
# windowrule=tags:2,appid:mpv
# windowrule=tags:6,appid:obs
# Monitor Rules
# monitorrule=eDP-1,0.55,1,tile,0,1,0,0
# monitorrule=HDMI-A-1,0.55,1,tile,0,1,1920,0
# Key Bindings
# The mod key is not case sensitive,
# but the second key is case sensitive,
# if you use shift as one of the mod keys,
# remember to use uppercase keys
# reload config
bind=SUPER,r,reload_config
# menu and terminal
bind=Alt,space,spawn,wofi --normal-window -c ~/.config/maomao/wofi/config -s ~/.config/maomao/wofi/style.css
bind=Alt,Return,spawn,foot
# exit
bind=SUPER,m,quit
bind=ALT,q,killclient,
# switch window focus
bind=SUPER,Tab,focusstack,next
bind=ALT,Left,focusdir,left
bind=ALT,Right,focusdir,right
bind=ALT,Up,focusdir,up
bind=ALT,Down,focusdir,down
# swap window
bind=SUPER+SHIFT,Up,exchange_client,up
bind=SUPER+SHIFT,Down,exchange_client,down
bind=SUPER+SHIFT,Left,exchange_client,left
bind=SUPER+SHIFT,Right,exchange_client,right
# switch window status
bind=SUPER,g,toggleglobal,
bind=ALT,Tab,toggleoverview,
bind=ALT,backslash,togglefloating,
bind=ALT,a,togglemaxmizescreen,
bind=ALT,f,togglefullscreen,
bind=SUPER,i,minized,
bind=SUPER+SHIFT,I,restore_minized
bind=ALT,z,toggle_scratchpad
# scroller layout
bind=ALT,e,set_proportion,1.0
bind=ALT,x,switch_proportion_preset,
# tile layout
bind=SUPER,e,incnmaster,1
bind=SUPER,t,incnmaster,-1
bind=ALT+CTRL,Left,setmfact,-0.01
bind=ALT+CTRL,Right,setmfact,+0.01
bind=ALT,s,zoom,
# switch layout
bind=CTRL+SUPER,i,setlayout,tile
bind=CTRL+SUPER,l,setlayout,scroller
bind=SUPER,n,switch_layout
# tag switch
bind=SUPER,Left,viewtoleft,
bind=CTRL,Left,viewtoleft_have_client,
bind=SUPER,Right,viewtoright,
bind=CTRL,Right,viewtoright_have_client,
bind=CTRL+SUPER,Left,tagtoleft,
bind=CTRL+SUPER,Right,tagtoright,
bind=Ctrl,KP_1,view,1
bind=Ctrl,KP_2,view,2
bind=Ctrl,KP_3,view,3
bind=Ctrl,KP_4,view,4
bind=Ctrl,KP_5,view,5
bind=Ctrl,KP_6,view,6
bind=Ctrl,KP_7,view,7
bind=Ctrl,KP_8,view,8
bind=Ctrl,KP_9,view,9
bind=Alt,KP_1,tag,1
bind=Alt,KP_2,tag,2
bind=Alt,KP_3,tag,3
bind=Alt,KP_4,tag,4
bind=Alt,KP_5,tag,5
bind=Alt,KP_6,tag,6
bind=Alt,KP_7,tag,7
bind=Alt,KP_8,tag,8
bind=Alt,KP_9,tag,9
# monitor switch
bind=SUPER,bracketleft,focusmon,left
bind=SUPER,bracketright,focusmon,right
bind=SUPER+CTRL,bracketleft,tagmon,left
bind=SUPER+CTRL,bracketright,tagmon,right
# gaps
bind=ALT+SHIFT,X,incgaps,1
bind=ALT+SHIFT,Z,incgaps,-1
bind=ALT+SHIFT,R,togglegaps
#custom app bind example
# bind=SUPER,Return,spawn,google-chrome
# bind=CTRL+ALT,Return,spawn,st -e ~/tool/ter-multiplexer.sh
# Mouse Button Bindings
# NONE mode key only work in ov mode
mousebind=SUPER,btn_left,moveresize,curmove
mousebind=NONE,btn_middle,togglemaxmizescreen,0
mousebind=SUPER,btn_right,moveresize,curresize
mousebind=NONE,btn_left,toggleoverview,-1
mousebind=NONE,btn_right,killclient,0
# Axis Bindings
axisbind=SUPER,UP,viewtoleft_have_client
axisbind=SUPER,DOWN,viewtoright_have_client

View file

@ -1,278 +0,0 @@
/* speedie's dwl config */
#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \
((hex >> 16) & 0xFF) / 255.0f, \
((hex >> 8) & 0xFF) / 255.0f, \
(hex & 0xFF) / 255.0f }
/* animation */
static const bool animations = true; // Enable animations
static const char *animation_type = "slide"; //slide or zoom
static const char animation_fade_in = 0; // Enable animation fade in
static const float zoom_initial_ratio = 0.5; // Initial window ratio for animations
static const float fadein_begin_opacity = 0; // Begin opacity for animations fasdein
static const uint32_t animation_duration_move = 500; // Animation move speed
static const uint32_t animation_duration_open = 400; // Animation open speed
static const uint32_t animation_duration_tag = 400; // Animation tag speed
// static const double animation_curve[4] = {0.05,0.9,0.1,1.05}; // Animation curve
static const double animation_curve[4] = {0.46,1.0,0.29,0.99}; // Animation curve
/* scroller layout setting*/
static const int scroller_structs = 20;
static const float scroller_default_proportion = 0.8;
static bool scoller_foucs_center = false;
static const float scroller_proportion_preset[] = {0.5,0.8,1.0};
/* master-stack layout setting*/
static const unsigned int new_is_master = 1; // New windows are inserted at the head
static const unsigned int default_mfact = 0.55f; // Master mfact
static const unsigned int default_nmaster = 1; // Master number
/* overview setting*/
static const unsigned int hotarea_size = 10; // Hot area size, 10x10
static const unsigned int enable_hotarea = 1; // Enable mouse hot area
static const unsigned int ov_tab_mode = 1; // Enable switch window like gnome alt+tab
static const int overviewgappi = 5; /* Gap between windows and edges in overview mode */
static const int overviewgappo = 30; /* Gap between windows in overview mode */
/* misc */
static const unsigned int axis_bind_apply_timeout = 100; // Timeout for wheel binding actions
static const unsigned int focus_on_activate = 1; // Automatically focus on window activation request
static const unsigned int numlockon = 1; // Enable numlock
static int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if the surface isn't visible */
static int sloppyfocus = 1; /* Focus follows mouse */
static int warpcursor = 1; /* Warp cursor to focused client */
/* logging */
static int log_level = WLR_ERROR;
/* appearance */
static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
static unsigned int gappih = 5; /* Horizontal inner gap between windows */
static unsigned int gappiv = 5; /* Vertical inner gap between windows */
static unsigned int gappoh = 10; /* Horizontal outer gap between windows and screen edge */
static unsigned int gappov = 10; /* Vertical outer gap between windows and screen edge */
static unsigned int borderpx = 5; /* Border pixel of windows */
static const float rootcolor[] = COLOR(0x323232ff);
static const float bordercolor[] = COLOR(0x444444ff);
static const float focuscolor[] = COLOR(0xad741fff);
static const float maxmizescreencolor[] = COLOR(0x89aa61ff);
static const float urgentcolor[] = COLOR(0xad401fff);
static const float scratchpadcolor[] = COLOR(0x516c93ff);
static const float globalcolor[] = COLOR(0xb153a7ff);
// static const char *cursor_theme = "Bibata-Modern-Ice";
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
/* Autostart */
static const char *const autostart[] = {
"/bin/sh",
"-c",
"~/.config/maomao/autostart.sh",
NULL,
NULL,
};
/* tagging
* expand the array to add more tags
*/
static const char *tags[] = {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
};
static const Rule rules[] = {
/* app_id title tags mask isfloating isfullscreen scroller_proportion animation_type isnoborder monitor width height */
/* examples:
{ "Gimp", NULL, 0, 1, -1,800,600 },
*/
{ "Google-chrome", NULL, 1 << 3, 0, 0, 0, NULL, 0,-1, 0,0},
{ "wofi", NULL, 0, 1, 0, 0, "zoom", 1,-1, 0,0},
{ "pot", NULL, 0, 1, 0, 0, "zoom", 1,-1, 0,0},
};
/* layout(s) */
static const Layout overviewlayout = { "󰃇", overview, "ovgrid" };
static const Layout layouts[] = { // At least two layouts, cannot delete less than two
/* symbol arrange function */
{ "󱞬", tile, "tile" }, // master-stack layout
{ "", scroller, "scroller" }, // scroller layout
};
/* monitors */
static const MonitorRule monrules[] = {
/* name mfact nmaster scale layout rotate/reflect x y*/
/* example of a HiDPI laptop monitor:
{ "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL },
*/
/* defaults */
// { "eDP-1", 0.5, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL },
{ "eDP-1", 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0,0},
{ "HDMI-A-1", 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 1920,0},
};
/* keyboard */
static const struct xkb_rule_names xkb_rules = {
/* can specify fields: rules, model, layout, variant, options */
/* example:
.options = "ctrl:nocaps",
*/
.options = NULL,
};
static int repeat_rate = 25;
static int repeat_delay = 600;
/* Trackpad */
static int tap_to_click = 1;
static int tap_and_drag = 1;
static int drag_lock = 1;
static int natural_scrolling = 0;
static int disable_while_typing = 1;
static int left_handed = 0;
static int middle_button_emulation = 0;
/* You can choose between:
LIBINPUT_CONFIG_SCROLL_NO_SCROLL
LIBINPUT_CONFIG_SCROLL_2FG
LIBINPUT_CONFIG_SCROLL_EDGE
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
*/
static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
/* You can choose between:
LIBINPUT_CONFIG_CLICK_METHOD_NONE
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
*/
static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
/* You can choose between:
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE
*/
static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
/* You can choose between:
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
*/
static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
static const double accel_speed = 0.0;
/* You can choose between:
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
*/
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT
#define TAGKEYS(KEY,SKEY,TAG) \
{ WLR_MODIFIER_CTRL, KEY, bind_to_view, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
{ WLR_MODIFIER_ALT, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static const char *termcmd[] = { "foot", NULL };
/* static const char *menucmd[] = { "wofi", NULL }; */
static const Key keys[] = {
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
/* modifier key function argument */
{ MODKEY, XKB_KEY_space, spawn, SHCMD("wofi --normal-window ~/.config/maomao/wofi/config") },
{ MODKEY, XKB_KEY_Return, spawn, {.v = termcmd} },
// add your custom cmd key bind like this
/* { WLR_MODIFIER_LOGO, XKB_KEY_Return, spawn, SHCMD("google-chrome") }, */
{ WLR_MODIFIER_LOGO, XKB_KEY_Tab, focusstack, {.i = +1} },
{ WLR_MODIFIER_ALT, XKB_KEY_Left, focusdir, {.i = LEFT } }, /* alt left | Switch focus window within the current tag */
{ WLR_MODIFIER_ALT, XKB_KEY_Right, focusdir, {.i = RIGHT } }, /* alt right | Switch focus window within the current tag */
{ WLR_MODIFIER_ALT, XKB_KEY_Up, focusdir, {.i = UP } }, /* alt up | Switch focus window within the current tag */
{ WLR_MODIFIER_ALT, XKB_KEY_Down, focusdir, {.i = DOWN } },
{ WLR_MODIFIER_LOGO, XKB_KEY_e, incnmaster, {.i = +1} },
{ WLR_MODIFIER_LOGO, XKB_KEY_t, incnmaster, {.i = -1} },
{ WLR_MODIFIER_ALT|WLR_MODIFIER_CTRL, XKB_KEY_Left, setmfact, {.f = -0.01} },
{ WLR_MODIFIER_ALT|WLR_MODIFIER_CTRL, XKB_KEY_Right, setmfact, {.f = +0.01} },
{ MODKEY, XKB_KEY_s, zoom, {0} },
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_Up, exchange_client, {.i = UP } }, /* super shift up | 2D exchange window (tiling only) */
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_Down, exchange_client, {.i = DOWN } }, /* super shift down | 2D exchange window (tiling only) */
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_Left, exchange_client, {.i = LEFT} }, /* super shift left | 2D exchange window (tiling only) */
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_Right, exchange_client, {.i = RIGHT } }, /* super shift right | 2D exchange window (tiling only) */
{ WLR_MODIFIER_LOGO, XKB_KEY_g, toggleglobal, {0} },
{ MODKEY, XKB_KEY_Tab, toggleoverview, {0} },
{ WLR_MODIFIER_LOGO, XKB_KEY_Left, viewtoleft, {0} },
{ WLR_MODIFIER_CTRL, XKB_KEY_Left, viewtoleft_have_client, {0} },
{ WLR_MODIFIER_LOGO, XKB_KEY_Right, viewtoright, {0} },
{ WLR_MODIFIER_CTRL, XKB_KEY_Right, viewtoright_have_client, {0} },
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_Left, tagtoleft, {0} }, /* ctrl alt left | Move current window to the left tag */
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_Right, tagtoright, {0} },
{ MODKEY, XKB_KEY_q, killclient, {0} },
{ MODKEY, XKB_KEY_e, set_proportion, {.f = 1.0} }, /* set scroller layout window to maxsize */
{ MODKEY, XKB_KEY_w, switch_proportion_preset, {0}}, /* switch scroller layout window to preset size */
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_i, setlayout, {.v = &layouts[0]} },
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_l, setlayout, {.v = &layouts[1]} },
{ WLR_MODIFIER_LOGO, XKB_KEY_n, switch_layout, {0} },
{ WLR_MODIFIER_ALT, XKB_KEY_backslash, togglefloating, {0} },
{ MODKEY, XKB_KEY_a, togglemaxmizescreen, {0} },
{ MODKEY, XKB_KEY_f, togglefullscreen, {0} },
{ WLR_MODIFIER_LOGO, XKB_KEY_i, minized, {0} }, // Minimize, move to scratchpad
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_I, restore_minized, {0} },
{ WLR_MODIFIER_ALT, XKB_KEY_z, toggle_scratchpad, {0} }, // Cycle through scratchpad
{ WLR_MODIFIER_LOGO, XKB_KEY_bracketleft, focusmon, {.i = WLR_DIRECTION_LEFT} }, // super + [
{ WLR_MODIFIER_LOGO, XKB_KEY_bracketright, focusmon, {.i = WLR_DIRECTION_RIGHT} }, // suepr + ]
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_bracketleft, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_bracketright, tagmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_X, incgaps, {.i = +1 } },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Z, incgaps, {.i = -1 } },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, togglegaps, {0} },
TAGKEYS( XKB_KEY_KP_1, XKB_KEY_exclam, 0),
TAGKEYS( XKB_KEY_KP_2, XKB_KEY_at, 1),
TAGKEYS( XKB_KEY_KP_3, XKB_KEY_numbersign, 2),
TAGKEYS( XKB_KEY_KP_4, XKB_KEY_dollar, 3),
TAGKEYS( XKB_KEY_KP_5, XKB_KEY_percent, 4),
TAGKEYS( XKB_KEY_KP_6, XKB_KEY_asciicircum, 5),
TAGKEYS( XKB_KEY_KP_7, XKB_KEY_ampersand, 6),
TAGKEYS( XKB_KEY_KP_8, XKB_KEY_asterisk, 7),
TAGKEYS( XKB_KEY_KP_9, XKB_KEY_parenleft, 8),
//{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} },
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
{ WLR_MODIFIER_LOGO,XKB_KEY_m, quit, {0} },
#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),
};
static const Button buttons[] = {
{ WLR_MODIFIER_LOGO, BTN_LEFT, moveresize, {.ui = CurMove } },
{ 0, BTN_MIDDLE, togglemaxmizescreen, {0} }, // Middle button triggers fake fullscreen
{ WLR_MODIFIER_LOGO, BTN_RIGHT, moveresize, {.ui = CurResize } },
{ WLR_MODIFIER_ALT|WLR_MODIFIER_CTRL, BTN_LEFT, spawn, SHCMD("bash ~/tool/shotTranslate.sh shot")},
{ 0, BTN_LEFT, toggleoverview, {.i = -1 } },
{ 0, BTN_RIGHT, killclient, {0} },
};
static const Axis axes[] = {
{ WLR_MODIFIER_LOGO, AxisUp, viewtoleft_have_client, {0} }, // Middle button + super to switch workspace forward
{ WLR_MODIFIER_LOGO, AxisDown, viewtoright_have_client, {0} }, // Middle button + super to switch workspace backward
};

34
dispatch.h Normal file
View file

@ -0,0 +1,34 @@
void minized(const Arg *arg);
void restore_minized(const Arg *arg);
void toggle_scratchpad(const Arg *arg);
void focusdir(const Arg *arg);
void toggleoverview(const Arg *arg);
void set_proportion(const Arg *arg);
void switch_proportion_preset(const Arg *arg);
void zoom(const Arg *arg);
void tagtoleft(const Arg *arg);
void tagtoright(const Arg *arg);
void viewtoleft(const Arg *arg);
void viewtoright(const Arg *arg);
void viewtoleft_have_client(const Arg *arg);
void viewtoright_have_client(const Arg *arg);
void togglefloating(const Arg *arg);
void togglefullscreen(const Arg *arg);
void togglemaxmizescreen(const Arg *arg);
void togglegaps(const Arg *arg);
void tagmon(const Arg *arg);
void spawn(const Arg *arg);
void setlayout(const Arg *arg);
void switch_layout(const Arg *arg);
void setmfact(const Arg *arg);
void quit(const Arg *arg);
void moveresize(const Arg *arg);
void exchange_client(const Arg *arg);
void killclient(const Arg *arg);
void toggleglobal(const Arg *arg);
void incnmaster(const Arg *arg);
void incgaps(const Arg *arg);
void focusmon(const Arg *arg);
void focusstack(const Arg *arg);
void chvt(const Arg *arg);
void reload_config(const Arg *arg);

372
maomao.c
View file

@ -3,6 +3,7 @@
*/
#include <getopt.h>
#include <libinput.h>
#include <wordexp.h>
#include <signal.h>
#include <execinfo.h>
#include <limits.h>
@ -97,7 +98,7 @@
/* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11 }; /* client types */
enum { AxisUp, AxisRight, AxisDown, AxisLeft }; // 滚轮滚动的方向
enum { AxisUp,AxisDown, AxisLeft, AxisRight}; // 滚轮滚动的方向
enum {
LyrBg,
LyrBottom,
@ -123,11 +124,11 @@ enum {
#endif
enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* movewin */
typedef union {
typedef struct {
int i;
unsigned int ui;
float f;
const void *v;
char *v;
unsigned int ui;
} Arg;
typedef struct {
@ -371,7 +372,6 @@ static void autostartexec(void); // 自启动命令执行
static void axisnotify(struct wl_listener *listener, void *data); // 滚轮事件处理
static void buttonpress(struct wl_listener *listener,
void *data); // 鼠标按键事件处理
static void chvt(const Arg *arg);
static void checkidleinhibitor(struct wlr_surface *exclude);
static void cleanup(void); // 退出清理
static void cleanupkeyboard(struct wl_listener *listener,
@ -395,7 +395,6 @@ static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
static void cursorframe(struct wl_listener *listener, void *data);
static void cursorwarptohint(void);
static void destroydecoration(struct wl_listener *listener, void *data);
static void defaultgaps(const Arg *arg);
static void destroydragicon(struct wl_listener *listener, void *data);
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
@ -431,26 +430,17 @@ static void dwl_ipc_output_set_tags(struct wl_client *client,
static void dwl_ipc_output_release(struct wl_client *client,
struct wl_resource *resource);
static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static void setborder_color(Client *c);
static Client *focustop(Monitor *m);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void incnmaster(const Arg *arg);
static void incgaps(const Arg *arg);
static void incigaps(const Arg *arg);
static int keyrepeat(void *data);
static void incihgaps(const Arg *arg);
static void incivgaps(const Arg *arg);
static void incogaps(const Arg *arg);
static void incohgaps(const Arg *arg);
static void incovgaps(const Arg *arg);
static void toggleglobal(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static void killclient(const Arg *arg);
static void locksession(struct wl_listener *listener, void *data);
static void maplayersurfacenotify(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
@ -462,8 +452,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device,
double sx, double sy, double sx_unaccel,
double sy_unaccel);
static void motionrelative(struct wl_listener *listener, void *data);
static void moveresize(const Arg *arg);
static void exchange_client(const Arg *arg);
static void reset_foreign_tolevel(Client *c);
static void exchange_two_client(Client *c1, Client *c2);
static void outputmgrapply(struct wl_listener *listener, void *data);
@ -473,7 +462,6 @@ static void outputmgrtest(struct wl_listener *listener, void *data);
static void pointerfocus(Client *c, struct wlr_surface *surface, double sx,
double sy, uint32_t time);
static void printstatus(void);
static void quit(const Arg *arg);
static void quitsignal(int signo);
static void rendermon(struct wl_listener *listener, void *data);
static void requestdecorationmode(struct wl_listener *listener, void *data);
@ -486,29 +474,20 @@ static void setfloating(Client *c, int floating);
static void setfullscreen(Client *c, int fullscreen);
static void setmaxmizescreen(Client *c, int maxmizescreen);
static void setgaps(int oh, int ov, int ih, int iv);
static void setlayout(const Arg *arg);
static void switch_layout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setmon(Client *c, Monitor *m, unsigned int newtags);
static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data);
static void setup(void);
static void sigchld(int unused);
static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void setgamma(struct wl_listener *listener, void *data);
static void tile(Monitor *m, unsigned int gappo, unsigned int uappi);
static void overview(Monitor *m, unsigned int gappo, unsigned int gappi);
static void grid(Monitor *m, unsigned int gappo, unsigned int uappi);
static void scroller(Monitor *m, unsigned int gappo, unsigned int uappi);
static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg);
static void togglemaxmizescreen(const Arg *arg);
static void togglegaps(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unlocksession(struct wl_listener *listener, void *data);
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
static void unmapnotify(struct wl_listener *listener, void *data);
@ -516,36 +495,24 @@ static void updatemons(struct wl_listener *listener, void *data);
static void updatetitle(struct wl_listener *listener, void *data);
static void urgent(struct wl_listener *listener, void *data);
static void view(const Arg *arg, bool want_animation);
static void bind_to_view(const Arg *arg);
static void viewtoleft_have_client(const Arg *arg);
static void viewtoright_have_client(const Arg *arg);
static void viewtoleft(const Arg *arg);
static void viewtoright(const Arg *arg);
static void handlesig(int signo);
static void tagtoleft(const Arg *arg);
static void tagtoright(const Arg *arg);
static void virtualkeyboard(struct wl_listener *listener, void *data);
static void virtualpointer(struct wl_listener *listener, void *data);
static void warp_cursor(const Client *c);
static Monitor *xytomon(double x, double y);
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
static void zoom(const Arg *arg);
static void clear_fullscreen_flag(Client *c);
static Client *direction_select(const Arg *arg);
static void focusdir(const Arg *arg);
static void toggleoverview(const Arg *arg);
static void set_proportion(const Arg *arg);
static void switch_proportion_preset(const Arg *arg);
static void warp_cursor_to_selmon(const Monitor *m);
unsigned int want_restore_fullscreen(Client *target_client);
static void overview_restore(Client *c, const Arg *arg);
static void overview_backup(Client *c);
static int applyrulesgeom(Client *c);
static void set_minized(Client *c);
static void minized(const Arg *arg);
static void restore_minized(const Arg *arg);
static void toggle_scratchpad(const Arg *arg);
static void show_scratchpad(Client *c);
static void show_hide_client(Client *c);
static void tag_client(const Arg *arg, Client *target_client);
@ -566,6 +533,21 @@ void apply_border(Client *c, struct wlr_box clip_box,int offset);
void client_set_opacity(Client *c, double opacity);
void init_baked_points(void);
Client *direction_select(const Arg *arg);
void bind_to_view(const Arg *arg);
void toggletag(const Arg *arg);
void toggleview(const Arg *arg);
void tag(const Arg *arg);
void incihgaps(const Arg *arg);
void incivgaps(const Arg *arg);
void incogaps(const Arg *arg);
void incohgaps(const Arg *arg);
void incovgaps(const Arg *arg);
void incigaps(const Arg *arg);
void defaultgaps(const Arg *arg);
#include "dispatch.h"
/* variables */
static const char broken[] = "broken";
// static const char *cursor_image = "left_ptr";
@ -646,6 +628,7 @@ static void associatex11(struct wl_listener *listener, void *data);
static Atom getatom(xcb_connection_t *xc, const char *name);
static void sethints(struct wl_listener *listener, void *data);
static void xwaylandready(struct wl_listener *listener, void *data);
void free_config(void);
// static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
// static struct wl_listener xwayland_ready = {.notify = xwaylandready};
static struct wlr_xwayland *xwayland;
@ -653,7 +636,8 @@ static Atom netatom[NetLast];
#endif
/* configuration, allows nested code to access above variables */
#include "config.h"
#include "preset_config.h"
#include "parse_config.h"
/* attempt to encapsulate suck into one file */
#include "client.h"
@ -661,6 +645,8 @@ static Atom netatom[NetLast];
#include "IM.h"
#endif
Config config;
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags {
char limitexceeded[LENGTH(tags) > 31 ? -1 : 1];
@ -1122,23 +1108,23 @@ int // 0.5
applyrulesgeom(Client *c) {
/* rule matching */
const char *appid, *title;
const Rule *r;
ConfigWinRule *r;
int hit = 0;
int ji;
if (!(appid = client_get_appid(c)))
appid = broken;
if (!(title = client_get_title(c)))
title = broken;
for (r = rules; r < END(rules); r++) {
if ((!r->title || strstr(title, r->title)) &&
(!r->id || strstr(appid, r->id)) && r->width != 0 && r->height != 0) {
c->geom.width = r->width;
c->geom.height = r->height;
for (ji = 0; ji < config.window_rules_count; ji++) {
r = &config.window_rules[ji];
if ( (r->title && strstr(title, r->title)) || (r->id && strstr(appid, r->id))) {
c->geom.width = r->width > 0 ? r->width : c->geom.width;
c->geom.height = r->height > 0 ? r->height : c->geom.height;
// 重新计算居中的坐标
c->geom = setclient_coordinate_center(c->geom);
hit = 1;
break;
}
}
return hit;
@ -1149,7 +1135,8 @@ applyrules(Client *c) {
/* rule matching */
const char *appid, *title;
uint32_t i, newtags = 0;
const Rule *r;
int ji;
const ConfigWinRule *r;
Monitor *mon = selmon, *m;
c->isfloating = client_is_float_type(c);
@ -1158,28 +1145,28 @@ applyrules(Client *c) {
if (!(title = client_get_title(c)))
title = broken;
for (r = rules; r < END(rules); r++) {
if ((!r->title || strstr(title, r->title)) &&
(!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating;
c->animation_type = r->animation_type;
for (ji = 0; ji < config.window_rules_count; ji++) {
r = &config.window_rules[ji];
if ( (r->title && strstr(title, r->title)) || (r->id && strstr(appid, r->id))) {
c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating;
c->animation_type = r->animation_type == NULL ? c->animation_type : r->animation_type;
c->scroller_proportion = r->scroller_proportion > 0 ? r->scroller_proportion : scroller_default_proportion;
c->isnoborder = r->isnoborder;
newtags |= r->tags;
c->isnoborder = r->isnoborder > 0 ? r->isnoborder : c->isnoborder;
newtags = r->tags > 0 ? r->tags|newtags : newtags;
i = 0;
wl_list_for_each(m, &mons, link) if (r->monitor == i++) mon = m;
if (c->isfloating && r->width != 0 && r->height != 0) {
c->geom.width = r->width;
c->geom.height = r->height;
if (c->isfloating) {
c->geom.width = r->width > 0 ? r->width : c->geom.width;
c->geom.height = r->height > 0 ? r->height : c->geom.height;
// 重新计算居中的坐标
c->geom = setclient_coordinate_center(c->geom);
}
if (r->isfullscreen) {
if (r->isfullscreen && r->isfullscreen > 0) {
c->isfullscreen = 1;
c->ignore_clear_fullscreen = 1;
}
break;
}
}
@ -1544,7 +1531,8 @@ axisnotify(struct wl_listener *listener, void *data) {
struct wlr_pointer_axis_event *event = data;
struct wlr_keyboard *keyboard;
uint32_t mods;
const Axis *a;
AxisBinding *a;
int ji;
unsigned int adir;
// IDLE_NOTIFY_ACTIVITY;
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
@ -1558,7 +1546,8 @@ axisnotify(struct wl_listener *listener, void *data) {
else
adir = event->delta > 0 ? AxisRight : AxisLeft;
for (a = axes; a < END(axes); a++) {
for (ji = 0; ji < config.axis_bindings_count; ji++) {
a = &config.axis_bindings[ji];
if (CLEANMASK(mods) == CLEANMASK(a->mod) && // 按键一致
adir == a->dir && a->func) { // 滚轮方向判断一致且处理函数存在
if (event->time_msec - axis_apply_time > axis_bind_apply_timeout) {
@ -1587,7 +1576,8 @@ buttonpress(struct wl_listener *listener, void *data) {
struct wlr_keyboard *keyboard;
uint32_t mods;
Client *c;
const Button *b;
int ji;
const MouseBinding *b;
struct wlr_surface *surface;
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
@ -1609,7 +1599,8 @@ buttonpress(struct wl_listener *listener, void *data) {
keyboard = wlr_seat_get_keyboard(seat);
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
for (b = buttons; b < END(buttons); b++) {
for (ji = 0; ji < config.mouse_bindings_count; ji++) {
b = &config.mouse_bindings[ji];
if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button &&
b->func && (selmon->isoverview == 1 || b->button == BTN_MIDDLE) &&
c) {
@ -2003,8 +1994,9 @@ createmon(struct wl_listener *listener, void *data) {
/* This event is raised by the backend when a new output (aka a display or
* monitor) becomes available. */
struct wlr_output *wlr_output = data;
const MonitorRule *r;
const ConfigMonitorRule *r;
size_t i;
int ji,jk;
Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
m->wlr_output = wlr_output;
@ -2034,14 +2026,20 @@ createmon(struct wl_listener *listener, void *data) {
} else {
m->lt[0] = m->lt[1] = &layouts[0];
}
for (r = monrules; r < END(monrules); r++) {
for (ji = 0; ji < config.monitor_rules_count; ji++) {
r = &config.monitor_rules[ji];
if (!r->name || strstr(wlr_output->name, r->name)) {
m->mfact = r->mfact;
m->nmaster = r->nmaster;
m->m.x = r->x;
m->m.y = r->y;
if (r->lt)
m->lt[0] = m->lt[1] = r->lt;
if (r->layout) {
for (jk = 0; jk < LENGTH(layouts); jk++) {
if(strcmp(layouts[jk].name , r->layout) == 0) {
m->lt[0] = m->lt[1] = &layouts[jk];
}
}
}
scale = r->scale;
rr = r->rr;
break;
@ -2889,8 +2887,10 @@ keybinding(uint32_t mods, xkb_keysym_t sym) {
* processing.
*/
int handled = 0;
const Key *k;
for (k = keys; k < END(keys); k++) {
const KeyBinding *k;
int i;
for (i =0; i < config.key_bindings_count; i++) {
k = &config.key_bindings[i];
if (CLEANMASK(mods) == CLEANMASK(k->mod) && sym == k->keysym && k->func) {
k->func(&k->arg);
handled = 1;
@ -3556,6 +3556,7 @@ printstatus(void) {
void // 0.5
quit(const Arg *arg) {
wl_display_terminate(dpy);
free_config();
}
void quitsignal(int signo) { quit(NULL); }
@ -4136,32 +4137,37 @@ void setgaps(int oh, int ov, int ih, int iv) {
void // 17
setlayout(const Arg *arg) {
if (!selmon)
return;
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
selmon->sellt ^= 1;
if (arg && arg->v) {
selmon->lt[selmon->sellt] = (Layout *)arg->v;
selmon->pertag->sellts[selmon->pertag->curtag] = selmon->sellt;
selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] =
selmon->lt[selmon->sellt];
}
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol,
LENGTH(selmon->ltsymbol));
arrange(selmon, false);
printstatus();
int jk;
for (jk = 0; jk < LENGTH(layouts); jk++) {
if(strcmp(layouts[jk].name , arg->v) == 0) {
selmon->lt[selmon->sellt] = &layouts[jk];
selmon->pertag->sellts[selmon->pertag->curtag] = selmon->sellt;
selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] =
selmon->lt[selmon->sellt];
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol,
LENGTH(selmon->ltsymbol));
arrange(selmon, false);
printstatus();
return;
}
}
}
void switch_layout(const Arg *arg) {
if (!selmon)
return;
selmon->sellt ^= 1;
selmon->pertag->sellts[selmon->pertag->curtag] = selmon->sellt;
int jk;
for (jk = 0; jk < LENGTH(layouts); jk++) {
if(strcmp(layouts[jk].name , selmon->lt[selmon->sellt]->name)) {
selmon->lt[selmon->sellt] = &layouts[jk];
selmon->pertag->sellts[selmon->pertag->curtag] = selmon->sellt;
arrange(selmon, false);
printstatus();
return;
}
}
/* TODO change layout symbol? */
arrange(selmon, false);
printstatus();
}
/* arg > 1.0 will set mfact absolutely */
@ -4335,11 +4341,144 @@ void signalhandler(int signalnumber)
// 不调用 exit 以允许生成核心转储文件
}
void free_config(void) {
// 释放内存
int i;
for (i = 0; i < config.window_rules_count; i++) {
ConfigWinRule *rule = &config.window_rules[i];
if (rule->id) free((void *)rule->id);
if (rule->title) free((void *)rule->title);
if (rule->animation_type) free((void *)rule->animation_type);
}
free(config.window_rules);
for ( i = 0; i < config.monitor_rules_count; i++) {
ConfigMonitorRule *rule = &config.monitor_rules[i];
if (rule->name) free((void *)rule->name);
if (rule->layout) free((void *)rule->layout);
}
free(config.monitor_rules);
for ( i = 0; i < config.key_bindings_count; i++) {
if (config.key_bindings[i].arg.v) {
free((void *)config.key_bindings[i].arg.v);
config.key_bindings[i].arg.v = NULL; // 避免重复释放
}
}
free(config.key_bindings);
for ( i = 0; i < config.mouse_bindings_count; i++) {
if (config.mouse_bindings[i].arg.v) {
free((void *)config.mouse_bindings[i].arg.v);
config.mouse_bindings[i].arg.v = NULL; // 避免重复释放
}
}
free(config.mouse_bindings);
for (i = 0; i < config.axis_bindings_count; i++) {
if (config.axis_bindings[i].arg.v) {
free((void *)config.axis_bindings[i].arg.v);
config.axis_bindings[i].arg.v = NULL; // 避免重复释放
}
}
free(config.axis_bindings);
}
void override_config(void) {
animations = config.animations;
animation_type = config.animation_type;
animation_fade_in = config.animation_fade_in;
zoom_initial_ratio = config.zoom_initial_ratio;
fadein_begin_opacity = config.fadein_begin_opacity;
animation_duration_move = config.animation_duration_move;
animation_duration_open = config.animation_duration_open;
animation_duration_tag = config.animation_duration_tag;
// 复制数组类型的变量
memcpy(animation_curve, config.animation_curve, sizeof(animation_curve));
memcpy(scroller_proportion_preset, config.scroller_proportion_preset, sizeof(scroller_proportion_preset));
scroller_structs = config.scroller_structs;
scroller_default_proportion = config.scroller_default_proportion;
scoller_focus_center = config.scoller_focus_center;
new_is_master = config.new_is_master;
default_mfact = config.default_mfact;
default_nmaster = config.default_nmaster;
hotarea_size = config.hotarea_size;
enable_hotarea = config.enable_hotarea;
ov_tab_mode = config.ov_tab_mode;
overviewgappi = config.overviewgappi;
overviewgappo = config.overviewgappo;
axis_bind_apply_timeout = config.axis_bind_apply_timeout;
focus_on_activate = config.focus_on_activate;
numlockon = config.numlockon;
bypass_surface_visibility = config.bypass_surface_visibility;
sloppyfocus = config.sloppyfocus;
warpcursor = config.warpcursor;
smartgaps = config.smartgaps;
gappih = config.gappih;
gappiv = config.gappiv;
gappoh = config.gappoh;
gappov = config.gappov;
borderpx = config.borderpx;
// 复制颜色数组
memcpy(rootcolor, config.rootcolor, sizeof(rootcolor));
memcpy(bordercolor, config.bordercolor, sizeof(bordercolor));
memcpy(focuscolor, config.focuscolor, sizeof(focuscolor));
memcpy(maxmizescreencolor, config.maxmizescreencolor, sizeof(maxmizescreencolor));
memcpy(urgentcolor, config.urgentcolor, sizeof(urgentcolor));
memcpy(scratchpadcolor, config.scratchpadcolor, sizeof(scratchpadcolor));
memcpy(globalcolor, config.globalcolor, sizeof(globalcolor));
}
void parse_config(void) {
char filename[1024];
memset(&config, 0, sizeof(config));
config.window_rules = NULL;
config.window_rules_count = 0;
config.monitor_rules = NULL;
config.monitor_rules_count = 0;
config.key_bindings = NULL;
config.key_bindings_count = 0;
config.mouse_bindings = NULL;
config.mouse_bindings_count = 0;
config.axis_bindings = NULL;
config.axis_bindings_count = 0;
// 获取当前用户家目录
const char *homedir = getenv("HOME");
if (!homedir) {
// 如果获取失败,则无法继续
return;
}
// 构建日志文件路径
snprintf(filename, sizeof(filename), "%s/.config/maomao/config.conf", homedir);
parse_config_file(&config, filename);
override_config();
}
void reload_config(const Arg *arg) {
free_config();
parse_config();
}
void setup(void) {
signal(SIGSEGV, signalhandler);
parse_config();
init_baked_points();
int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
@ -4601,13 +4740,30 @@ void sigchld(int unused) {
}
}
void // 17
spawn(const Arg *arg) {
void spawn(const Arg *arg) {
if (fork() == 0) {
dup2(STDERR_FILENO, STDOUT_FILENO);
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
die("dwl: execvp %s failed:", ((char **)arg->v)[0]);
dup2(STDERR_FILENO, STDOUT_FILENO);
setsid();
// 将 arg->v 拆分为字符串数组
char *argv[64]; // 假设最多有 64 个参数
int argc = 0;
char *token = strtok((char *)arg->v, " ");
while (token != NULL && argc < 63) {
// 扩展 ~ 为家目录路径
wordexp_t p;
if (wordexp(token, &p, 0) == 0) {
argv[argc++] = p.we_wordv[0];
} else {
argv[argc++] = token; // 如果扩展失败,使用原始 token
}
token = strtok(NULL, " ");
}
argv[argc] = NULL; // execvp 需要以 NULL 结尾的数组
// 执行命令
execvp(argv[0], argv);
die("dwl: execvp %s failed:", argv[0]);
}
}
@ -4847,7 +5003,7 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
if (need_scroller) {
if (scoller_foucs_center ||
if (scoller_focus_center ||
selmon->prevsel == NULL ||
(selmon->prevsel->scroller_proportion * max_client_width) + (root_client->scroller_proportion * max_client_width) > m->w.width - 2 * scroller_structs - gappih) {
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;

View file

@ -6,8 +6,25 @@ subdir('protocols')
fs = import('fs')
if not fs.exists('config.h')
run_command('cp', 'config.def.h', 'config.h', check: true)
# 获取用户的主目录
home_dir = run_command('sh', '-c', 'echo $HOME', check: true).stdout().strip()
config_dir = join_paths(home_dir, '.config', 'maomao')
# 如果目标目录不存在,则创建它
if not fs.is_dir(config_dir)
run_command('mkdir', '-p', config_dir, check: true)
endif
# 拷贝 config.conf
config_file = join_paths(config_dir, 'config.conf')
if not fs.exists(config_file)
run_command('cp', 'config.conf', config_file, check: true)
endif
# 拷贝 autostart.sh
autostart_file = join_paths(config_dir, 'autostart.sh')
if not fs.exists(autostart_file)
run_command('cp', 'autostart.sh', autostart_file, check: true)
endif
cc = meson.get_compiler('c')

699
parse_config.h Normal file
View file

@ -0,0 +1,699 @@
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
typedef struct {
const char *id;
const char *title;
unsigned int tags;
int isfloating;
int isfullscreen;
float scroller_proportion;
const char *animation_type;
int isnoborder;
int monitor;
int width;
int height;
} ConfigWinRule;
typedef struct {
const char *name; // 显示器名称
float mfact; // 主区域比例
int nmaster; // 主区域窗口数量
const char *layout; // 布局名称(字符串)
int rr; // 旋转和翻转(假设为整数)
float scale; // 显示器缩放比例
int x, y; // 显示器位置
} ConfigMonitorRule;
typedef struct {
uint32_t mod;
xkb_keysym_t keysym;
void (*func)(const Arg *);
Arg arg;
} KeyBinding;
typedef struct {
unsigned int mod;
unsigned int button;
void (*func)(const Arg *);
Arg arg;
} MouseBinding;
typedef struct {
unsigned int mod;
unsigned int dir;
void (*func)(const Arg *);
Arg arg;
} AxisBinding;
typedef struct {
int animations;
char animation_type[10];
char animation_fade_in;
float zoom_initial_ratio;
float fadein_begin_opacity;
uint32_t animation_duration_move;
uint32_t animation_duration_open;
uint32_t animation_duration_tag;
double animation_curve[4];
int scroller_structs;
float scroller_default_proportion;
int scoller_focus_center;
float scroller_proportion_preset[3];
unsigned int new_is_master;
float default_mfact;
unsigned int default_nmaster;
unsigned int hotarea_size;
unsigned int enable_hotarea;
unsigned int ov_tab_mode;
int overviewgappi;
int overviewgappo;
unsigned int axis_bind_apply_timeout;
unsigned int focus_on_activate;
unsigned int numlockon;
int bypass_surface_visibility;
int sloppyfocus;
int warpcursor;
int smartgaps;
unsigned int gappih;
unsigned int gappiv;
unsigned int gappoh;
unsigned int gappov;
unsigned int borderpx;
float rootcolor[4];
float bordercolor[4];
float focuscolor[4];
float maxmizescreencolor[4];
float urgentcolor[4];
float scratchpadcolor[4];
float globalcolor[4];
char autostart[3][256];
struct {
int id;
char name[256];
} tags[9];
ConfigWinRule *window_rules;
int window_rules_count;
ConfigMonitorRule *monitor_rules; // 动态数组
int monitor_rules_count; // 条数
KeyBinding *key_bindings;
int key_bindings_count;
MouseBinding *mouse_bindings;
int mouse_bindings_count;
AxisBinding *axis_bindings;
int axis_bindings_count;
} Config;
int parseDirection(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, "up") == 0) {
return UP;
} else if (strcmp(lowerStr, "down") == 0) {
return DOWN;
} else if (strcmp(lowerStr, "left") == 0) {
return LEFT;
} else if (strcmp(lowerStr, "right") == 0) {
return RIGHT;
} else {
return UNDIR;
}
}
long int parse_color(const char *hex_str) {
char *endptr;
long int hex_num = strtol(hex_str, &endptr, 16);
if (*endptr != '\0') {
return -1;
}
return hex_num;
}
// 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写)
static bool starts_with_ignore_case(const char *str, const char *prefix) {
while (*prefix) {
if (tolower(*str) != tolower(*prefix)) {
return false;
}
str++;
prefix++;
}
return true;
}
uint32_t parse_mod(const char *mod_str) {
uint32_t mod = 0;
char lower_str[64]; // 假设输入的字符串长度不超过 64
int i = 0;
// 将 mod_str 转换为全小写
for (i = 0; mod_str[i] && i < sizeof(lower_str) - 1; i++) {
lower_str[i] = tolower(mod_str[i]);
}
lower_str[i] = '\0'; // 确保字符串以 NULL 结尾
// 检查修饰键,忽略左右键标识(如 "_l" 和 "_r"
if (strstr(lower_str, "super") || strstr(lower_str, "super_l") || strstr(lower_str, "super_r")) {
mod |= WLR_MODIFIER_LOGO;
}
if (strstr(lower_str, "ctrl") || strstr(lower_str, "ctrl_l") || strstr(lower_str, "ctrl_r")) {
mod |= WLR_MODIFIER_CTRL;
}
if (strstr(lower_str, "shift") || strstr(lower_str, "shift_l") || strstr(lower_str, "shift_r")) {
mod |= WLR_MODIFIER_SHIFT;
}
if (strstr(lower_str, "alt") || strstr(lower_str, "alt_l") || strstr(lower_str, "alt_r")) {
mod |= WLR_MODIFIER_ALT;
}
return mod;
}
xkb_keysym_t parse_keysym(const char *keysym_str) {
return xkb_keysym_from_name(keysym_str, XKB_KEYSYM_NO_FLAGS);
}
typedef void (*FuncType)(const Arg *);
int parseButton(const char *str) {
// 将输入字符串转换为小写
char lowerStr[20];
int i = 0;
while (str[i] && i < 19) {
lowerStr[i] = tolower(str[i]);
i++;
}
lowerStr[i] = '\0'; // 确保字符串正确终止
// 根据转换后的小写字符串返回对应的按钮编号
if (strcmp(lowerStr, "btn_left") == 0) {
return BTN_LEFT;
} else if (strcmp(lowerStr, "btn_right") == 0) {
return BTN_RIGHT;
} else if (strcmp(lowerStr, "btn_middle") == 0) {
return BTN_MIDDLE;
} else if (strcmp(lowerStr, "btn_side") == 0) {
return BTN_SIDE;
} else if (strcmp(lowerStr, "btn_extra") == 0) {
return BTN_EXTRA;
} else if (strcmp(lowerStr, "btn_forward") == 0) {
return BTN_FORWARD;
} else if (strcmp(lowerStr, "btn_back") == 0) {
return BTN_BACK;
} else if (strcmp(lowerStr, "btn_task") == 0) {
return BTN_TASK;
} else {
return 0;
}
}
int parseMouseAction(const char *str) {
// 将输入字符串转换为小写
char lowerStr[20];
int i = 0;
while (str[i] && i < 19) {
lowerStr[i] = tolower(str[i]);
i++;
}
lowerStr[i] = '\0'; // 确保字符串正确终止
// 根据转换后的小写字符串返回对应的按钮编号
if (strcmp(lowerStr, "curmove") == 0) {
return CurMove;
} else if (strcmp(lowerStr, "curresize") == 0) {
return CurResize;
} else if (strcmp(lowerStr, "curnormal") == 0) {
return CurNormal;
} else if (strcmp(lowerStr, "curpressed") == 0) {
return CurPressed;
} else {
return 0;
}
}
void parseColoer(float *color,unsigned long int hex) {
color[0] = ((hex >> 24) & 0xFF) / 255.0f;
color[1] = ((hex >> 16) & 0xFF) / 255.0f;
color[2] = ((hex >> 8) & 0xFF) / 255.0f;
color[3] = (hex & 0xFF) / 255.0f;
}
FuncType parse_func_name(char *func_name,Arg *arg, char *arg_value) {
FuncType func = NULL;
(*arg).v = NULL;
if (strcmp(func_name, "focusstack") == 0) {
func = focusstack;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "focusdir") == 0) {
func = focusdir;
(*arg).i = parseDirection(arg_value);
} else if (strcmp(func_name, "incnmaster") == 0) {
func = incnmaster;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "setmfact") == 0) {
func = setmfact;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "zoom") == 0) {
func = zoom;
} else if (strcmp(func_name, "exchange_client") == 0) {
func = exchange_client;
(*arg).i = parseDirection(arg_value);
} else if (strcmp(func_name, "toggleglobal") == 0) {
func = toggleglobal;
} else if (strcmp(func_name, "toggleoverview") == 0) {
func = toggleoverview;
} else if (strcmp(func_name, "set_proportion") == 0) {
func = set_proportion;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "switch_proportion_preset") == 0) {
func = switch_proportion_preset;
} else if (strcmp(func_name, "viewtoleft") == 0) {
func = viewtoleft;
} else if (strcmp(func_name, "viewtoright") == 0) {
func = viewtoright;
} else if (strcmp(func_name, "tagtoleft") == 0) {
func = tagtoleft;
} else if (strcmp(func_name, "tagtoright") == 0) {
func = tagtoright;
} else if (strcmp(func_name, "killclient") == 0) {
func = killclient;
} else if (strcmp(func_name, "setlayout") == 0) {
func = setlayout;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "switch_layout") == 0) {
func = switch_layout;
} else if (strcmp(func_name, "togglefloating") == 0) {
func = togglefloating;
} else if (strcmp(func_name, "togglefullscreen") == 0) {
func = togglefullscreen;
} else if (strcmp(func_name, "minized") == 0) {
func = minized;
} else if (strcmp(func_name, "restore_minized") == 0) {
func = restore_minized;
} else if (strcmp(func_name, "toggle_scratchpad") == 0) {
func = toggle_scratchpad;
} else if (strcmp(func_name, "focusmon") == 0) {
func = focusmon;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "tagmon") == 0) {
func = tagmon;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "incgaps") == 0) {
func = incgaps;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "togglegaps") == 0) {
func = togglegaps;
} else if (strcmp(func_name, "chvt") == 0) {
func = chvt;
(*arg).i = atoi(arg_value);
} else if (strcmp(func_name, "spawn") == 0) {
func = spawn;
(*arg).v = strdup(arg_value);
} else if (strcmp(func_name, "quit") == 0) {
func = quit;
} else if (strcmp(func_name, "moveresize") == 0) {
func = moveresize;
(*arg).ui = parseMouseAction(arg_value);
} else if (strcmp(func_name, "togglemaxmizescreen") == 0) {
func = togglemaxmizescreen;
} else if (strcmp(func_name, "viewtoleft_have_client") == 0) {
func = viewtoleft_have_client;
} else if (strcmp(func_name, "viewtoright_have_client") == 0) {
func = viewtoright_have_client;
} else if (strcmp(func_name, "reload_config") == 0) {
func = reload_config;
} else if (strcmp(func_name, "tag") == 0) {
func = tag;
(*arg).ui = 1 << (atoi(arg_value) -1);
} else if (strcmp(func_name, "view") == 0) {
func = bind_to_view;
(*arg).ui = 1 << (atoi(arg_value) - 1);
} else {
return NULL;
}
return func;
}
void parse_config_line(Config *config, const char *line) {
char key[256], value[256];
if (sscanf(line, "%[^=]=%[^\n]", key, value) != 2) {
fprintf(stderr, "Error: Invalid line format: %s\n", line);
return;
}
if (strcmp(key, "animations") == 0) {
config->animations = atoi(value);
} else if (strcmp(key, "animation_type") == 0) {
strncpy(config->animation_type, value, sizeof(config->animation_type));
} else if (strcmp(key, "animation_fade_in") == 0) {
config->animation_fade_in = atoi(value);
} else if (strcmp(key, "zoom_initial_ratio") == 0) {
config->zoom_initial_ratio = atof(value);
} else if (strcmp(key, "fadein_begin_opacity") == 0) {
config->fadein_begin_opacity = atof(value);
} else if (strcmp(key, "animation_duration_move") == 0) {
config->animation_duration_move = atoi(value);
} else if (strcmp(key, "animation_duration_open") == 0) {
config->animation_duration_open = atoi(value);
} else if (strcmp(key, "animation_duration_tag") == 0) {
config->animation_duration_tag = atoi(value);
} else if (strcmp(key, "animation_curve") == 0) {
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve[0], &config->animation_curve[1], &config->animation_curve[2], &config->animation_curve[3]) != 4) {
fprintf(stderr, "Error: Invalid animation_curve format: %s\n", value);
}
} else if (strcmp(key, "scroller_structs") == 0) {
config->scroller_structs = atoi(value);
} else if (strcmp(key, "scroller_default_proportion") == 0) {
config->scroller_default_proportion = atof(value);
} else if (strcmp(key, "scoller_focus_center") == 0) {
config->scoller_focus_center = atoi(value);
} else if (strcmp(key, "scroller_proportion_preset") == 0) {
if (sscanf(value, "%f,%f,%f", &config->scroller_proportion_preset[0], &config->scroller_proportion_preset[1], &config->scroller_proportion_preset[2]) != 3) {
fprintf(stderr, "Error: Invalid scroller_proportion_preset format: %s\n", value);
}
} else if (strcmp(key, "new_is_master") == 0) {
config->new_is_master = atoi(value);
} else if (strcmp(key, "default_mfact") == 0) {
config->default_mfact = atof(value);
} else if (strcmp(key, "default_nmaster") == 0) {
config->default_nmaster = atoi(value);
} else if (strcmp(key, "hotarea_size") == 0) {
config->hotarea_size = atoi(value);
} else if (strcmp(key, "enable_hotarea") == 0) {
config->enable_hotarea = atoi(value);
} else if (strcmp(key, "ov_tab_mode") == 0) {
config->ov_tab_mode = atoi(value);
} else if (strcmp(key, "overviewgappi") == 0) {
config->overviewgappi = atoi(value);
} else if (strcmp(key, "overviewgappo") == 0) {
config->overviewgappo = atoi(value);
} else if (strcmp(key, "axis_bind_apply_timeout") == 0) {
config->axis_bind_apply_timeout = atoi(value);
} else if (strcmp(key, "focus_on_activate") == 0) {
config->focus_on_activate = atoi(value);
} else if (strcmp(key, "numlockon") == 0) {
config->numlockon = atoi(value);
} else if (strcmp(key, "bypass_surface_visibility") == 0) {
config->bypass_surface_visibility = atoi(value);
} else if (strcmp(key, "sloppyfocus") == 0) {
config->sloppyfocus = atoi(value);
} else if (strcmp(key, "warpcursor") == 0) {
config->warpcursor = atoi(value);
} else if (strcmp(key, "smartgaps") == 0) {
config->smartgaps = atoi(value);
} else if (strcmp(key, "gappih") == 0) {
config->gappih = atoi(value);
} else if (strcmp(key, "gappiv") == 0) {
config->gappiv = atoi(value);
} else if (strcmp(key, "gappoh") == 0) {
config->gappoh = atoi(value);
} else if (strcmp(key, "gappov") == 0) {
config->gappov = atoi(value);
} else if (strcmp(key, "borderpx") == 0) {
config->borderpx = atoi(value);
} else if (strcmp(key, "rootcolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid rootcolor format: %s\n", value);
} else {
parseColoer(config->rootcolor,color);
}
} else if (strcmp(key, "bordercolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid bordercolor format: %s\n", value);
} else {
parseColoer(config->bordercolor,color);
}
} else if (strcmp(key, "focuscolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid focuscolor format: %s\n", value);
} else {
parseColoer(config->focuscolor,color);
}
} else if (strcmp(key, "maxmizescreencolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid maxmizescreencolor format: %s\n", value);
} else {
parseColoer(config->maxmizescreencolor,color);
}
} else if (strcmp(key, "urgentcolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid urgentcolor format: %s\n", value);
} else {
parseColoer(config->urgentcolor,color);
}
} else if (strcmp(key, "scratchpadcolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid scratchpadcolor format: %s\n", value);
} else {
parseColoer(config->scratchpadcolor,color);
}
} else if (strcmp(key, "globalcolor") == 0) {
long int color = parse_color(value);
if (color == -1) {
fprintf(stderr, "Error: Invalid globalcolor format: %s\n", value);
} else {
parseColoer(config->globalcolor,color);
}
} else if (strcmp(key, "autostart") == 0) {
if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0], config->autostart[1], config->autostart[2]) != 3) {
fprintf(stderr, "Error: Invalid autostart format: %s\n", value);
}
} else if (strcmp(key, "tags") == 0) {
int id;
char name[256];
if (sscanf(value, "id:%d,name:%255[^\n]", &id, name) == 2) {
if (id >= 1 && id <= 9) {
config->tags[id - 1].id = id;
strncpy(config->tags[id - 1].name, name, sizeof(config->tags[id - 1].name));
} else {
fprintf(stderr, "Error: Invalid tag id: %d\n", id);
}
} else {
fprintf(stderr, "Error: Invalid tags format: %s\n", value);
}
} else if (strcmp(key, "windowrule") == 0) {
config->window_rules = realloc(config->window_rules, (config->window_rules_count + 1) * sizeof(ConfigWinRule));
if (!config->window_rules) {
fprintf(stderr, "Error: Failed to allocate memory for window rules\n");
return;
}
ConfigWinRule *rule = &config->window_rules[config->window_rules_count];
memset(rule, 0, sizeof(ConfigWinRule));
rule->isfloating = -1;
rule->isfullscreen = -1;
rule->isnoborder = -1;
rule->monitor = -1;
rule->width = -1;
rule->height = -1;
rule->animation_type = NULL;
rule->scroller_proportion = -1;
rule->id = NULL;
rule->title = NULL;
rule->tags = 0;
char *token = strtok(value, ",");
while (token != NULL) {
char *colon = strchr(token, ':');
if (colon != NULL) {
*colon = '\0';
char *key = token;
char *val = colon + 1;
if (strcmp(key, "isfloating") == 0) {
rule->isfloating = atoi(val);
} else if (strcmp(key, "title") == 0) {
rule->title = strdup(val);
} else if (strcmp(key, "appid") == 0) {
rule->id = strdup(val);
} else if (strcmp(key, "animation_type") == 0) {
rule->animation_type = strdup(val);
} else if (strcmp(key, "tags") == 0) {
rule->tags = 1 << (atoi(val) - 1);
} else if (strcmp(key, "monitor") == 0) {
rule->monitor = atoi(val);
} else if (strcmp(key, "width") == 0) {
rule->width = atoi(val);
} else if (strcmp(key, "height") == 0) {
rule->height = atoi(val);
} else if (strcmp(key, "isnoborder") == 0) {
rule->isnoborder = atoi(val);
} else if (strcmp(key, "scroller_proportion") == 0) {
rule->scroller_proportion = atof(val);
} else if (strcmp(key, "isfullscreen") == 0) {
rule->isfullscreen = atoi(val);
}
}
token = strtok(NULL, ",");
}
config->window_rules_count++;
} else if (strcmp(key, "monitorrule") == 0) {
config->monitor_rules = realloc(config->monitor_rules, (config->monitor_rules_count + 1) * sizeof(ConfigMonitorRule));
if (!config->monitor_rules) {
fprintf(stderr, "Error: Failed to allocate memory for monitor rules\n");
return;
}
ConfigMonitorRule *rule = &config->monitor_rules[config->monitor_rules_count];
memset(rule, 0, sizeof(ConfigMonitorRule));
char layout[256], name[256];
int parsed = sscanf(value, "%255[^,],%f,%d,%255[^,],%d,%f,%d,%d",
name,
&rule->mfact,
&rule->nmaster,
layout,
&rule->rr,
&rule->scale,
&rule->x,
&rule->y);
if (parsed == 8) {
rule->name = strdup(name);
rule->layout = strdup(layout);
if (!rule->name || !rule->layout) {
if (rule->name) free((void *)rule->name);
if (rule->layout) free((void *)rule->layout);
fprintf(stderr, "Error: Failed to allocate memory for monitor rule\n");
return;
}
config->monitor_rules_count++;
} else {
fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value);
}
} else if (strncmp(key, "bind", 4) == 0) {
config->key_bindings = realloc(config->key_bindings, (config->key_bindings_count + 1) * sizeof(KeyBinding));
if (!config->key_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for key bindings\n");
return;
}
KeyBinding *binding = &config->key_bindings[config->key_bindings_count];
memset(binding, 0, sizeof(KeyBinding));
char mod_str[256], keysym_str[256], func_name[256], arg_value[256] = "none";
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, keysym_str, func_name, arg_value) < 3) {
fprintf(stderr, "Error: Invalid bind format: %s\n", value);
return;
}
binding->mod = parse_mod(mod_str);
binding->keysym = parse_keysym(keysym_str);
binding->arg.v = NULL;
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
if (!binding->func){
fprintf(stderr, "Error: Unknown function in bind: %s\n", func_name);
} else {
config->key_bindings_count++;
}
} else if (strncmp(key, "mousebind", 9) == 0) {
config->mouse_bindings = realloc(config->mouse_bindings, (config->mouse_bindings_count + 1) * sizeof(MouseBinding));
if (!config->mouse_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for mouse bindings\n");
return;
}
MouseBinding *binding = &config->mouse_bindings[config->mouse_bindings_count];
memset(binding, 0, sizeof(MouseBinding));
char mod_str[256], button_str[256], func_name[256], arg_value[256] = "none";
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, button_str, func_name, arg_value) < 3) {
fprintf(stderr, "Error: Invalid mousebind format: %s\n", value);
return;
}
binding->mod = parse_mod(mod_str);
binding->button = parseButton(button_str);
binding->arg.v = NULL;
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
if (!binding->func){
fprintf(stderr, "Error: Unknown function in mousebind: %s\n", func_name);
} else {
config->mouse_bindings_count++;
}
} else if (strncmp(key, "axisbind", 8) == 0) {
config->axis_bindings = realloc(config->axis_bindings, (config->axis_bindings_count + 1) * sizeof(AxisBinding));
if (!config->axis_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for axis bindings\n");
return;
}
AxisBinding *binding = &config->axis_bindings[config->axis_bindings_count];
memset(binding, 0, sizeof(AxisBinding));
char mod_str[256], dir_str[256], func_name[256], arg_value[256] = "none";
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, dir_str, func_name, arg_value) < 3) {
fprintf(stderr, "Error: Invalid axisbind format: %s\n", value);
return;
}
binding->mod = parse_mod(mod_str);
binding->dir = parseDirection(dir_str);
binding->arg.v = NULL;
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
if (!binding->func){
fprintf(stderr, "Error: Unknown function in axisbind: %s\n", func_name);
} else {
config->axis_bindings_count++;
}
} else {
fprintf(stderr, "Error: Unknown key: %s\n", key);
}
}
void parse_config_file(Config *config, const char *file_path) {
FILE *file = fopen(file_path, "r");
if (!file) {
perror("Error opening file");
return;
}
char line[512];
while (fgets(line, sizeof(line), file)) {
if (line[0] == '#' || line[0] == '\n') continue;
parse_config_line(config, line);
}
fclose(file);
}

151
preset_config.h Normal file
View file

@ -0,0 +1,151 @@
/* speedie's maomao config */
#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \
((hex >> 16) & 0xFF) / 255.0f, \
((hex >> 8) & 0xFF) / 255.0f, \
(hex & 0xFF) / 255.0f }
/* animaion */
char *animation_type = "slide"; //是否启用动画 //slide,zoom
int animations = 1; //是否启用动画
char animation_fade_in = 1; // Enable animation fade in
float zoom_initial_ratio = 0.5; //动画起始窗口比例
float fadein_begin_opacity = 0; // Begin opac window ratio for animations
uint32_t animation_duration_move = 500; // Animation move speed
uint32_t animation_duration_open = 400; // Animation open speed
uint32_t animation_duration_tag = 300; // Animation tag speed
double animation_curve[4] = {0.46,1.0,0.29,0.99}; //动画曲线
/* appearance */
unsigned int axis_bind_apply_timeout = 100; //滚轮绑定动作的触发的时间间隔
unsigned int focus_on_activate = 1; //收到窗口激活请求是否自动跳转聚焦
unsigned int new_is_master = 1; //新窗口是否插在头部
unsigned int default_mfact = 0.55f; // master 窗口比例
unsigned int default_nmaster = 1; //默认master数量
/* logging */
int log_level = WLR_ERROR;
unsigned int numlockon = 1; //是否打开右边小键盘
unsigned int ov_tab_mode = 0; // alt tab切换模式
unsigned int hotarea_size = 10; //热区大小,10x10
unsigned int enable_hotarea = 1; //是否启用鼠标热区
int smartgaps = 0; /* 1 means no outer gap when there is only one window */
int sloppyfocus = 1; /* focus follows mouse */
unsigned int gappih = 5; /* horiz inner gap between windows */
unsigned int gappiv = 5; /* vert inner gap between windows */
unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
unsigned int gappov = 10; /* vert outer gap between windows and screen edge */
int scroller_structs = 20;
float scroller_default_proportion = 0.9;
int scoller_focus_center = 0;
float scroller_proportion_preset[] = {0.5,0.9,1.0};
int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
unsigned int borderpx = 4; /* border pixel of windows */
float rootcolor[] = COLOR(0x323232ff);
float bordercolor[] = COLOR(0x444444ff);
float focuscolor[] = COLOR(0xc66b25ff);
float maxmizescreencolor[] = COLOR(0x89aa61ff);
float urgentcolor[] = COLOR(0xad401fff);
float scratchpadcolor[] = COLOR(0x516c93ff);
float globalcolor[] = COLOR(0xb153a7ff);
// char *cursor_theme = "Bibata-Modern-Ice";
int overviewgappi = 5; /* overview时 窗口与边缘 缝隙大小 */
int overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
int warpcursor = 1; /* Warp cursor to focused client */
/* layout(s) */
Layout overviewlayout = { "󰃇", overview, "overview" };
Layout layouts[] = { //最少两个,不能删除少于两个
/* symbol arrange function name */
{ "", scroller, "scroller" }, //滚动布局
{ "󱞬", tile, "tile" }, //堆栈布局
};
/* keyboard */
struct xkb_rule_names xkb_rules = {
/* can specify fields: rules, model, layout, variant, options */
/* example:
.options = "ctrl:nocaps",
*/
.options = NULL,
};
int repeat_rate = 25;
int repeat_delay = 600;
/* Trackpad */
int tap_to_click = 1;
int tap_and_drag = 1;
int drag_lock = 1;
int natural_scrolling = 0;
int disable_while_typing = 1;
int left_handed = 0;
int middle_button_emulation = 0;
/* You can choose between:
LIBINPUT_CONFIG_SCROLL_NO_SCROLL
LIBINPUT_CONFIG_SCROLL_2FG
LIBINPUT_CONFIG_SCROLL_EDGE
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
*/
enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
/* You can choose between:
LIBINPUT_CONFIG_CLICK_METHOD_NONE
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
*/
enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
/* You can choose between:
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE
*/
uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
/* You can choose between:
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
*/
enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
double accel_speed = 0.0;
/* You can choose between:
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
*/
enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT
static const char *tags[] = {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
};
static const char *const autostart[] = {
"/bin/sh",
"-c",
"~/.config/maomao/autostart.sh",
NULL,
NULL,
};