From 16fe8f61944092b69ef06e8a8cb39c5a3435c202 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 16 Feb 2025 23:09:46 +0800 Subject: [PATCH] feat: support config file and reload config without logout --- README.md | 5 +- autostart.sh | 10 +- config.conf | 201 ++++++++++++++ config.def.h | 278 ------------------- dispatch.h | 34 +++ maomao.c | 372 ++++++++++++++++++-------- meson.build | 21 +- parse_config.h | 699 ++++++++++++++++++++++++++++++++++++++++++++++++ preset_config.h | 151 +++++++++++ 9 files changed, 1377 insertions(+), 394 deletions(-) create mode 100644 config.conf delete mode 100644 config.def.h create mode 100644 dispatch.h create mode 100644 parse_config.h create mode 100644 preset_config.h diff --git a/README.md b/README.md index d118334..228e51c 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/autostart.sh b/autostart.sh index 86f0382..ea54097 100755 --- a/autostart.sh +++ b/autostart.sh @@ -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 + diff --git a/config.conf b/config.conf new file mode 100644 index 0000000..4f3c1b3 --- /dev/null +++ b/config.conf @@ -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 diff --git a/config.def.h b/config.def.h deleted file mode 100644 index cb5103b..0000000 --- a/config.def.h +++ /dev/null @@ -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 -}; diff --git a/dispatch.h b/dispatch.h new file mode 100644 index 0000000..4e7e168 --- /dev/null +++ b/dispatch.h @@ -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); \ No newline at end of file diff --git a/maomao.c b/maomao.c index c0a99c2..7825339 100644 --- a/maomao.c +++ b/maomao.c @@ -3,6 +3,7 @@ */ #include #include +#include #include #include #include @@ -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; diff --git a/meson.build b/meson.build index 499bcac..261f2b4 100644 --- a/meson.build +++ b/meson.build @@ -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') diff --git a/parse_config.h b/parse_config.h new file mode 100644 index 0000000..9cbeeb1 --- /dev/null +++ b/parse_config.h @@ -0,0 +1,699 @@ +#include +#include +#include +#include + +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); +} \ No newline at end of file diff --git a/preset_config.h b/preset_config.h new file mode 100644 index 0000000..7cac46c --- /dev/null +++ b/preset_config.h @@ -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, +}; \ No newline at end of file