diff --git a/README.md b/README.md index b420750..78a44b3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ +Master-Stack Layout https://github.com/user-attachments/assets/da80c6d1-b9a5-44c4-b738-6421365e6aa5 +Scroller Layout + +https://github.com/user-attachments/assets/2ff96868-b276-4fa1-b4d7-87bdc36beb3c + + # feature - dwl ipc support @@ -29,6 +35,8 @@ https://github.com/user-attachments/assets/da80c6d1-b9a5-44c4-b738-6421365e6aa5 - window close animaition - custom mov/open/tag animaition sppeed - fade in animation +- alt-tab switch window like gnome +- niri like scroller layout ## suggest tools diff --git a/config.def.h b/config.def.h index 711ec18..d8576ba 100644 --- a/config.def.h +++ b/config.def.h @@ -17,43 +17,54 @@ static const uint32_t animation_duration_tag = 300; // 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 -/* appearance */ -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 +/* 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 -/* logging */ -static int log_level = WLR_ERROR; -static const unsigned int numlockon = 1; // Enable numlock + +/* 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 int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +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 int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if the surface isn't visible */ 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 fakefullscreencolor[] = COLOR(0x89aa61ff); +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"; -static const int overviewgappi = 5; /* Gap between windows and edges in overview mode */ -static const int overviewgappo = 30; /* Gap between windows in overview mode */ - /* 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}; -static int warpcursor = 1; /* Warp cursor to focused client */ - /* Autostart */ static const char *const autostart[] = { "/bin/sh", @@ -94,8 +105,8 @@ static const Layout overviewlayout = { "󰃇", overview }; static const Layout layouts[] = { // At least two layouts, cannot delete less than two /* symbol arrange function */ - { "󱞬", tile }, // Stack layout - { "﩯", grid }, // Grid layout + { "󱞬", tile, "tile" }, // master-stack layout + { "", scroller, "scroller" }, // scroller layout }; @@ -178,14 +189,14 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ -// static const char *termcmd[] = { "foot", NULL }; -// static const char *menucmd[] = { "wofi --conf ~/.config/maomao/wofi/config_menu", NULL }; +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") }, - { MODKEY, XKB_KEY_Return, spawn, SHCMD("foot") }, + { MODKEY, XKB_KEY_space, spawn, {.v = menucmd} }, + { MODKEY, XKB_KEY_Return, spawn, {.v = termcmd} }, { WLR_MODIFIER_LOGO, XKB_KEY_Tab, focusstack, {.i = +1} }, @@ -214,11 +225,13 @@ static const Key keys[] = { { 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} }, - { WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, - { WLR_MODIFIER_CTRL|WLR_MODIFIER_LOGO, XKB_KEY_g, setlayout, {.v = &layouts[1]} }, + { 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, togglefakefullscreen, {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} }, @@ -250,7 +263,7 @@ static const Key keys[] = { static const Button buttons[] = { { WLR_MODIFIER_LOGO, BTN_LEFT, moveresize, {.ui = CurMove } }, - { 0, BTN_MIDDLE, togglefakefullscreen, {0} }, // Middle button triggers fake fullscreen + { 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 } }, diff --git a/main.c b/main.c index c3678f7..239cb01 100644 --- a/main.c +++ b/main.c @@ -84,8 +84,8 @@ #define TAGMASK ((1 << LENGTH(tags)) - 1) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #define ISFULLSCREEN(A) \ - ((A)->isfullscreen || (A)->isfakefullscreen || \ - (A)->overview_isfakefullscreenbak || (A)->overview_isfullscreenbak) + ((A)->isfullscreen || (A)->ismaxmizescreen || \ + (A)->overview_ismaxmizescreenbak || (A)->overview_isfullscreenbak) #define LISTEN_STATIC(E, H) \ do { \ static struct wl_listener _l = {.notify = (H)}; \ @@ -197,12 +197,12 @@ typedef struct { uint32_t configure_serial; struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; int isfloating, isurgent, isfullscreen, istiled, isminied; - int isfakefullscreen; + int ismaxmizescreen; int overview_backup_x, overview_backup_y, overview_backup_w, overview_backup_h, overview_backup_bw; int fullscreen_backup_x, fullscreen_backup_y, fullscreen_backup_w, fullscreen_backup_h; - int overview_isfullscreenbak, overview_isfakefullscreenbak, + int overview_isfullscreenbak, overview_ismaxmizescreenbak, overview_isfloatingbak; uint32_t resize; /* configure serial of a pending resize */ @@ -225,6 +225,7 @@ typedef struct { bool resizing; bool is_open_animation; bool is_restoring_from_ov; + float scroller_proportion; struct dwl_animation animation; @@ -278,6 +279,7 @@ typedef struct { typedef struct { const char *symbol; void (*arrange)(Monitor *, unsigned int, unsigned int); + const char *name; } Layout; struct Monitor { @@ -307,7 +309,7 @@ struct Monitor { int gappoh; /* horizontal outer gaps */ int gappov; /* vertical outer gaps */ Pertag *pertag; - Client *sel; + Client *sel,*prevsel; int isoverview; int is_in_hotarea; int gamma_lut_changed; @@ -480,7 +482,7 @@ static void run(char *startup_cmd); static void setcursor(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); -static void setfakefullscreen(Client *c, int fakefullscreen); +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); @@ -498,9 +500,10 @@ 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 togglefakefullscreen(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); @@ -530,6 +533,8 @@ 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); @@ -856,10 +861,10 @@ applybounds(Client *c, struct wlr_box *bbox) { /*清除全屏标志,还原全屏时清0的border*/ void clear_fullscreen_flag(Client *c) { - if (c->isfullscreen || c->isfakefullscreen) { + if (c->isfullscreen || c->ismaxmizescreen) { c->isfullscreen = 0; c->isfloating = 0; - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; c->bw = borderpx; client_set_fullscreen(c, false); } @@ -906,9 +911,9 @@ void restore_minized(const Arg *arg) { void show_scratchpad(Client *c) { c->is_scratchpad_show = 1; - if (c->isfullscreen || c->isfakefullscreen) { + if (c->isfullscreen || c->ismaxmizescreen) { c->isfullscreen = 0; // 清除窗口全屏标志 - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; c->bw = borderpx; // 恢复非全屏的border } /* return if fullscreen */ @@ -1046,7 +1051,7 @@ void logtofile(const char *fmt, ...) { /* function implementations */ void lognumtofile(unsigned int num) { char cmd[256]; - sprintf(cmd, "echo '%x' >> ~/log", num); + sprintf(cmd, "echo '%d' >> ~/log", num); system(cmd); } @@ -1146,10 +1151,7 @@ arrange(Monitor *m, bool want_animation) { wl_list_for_each(c, &clients, link) { if (c->iskilling) continue; - if (c->mon == m && c->isglobal) { - c->tags = m->tagset[m->seltags]; - focusclient(c, 1); - } + if (c->mon == m) { if (VISIBLEON(c, m)) { wlr_scene_node_set_enabled(&c->scene->node, true); @@ -1166,7 +1168,7 @@ arrange(Monitor *m, bool want_animation) { } c->animation.from_rule = false; - if ((c->isfloating || c->isfullscreen || c->isfakefullscreen) && + if ((c->isfloating || c->isfullscreen || c->ismaxmizescreen) && (c->animation.tagouting || c->animation.tagouted)) { c->animation.tagouting = false; c->animation.tagouted = false; @@ -1247,7 +1249,7 @@ Client *direction_select(const Arg *arg) { return NULL; if (tc && - (tc->isfullscreen || tc->isfakefullscreen)) /* no support for focusstack + (tc->isfullscreen || tc->ismaxmizescreen)) /* no support for focusstack with fullscreen windows */ return NULL; @@ -2548,8 +2550,15 @@ void focusclient(Client *c, int lift) { wlr_foreign_toplevel_handle_v1_set_activated(selmon->sel->foreign_toplevel, false); } - if (selmon) + if (selmon) { + selmon->prevsel = selmon->sel; selmon->sel = c; + if (c && selmon->prevsel && selmon->prevsel->istiled && selmon->prevsel->tags == c->tags && c->istiled && !c->isfloating && !c->isfullscreen && strcmp(selmon->lt[selmon->sellt]->name , "scroller") == 0) { + arrange(selmon,false); + } else if (selmon->prevsel) { + selmon->prevsel =NULL; + } + } if (c && c->foreign_toplevel) wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); @@ -2977,22 +2986,23 @@ mapnotify(struct wl_listener *listener, void *data) { WLR_EDGE_RIGHT); c->geom.width += 2 * c->bw; c->geom.height += 2 * c->bw; - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; c->isfullscreen = 0; c->istiled = 0; c->ignore_clear_fullscreen = 0; c->iskilling = 0; - // c->animainit_geom.width = c->geom.width * zoom_initial_ratio; - // c->animainit_geom.height = c->geom.height * zoom_initial_ratio; - // c->animainit_geom.x = c->geom.x + (c->geom.width - - // c->animainit_geom.width)/2; c->animainit_geom.y = c->geom.y + - // (c->geom.height - c->animainit_geom.height)/2; + c->scroller_proportion = scroller_default_proportion; c->is_open_animation = true; // nop - if (new_is_master) + if (new_is_master && strcmp(selmon->lt[selmon->sellt]->name , "scroller") != 0) // tile at the top wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈 - else + else if (strcmp(selmon->lt[selmon->sellt]->name , "scroller") == 0 && selmon->sel && selmon->sel->istiled) { + selmon->sel->link.next->prev = &c->link; + c->link.prev = &selmon->sel->link; + c->link.next = selmon->sel->link.next; + selmon->sel->link.next = &c->link; + }else wl_list_insert(clients.prev, &c->link); // 尾部入栈 wl_list_insert(&fstack, &c->flink); @@ -3060,16 +3070,16 @@ maximizenotify(struct wl_listener *listener, void *data) { // if (wl_resource_get_version(c->surface.xdg->toplevel->resource) // < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) // wlr_xdg_surface_schedule_configure(c->surface.xdg); - // togglefakefullscreen(&(Arg){0}); + // togglemaxmizescreen(&(Arg){0}); Client *c = wl_container_of(listener, c, maximize); if(!c || c->iskilling) return; - if (c->isfakefullscreen || c->isfullscreen) - setfakefullscreen(c, 0); + if (c->ismaxmizescreen || c->isfullscreen) + setmaxmizescreen(c, 0); else - setfakefullscreen(c, 1); + setmaxmizescreen(c, 1); } void set_minized(Client *c) { @@ -3105,7 +3115,7 @@ minimizenotify(struct wl_listener *listener, void *data) { // if (wl_resource_get_version(c->surface.xdg->toplevel->resource) // < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) // wlr_xdg_surface_schedule_configure(c->surface.xdg); - // togglefakefullscreen(&(Arg){0}); + // togglemaxmizescreen(&(Arg){0}); Client *c = wl_container_of(listener, c, minimize); if(!c || c->iskilling) @@ -3466,7 +3476,7 @@ void client_handle_opacity(Client *c) { if (!c || !c->mon || !client_surface(c)->mapped) return; - double opacity = c->isfullscreen || c->isfakefullscreen ? 1.0 + double opacity = c->isfullscreen || c->ismaxmizescreen ? 1.0 : c == selmon->sel ? 0.8 : 0.5; @@ -3589,9 +3599,9 @@ void setborder_color(Client *c) { } else if (c->isglobal && c == selmon->sel) { for (i = 0; i < 4; i++) wlr_scene_rect_set_color(c->border[i], globalcolor); - } else if (c->isfakefullscreen && c == selmon->sel) { + } else if (c->ismaxmizescreen && c == selmon->sel) { for (i = 0; i < 4; i++) - wlr_scene_rect_set_color(c->border[i], fakefullscreencolor); + wlr_scene_rect_set_color(c->border[i], maxmizescreencolor); } else if (c == selmon->sel) { for (i = 0; i < 4; i++) wlr_scene_rect_set_color(c->border[i], focuscolor); @@ -3649,7 +3659,7 @@ void exchange_two_client(Client *c1, Client *c2) { void exchange_client(const Arg *arg) { Client *c = selmon->sel; - if (!c || c->isfloating || c->isfullscreen || c->isfakefullscreen) + if (!c || c->isfloating || c->isfullscreen || c->ismaxmizescreen) return; exchange_two_client(c, direction_select(arg)); } @@ -3664,7 +3674,9 @@ int is_special_animaiton_rule(Client *c) { } } - if (visible_client_number < 2 && !c->isfloating) { + if (strcmp(selmon->lt[selmon->sellt]->name , "scroller") == 0) { + return DOWN; + } else if (visible_client_number < 2 && !c->isfloating) { return DOWN; } else if (visible_client_number == 2 && !c->isfloating && !new_is_master) { return RIGHT; @@ -3747,19 +3759,24 @@ void resize(Client *c, struct wlr_box geo, int interact) { if (!c || !c->mon || !client_surface(c)->mapped) return; - struct wlr_box *bbox, oldgeom; + struct wlr_box *bbox; // struct wlr_box clip; if (!c->mon) return; - oldgeom = c->geom; + // oldgeom = c->geom; bbox = interact ? &sgeom : &c->mon->w; - client_set_bounds( - c, geo.width, - geo.height); // 去掉这个推荐的窗口大小,因为有时推荐的窗口特别大导致平铺异常 - c->geom = geo; - applybounds( - c, bbox); // 去掉这个推荐的窗口大小,因为有时推荐的窗口特别大导致平铺异常 + + if(strcmp(c->mon->lt[c->mon->sellt]->name , "scroller") == 0) { + c->geom = geo; + } else { // 这里会限制不允许窗口划出屏幕 + client_set_bounds( + c, geo.width, + geo.height); // 去掉这个推荐的窗口大小,因为有时推荐的窗口特别大导致平铺异常 + c->geom = geo; + applybounds( + c, bbox); // 去掉这个推荐的窗口大小,因为有时推荐的窗口特别大导致平铺异常 + } if (!c->is_open_animation) { c->animation.begin_fade_in = false; @@ -3780,9 +3797,9 @@ void resize(Client *c, struct wlr_box geo, int interact) { if (c->animation.tagouting) { c->animainit_geom = c->geom; } else if (c->animation.tagining) { - c->animainit_geom.height = oldgeom.height; - c->animainit_geom.width = oldgeom.width; - c->animainit_geom.y = oldgeom.y; + c->animainit_geom.height = c->animation.current.height; + c->animainit_geom.width = c->animation.current.width; + c->animainit_geom.y = c->animation.current.y; } else if (c->is_open_animation) { set_open_animaiton(c, c->geom); } else { @@ -3928,20 +3945,20 @@ setfloating(Client *c, int floating) { printstatus(); } -void setfakefullscreen(Client *c, int fakefullscreen) { - struct wlr_box fakefullscreen_box; +void setmaxmizescreen(Client *c, int maxmizescreen) { + struct wlr_box maxmizescreen_box; if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) return; - c->isfakefullscreen = fakefullscreen; + c->ismaxmizescreen = maxmizescreen; // c->bw = fullscreen ? 0 : borderpx; - // client_set_fullscreen(c, fakefullscreen); - wlr_scene_node_reparent(&c->scene->node, layers[fakefullscreen ? LyrTile + // client_set_fullscreen(c, maxmizescreen); + wlr_scene_node_reparent(&c->scene->node, layers[maxmizescreen ? LyrTile : c->isfloating ? LyrFloat : LyrTile]); - if (fakefullscreen) { + if (maxmizescreen) { if (c->isfloating) c->oldgeom = c->geom; if (selmon->isoverview) { @@ -3950,20 +3967,20 @@ void setfakefullscreen(Client *c, int fakefullscreen) { } c->prev = c->geom; - fakefullscreen_box.x = c->mon->w.x + gappov; - fakefullscreen_box.y = c->mon->w.y + gappoh; - fakefullscreen_box.width = c->mon->w.width - 2 * gappov; - fakefullscreen_box.height = c->mon->w.height - 2 * gappov; + maxmizescreen_box.x = c->mon->w.x + gappov; + maxmizescreen_box.y = c->mon->w.y + gappoh; + maxmizescreen_box.width = c->mon->w.width - 2 * gappov; + maxmizescreen_box.height = c->mon->w.height - 2 * gappov; wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 - resize(c, fakefullscreen_box, 0); - c->isfakefullscreen = 1; + resize(c, maxmizescreen_box, 0); + c->ismaxmizescreen = 1; // c->isfloating = 0; } else { /* restore previous size instead of arrange for floating windows since * client positions are set by the user and cannot be recalculated */ // resize(c, c->prev, 0); c->bw = borderpx; - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; c->isfullscreen = 0; client_set_fullscreen(c, false); if (c->isfloating) @@ -4004,7 +4021,7 @@ void setfullscreen(Client *c, int fullscreen) // 用自定义全屏代理自带 c->bw = borderpx; c->isfullscreen = 0; c->isfullscreen = 0; - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; if (c->isfloating) setfloating(c, 1); arrange(c->mon, false); @@ -4564,6 +4581,93 @@ void grid(Monitor *m, unsigned int gappo, unsigned int gappi) { } } +// // 网格布局窗口大小和位置计算 +void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) { + unsigned int i, n; + + Client *c,*root_client; + Client *tempClients[100]; + n = 0; + struct wlr_box target_geom; + int focus_client_index = 0; + bool need_scroller = false; + + unsigned int max_client_width = m->w.width - 2 * scroller_structs - gappih; + + wl_list_for_each(c, &clients, + link) if (VISIBLEON(c, c->mon) && !c->isfloating && !c->iskilling && + !c->animation.tagouting && c->mon == selmon) { + tempClients[n] = c; + n++; + } + tempClients[n] = NULL; + if (n == 0) + return; + + if (n == 1) { + c = tempClients[0]; + target_geom.height = m->w.height - 2 * gappov; + target_geom.width = max_client_width * c->scroller_proportion; + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + resizeclient(c,target_geom.x,target_geom.y,target_geom.width,target_geom.height,0); + return; + } + + if(selmon->sel && selmon->sel->istiled ) { + root_client = selmon->sel; + } else if(selmon->prevsel && selmon->prevsel->istiled ) { + root_client = selmon->prevsel; + } else { + return; + } + + for (i = 0;tempClients[i]; i++) { + c = tempClients[i]; + if (root_client == c) { + if(selmon->prevsel != NULL && (c->geom.x - m->w.x - scroller_structs) > 0 && + c->geom.x + c->geom.width < m->w.x + m->w.width - scroller_structs) { + need_scroller = false; + }else { + need_scroller = true; + } + focus_client_index = i; + break; + } + } + + target_geom.height = m->w.height - 2 * gappov; + target_geom.width = max_client_width* c->scroller_proportion; + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + + if(need_scroller) { + if (scoller_foucs_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; + + } else { + target_geom.x = root_client->geom.x > m->w.x + (m->w.width)/2 ? + m->w.x + (m->w.width - root_client->scroller_proportion*max_client_width -scroller_structs) : + m->w.x + scroller_structs; + } + resize(tempClients[focus_client_index], target_geom, 0); + } else { + target_geom.x = c->geom.x; + resize(tempClients[focus_client_index], target_geom, 0); + } + for (i = 1; i <= focus_client_index; i++) { + c = tempClients[focus_client_index - i]; + target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - gappih - target_geom.width; + resize(c, target_geom, 0); + } + for (i = 1; tempClients[focus_client_index + i]; i++) { + c = tempClients[focus_client_index + i]; + target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + gappih + tempClients[focus_client_index + i - 1]->geom.width; + resize(c, target_geom, 0); + } +} + // 目标窗口有其他窗口和它同个tag就返回0 unsigned int want_restore_fullscreen(Client *target_client) { Client *c = NULL; @@ -4581,7 +4685,7 @@ unsigned int want_restore_fullscreen(Client *target_client) { void overview_backup(Client *c) { c->overview_isfloatingbak = c->isfloating; c->overview_isfullscreenbak = c->isfullscreen; - c->overview_isfakefullscreenbak = c->isfakefullscreen; + c->overview_ismaxmizescreenbak = c->ismaxmizescreen; c->overview_isfullscreenbak = c->isfullscreen; c->overview_backup_x = c->geom.x; c->overview_backup_y = c->geom.y; @@ -4591,13 +4695,13 @@ void overview_backup(Client *c) { if (c->isfloating) { c->isfloating = 0; } - if (c->isfullscreen || c->isfakefullscreen) { + if (c->isfullscreen || c->ismaxmizescreen) { // if (c->bw == 0) { // 真全屏窗口清除x11全屏属性 // XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, // PropModeReplace, (unsigned char *)0, 0); // } c->isfullscreen = 0; // 清除窗口全屏标志 - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; } c->bw = borderpx; // 恢复非全屏的border } @@ -4606,24 +4710,24 @@ void overview_backup(Client *c) { void overview_restore(Client *c, const Arg *arg) { c->isfloating = c->overview_isfloatingbak; c->isfullscreen = c->overview_isfullscreenbak; - c->isfakefullscreen = c->overview_isfakefullscreenbak; + c->ismaxmizescreen = c->overview_ismaxmizescreenbak; c->overview_isfloatingbak = 0; c->overview_isfullscreenbak = 0; - c->overview_isfakefullscreenbak = 0; + c->overview_ismaxmizescreenbak = 0; c->bw = c->overview_backup_bw; c->is_restoring_from_ov = (arg->ui & c->tags & TAGMASK) == 0 ? true : false; if (c->isfloating) { // XRaiseWindow(dpy, c->win); // 提升悬浮窗口到顶层 resizeclient(c, c->overview_backup_x, c->overview_backup_y, c->overview_backup_w, c->overview_backup_h, 1); - } else if (c->isfullscreen || c->isfakefullscreen) { + } else if (c->isfullscreen || c->ismaxmizescreen) { if (want_restore_fullscreen( c)) { // 如果同tag有其他窗口,且其他窗口是将要聚焦的,那么不恢复该窗口的全屏状态 resizeclient(c, c->overview_backup_x, c->overview_backup_y, c->overview_backup_w, c->overview_backup_h, 1); } else { c->isfullscreen = 0; - c->isfakefullscreen = 0; + c->ismaxmizescreen = 0; client_set_fullscreen(c, false); } } else { @@ -4640,6 +4744,49 @@ void overview_restore(Client *c, const Arg *arg) { } } +void switch_proportion_preset(const Arg *arg) { + float target_proportion = 0; + + if(LENGTH(scroller_proportion_preset) == 0) { + return; + } + + if (selmon->sel) { + + for (int i = 0; i < LENGTH(scroller_proportion_preset); i++) { + if (scroller_proportion_preset[i] == selmon->sel->scroller_proportion) { + if(i == LENGTH(scroller_proportion_preset) -1) { + target_proportion = scroller_proportion_preset[0]; + break; + } else { + target_proportion = scroller_proportion_preset[i+1]; + break; + } + } + } + + if (target_proportion == 0) { + target_proportion = scroller_proportion_preset[0]; + } + + unsigned int max_client_width = selmon->w.width - 2 * scroller_structs - gappih; + selmon->sel->scroller_proportion = target_proportion; + selmon->sel->geom.width = max_client_width * target_proportion; + // resize(selmon->sel, selmon->sel->geom, 0); + arrange(selmon, false); + } +} + +void set_proportion(const Arg *arg) { + if (selmon->sel) { + unsigned int max_client_width = selmon->w.width - 2 * scroller_structs - gappih; + selmon->sel->scroller_proportion = arg->f; + selmon->sel->geom.width = max_client_width * arg->f; + // resize(selmon->sel, selmon->sel->geom, 0); + arrange(selmon, false); + } +} + // 显示所有tag 或 跳转到聚焦窗口的tag void toggleoverview(const Arg *arg) { @@ -4684,7 +4831,7 @@ void toggleoverview(const Arg *arg) { wl_list_for_each(c, &clients, link) { if (c && (c != selmon->sel || c->overview_isfloatingbak || - c->overview_isfullscreenbak || c->overview_isfakefullscreenbak) && + c->overview_isfullscreenbak || c->overview_ismaxmizescreenbak) && !c->iskilling && client_surface(c)->mapped) overview_restore(c, &(Arg){.ui = target}); } @@ -4705,7 +4852,7 @@ void tile(Monitor *m, unsigned int gappo, unsigned int uappi) { wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && !c->animation.tagouting && !c->iskilling && !c->isfloating && - !c->isfullscreen && !c->isfakefullscreen) n++; + !c->isfullscreen && !c->ismaxmizescreen) n++; if (n == 0) return; @@ -4724,7 +4871,7 @@ void tile(Monitor *m, unsigned int gappo, unsigned int uappi) { my = ty = m->gappoh * oe; wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || c->iskilling || c->animation.tagouting || - c->isfloating || c->isfullscreen || c->isfakefullscreen) + c->isfloating || c->isfullscreen || c->ismaxmizescreen) continue; if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) { r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i; @@ -4757,9 +4904,9 @@ void togglefloating(const Arg *arg) { if (!sel) return; - if (sel->isfullscreen || sel->isfakefullscreen) { + if (sel->isfullscreen || sel->ismaxmizescreen) { sel->isfullscreen = 0; // 清除窗口全屏标志 - sel->isfakefullscreen = 0; + sel->ismaxmizescreen = 0; sel->bw = borderpx; // 恢复非全屏的border } /* return if fullscreen */ @@ -4775,7 +4922,7 @@ void togglefullscreen(const Arg *arg) { // if(sel->isfloating) // setfloating(sel, 0); - if (sel->isfullscreen || sel->isfakefullscreen) + if (sel->isfullscreen || sel->ismaxmizescreen) setfullscreen(sel, 0); else setfullscreen(sel, 1); @@ -4784,7 +4931,7 @@ void togglefullscreen(const Arg *arg) { sel->is_in_scratchpad = 0; } -void togglefakefullscreen(const Arg *arg) { +void togglemaxmizescreen(const Arg *arg) { Client *sel = focustop(selmon); if (!sel) return; @@ -4792,10 +4939,10 @@ void togglefakefullscreen(const Arg *arg) { // if(sel->isfloating) // setfloating(sel, 0); - if (sel->isfullscreen || sel->isfakefullscreen) - setfakefullscreen(sel, 0); + if (sel->isfullscreen || sel->ismaxmizescreen) + setmaxmizescreen(sel, 0); else - setfakefullscreen(sel, 1); + setmaxmizescreen(sel, 1); sel->is_scratchpad_show = 0; sel->is_in_scratchpad = 0; @@ -4864,6 +5011,9 @@ void unmapnotify(struct wl_listener *listener, void *data) { grabc = NULL; } + if (c == selmon->prevsel) + selmon->prevsel = NULL; + if (c == selmon->sel) { selmon->sel = NULL; Client *nextfocus = focustop(selmon);