mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-06 06:46:54 -04:00
feat: add rect indicator for drag tile to tile
This commit is contained in:
parent
7a950f54df
commit
9a00d8ce09
5 changed files with 189 additions and 49 deletions
|
|
@ -98,6 +98,7 @@ scratchpad_height_ratio=0.9
|
|||
borderpx=4
|
||||
rootcolor=0x201b14ff
|
||||
bordercolor=0x444444ff
|
||||
dropcolor=0x8FBA7C55
|
||||
focuscolor=0xc9b890ff
|
||||
maximizescreencolor=0x89aa61ff
|
||||
urgentcolor=0xad401fff
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ rootcolor=0x323232ff
|
|||
# Inactive window border
|
||||
bordercolor=0x444444ff
|
||||
|
||||
# Drop shadow when dragging windows
|
||||
dropcolor=0x8FBA7C55
|
||||
|
||||
# Active window border
|
||||
focuscolor=0xc66b25ff
|
||||
|
||||
|
|
|
|||
|
|
@ -404,6 +404,90 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
|||
return offset;
|
||||
}
|
||||
|
||||
void client_set_drop_area(Client *c) {
|
||||
|
||||
bool first_draw = false;
|
||||
int32_t drop_direction = UNDIR;
|
||||
|
||||
if (!c->enable_drop_area_draw && !c->droparea->node.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c->enable_drop_area_draw && c->droparea->node.enabled) {
|
||||
wlr_scene_node_lower_to_bottom(&c->droparea->node);
|
||||
wlr_scene_node_set_enabled(&c->droparea->node, false);
|
||||
return;
|
||||
} else if (c->enable_drop_area_draw && !c->droparea->node.enabled) {
|
||||
wlr_scene_node_raise_to_top(&c->droparea->node);
|
||||
wlr_scene_node_set_enabled(&c->droparea->node, true);
|
||||
first_draw = true;
|
||||
}
|
||||
|
||||
int32_t bw = (int32_t)c->bw;
|
||||
int32_t client_width = c->geom.width - 2 * bw;
|
||||
int32_t client_height = c->geom.height - 2 * bw;
|
||||
|
||||
// 光标在窗口客户区内的相对坐标
|
||||
double rel_x = cursor->x - c->geom.x - bw;
|
||||
double rel_y = cursor->y - c->geom.y - bw;
|
||||
|
||||
struct wlr_box drop_box;
|
||||
|
||||
// 左边缘:x 在 0~30% 客户区宽度,且 y 在 30%~70% 客户区高度
|
||||
if (rel_x < client_width * 0.3 && rel_y > client_height * 0.3 &&
|
||||
rel_y < client_height * 0.7) {
|
||||
drop_box.x = bw;
|
||||
drop_box.y = bw;
|
||||
drop_box.width = client_width * 0.3;
|
||||
drop_box.height = client_height;
|
||||
drop_direction = LEFT;
|
||||
}
|
||||
// 右边缘:x 在 70%~100% 客户区宽度,且 y 在 30%~70% 客户区高度
|
||||
else if (rel_x > client_width * 0.7 && rel_y > client_height * 0.3 &&
|
||||
rel_y < client_height * 0.7) {
|
||||
drop_box.x = bw + client_width * 0.7;
|
||||
drop_box.y = bw;
|
||||
drop_box.width = client_width * 0.3;
|
||||
drop_box.height = client_height;
|
||||
drop_direction = RIGHT;
|
||||
}
|
||||
// 上边缘:x 在 30%~70% 客户区宽度,且 y 在 0~30% 客户区高度
|
||||
else if (rel_x > client_width * 0.3 && rel_x < client_width * 0.7 &&
|
||||
rel_y < client_height * 0.3) {
|
||||
drop_box.x = bw;
|
||||
drop_box.y = bw;
|
||||
drop_box.width = client_width;
|
||||
drop_box.height = client_height * 0.3;
|
||||
drop_direction = UP;
|
||||
}
|
||||
// 下边缘:x 在 30%~70% 客户区宽度,且 y 在 70%~100% 客户区高度
|
||||
else if (rel_x > client_width * 0.3 && rel_x < client_width * 0.7 &&
|
||||
rel_y > client_height * 0.7) {
|
||||
drop_box.x = bw;
|
||||
drop_box.y = bw + client_height * 0.7;
|
||||
drop_box.width = client_width;
|
||||
drop_box.height = client_height * 0.3;
|
||||
drop_direction = DOWN;
|
||||
}
|
||||
// 中心(或其他角落):显示在中间区域
|
||||
else {
|
||||
drop_box.x = bw + client_width * 0.3;
|
||||
drop_box.y = bw + client_height * 0.3;
|
||||
drop_box.width = client_width * 0.4;
|
||||
drop_box.height = client_height * 0.4;
|
||||
drop_direction = UNDIR;
|
||||
}
|
||||
|
||||
if (!first_draw && c->drop_direction == drop_direction) {
|
||||
return;
|
||||
} else {
|
||||
c->drop_direction = drop_direction;
|
||||
}
|
||||
|
||||
wlr_scene_node_set_position(&c->droparea->node, drop_box.x, drop_box.y);
|
||||
wlr_scene_rect_set_size(c->droparea, drop_box.width, drop_box.height);
|
||||
}
|
||||
|
||||
void client_apply_clip(Client *c, float factor) {
|
||||
|
||||
if (c->iskilling || !client_surface(c)->mapped)
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ typedef struct {
|
|||
float scratchpad_height_ratio;
|
||||
float rootcolor[4];
|
||||
float bordercolor[4];
|
||||
float dropcolor[4];
|
||||
float focuscolor[4];
|
||||
float maximizescreencolor[4];
|
||||
float urgentcolor[4];
|
||||
|
|
@ -1672,6 +1673,17 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
} else {
|
||||
convert_hex_to_rgba(config->bordercolor, color);
|
||||
}
|
||||
} else if (strcmp(key, "dropcolor") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid dropcolor "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->dropcolor, color);
|
||||
}
|
||||
} else if (strcmp(key, "focuscolor") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
|
|
@ -3310,6 +3322,10 @@ void set_value_default() {
|
|||
config.bordercolor[1] = 0x44 / 255.0f;
|
||||
config.bordercolor[2] = 0x44 / 255.0f;
|
||||
config.bordercolor[3] = 1.0f;
|
||||
config.dropcolor[0] = 0x8f / 255.0f;
|
||||
config.dropcolor[1] = 0xba / 255.0f;
|
||||
config.dropcolor[2] = 0x7c / 255.0f;
|
||||
config.dropcolor[3] = 0.5f;
|
||||
config.focuscolor[0] = 0xc6 / 255.0f;
|
||||
config.focuscolor[1] = 0x6b / 255.0f;
|
||||
config.focuscolor[2] = 0x25 / 255.0f;
|
||||
|
|
|
|||
134
src/mango.c
134
src/mango.c
|
|
@ -311,6 +311,7 @@ struct Client {
|
|||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
struct wlr_scene_rect *shield;
|
||||
struct wlr_scene_rect *droparea;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
|
||||
struct wlr_scene_tree *image_capture_tree;
|
||||
|
|
@ -422,6 +423,8 @@ struct Client {
|
|||
bool isfocusing;
|
||||
struct Client *next_in_stack;
|
||||
struct Client *prev_in_stack;
|
||||
bool enable_drop_area_draw;
|
||||
int32_t drop_direction;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -886,7 +889,7 @@ static KeyboardGroup *kb_group;
|
|||
static struct wl_list inputdevices;
|
||||
static struct wl_list keyboard_shortcut_inhibitors;
|
||||
static uint32_t cursor_mode;
|
||||
static Client *grabc;
|
||||
static Client *grabc, *dropc;
|
||||
static int32_t rzcorner;
|
||||
static int32_t grabcx, grabcy; /* client-relative */
|
||||
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
||||
|
|
@ -2141,49 +2144,41 @@ void scroller_insert_stack(Client *c, Client *target_client,
|
|||
}
|
||||
|
||||
void try_scroller_drop(Client *c, Client *closest, int vertical) {
|
||||
double ratio_main, ratio_cross;
|
||||
int32_t main_pos, cross_pos;
|
||||
int32_t main_size, cross_size;
|
||||
Client *stack_head = NULL;
|
||||
|
||||
Client *stack_head = get_scroll_stack_head(closest);
|
||||
|
||||
if (vertical) {
|
||||
main_pos = cursor->y;
|
||||
cross_pos = cursor->x;
|
||||
main_size = closest->geom.height;
|
||||
cross_size = closest->geom.width;
|
||||
} else {
|
||||
main_pos = cursor->x;
|
||||
cross_pos = cursor->y;
|
||||
main_size = closest->geom.width;
|
||||
cross_size = closest->geom.height;
|
||||
}
|
||||
|
||||
ratio_main =
|
||||
(double)(main_pos - (vertical ? closest->geom.y : closest->geom.x)) /
|
||||
main_size;
|
||||
ratio_cross =
|
||||
(double)(cross_pos - (vertical ? closest->geom.x : closest->geom.y)) /
|
||||
cross_size;
|
||||
|
||||
if (ratio_main > 0.3 && ratio_main < 0.7 &&
|
||||
(ratio_cross < 0.3 || ratio_cross > 0.7)) {
|
||||
setfloating(c, 0);
|
||||
if (ratio_cross < 0.3) {
|
||||
if (closest->drop_direction == LEFT) {
|
||||
setfloating(c, 0);
|
||||
scroller_insert_stack(c, closest, true);
|
||||
} else {
|
||||
return;
|
||||
} else if (closest->drop_direction == RIGHT) {
|
||||
setfloating(c, 0);
|
||||
scroller_insert_stack(c, closest, false);
|
||||
return;
|
||||
} else if (closest->drop_direction == UP) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
} else if (closest->drop_direction == DOWN) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_head->link, &c->link);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
stack_head = get_scroll_stack_head(closest);
|
||||
|
||||
if (ratio_main < 0.3) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
} else {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_head->link, &c->link);
|
||||
if (closest->drop_direction == UP) {
|
||||
setfloating(c, 0);
|
||||
scroller_insert_stack(c, closest, true);
|
||||
return;
|
||||
} else if (closest->drop_direction == DOWN) {
|
||||
setfloating(c, 0);
|
||||
scroller_insert_stack(c, closest, false);
|
||||
return;
|
||||
} else if (closest->drop_direction == LEFT) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
} else if (closest->drop_direction == RIGHT) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_head->link, &c->link);
|
||||
}
|
||||
}
|
||||
|
||||
setfloating(c, 0);
|
||||
|
|
@ -2196,22 +2191,27 @@ void place_drag_tile_client(Client *c) {
|
|||
const Layout *layout =
|
||||
closest->mon->pertag->ltidxs[closest->mon->pertag->curtag];
|
||||
|
||||
if (layout) {
|
||||
if (layout->id == SCROLLER) {
|
||||
try_scroller_drop(c, closest, 0);
|
||||
return;
|
||||
}
|
||||
if (layout->id == VERTICAL_SCROLLER) {
|
||||
try_scroller_drop(c, closest, 1);
|
||||
return;
|
||||
}
|
||||
if (closest->drop_direction == UNDIR) {
|
||||
exchange_two_client(c, closest);
|
||||
setfloating(c, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (closest->link.prev != &c->link) {
|
||||
if (layout->id == SCROLLER) {
|
||||
try_scroller_drop(c, closest, 0);
|
||||
return;
|
||||
}
|
||||
if (layout->id == VERTICAL_SCROLLER) {
|
||||
try_scroller_drop(c, closest, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (closest->drop_direction == LEFT || closest->drop_direction == UP) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(closest->link.prev, &c->link);
|
||||
} else {
|
||||
exchange_two_client(c, closest);
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&closest->link, &c->link);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2336,6 +2336,11 @@ buttonpress(struct wl_listener *listener, void *data) {
|
|||
apply_window_snap(tmpc);
|
||||
}
|
||||
tmpc->drag_to_tile = false;
|
||||
if (dropc) {
|
||||
dropc->enable_drop_area_draw = false;
|
||||
client_set_drop_area(dropc);
|
||||
dropc = NULL;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
cursor_mode = CurNormal;
|
||||
|
|
@ -4107,6 +4112,8 @@ void locksession(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void init_client_properties(Client *c) {
|
||||
c->drop_direction = UNDIR;
|
||||
c->enable_drop_area_draw = false;
|
||||
c->isfocusing = false;
|
||||
c->isfloating = 0;
|
||||
c->isfakefullscreen = 0;
|
||||
|
|
@ -4268,6 +4275,12 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
: config.bordercolor);
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
// extra node
|
||||
|
||||
c->droparea = wlr_scene_rect_create(c->scene, 0, 0, config.dropcolor);
|
||||
wlr_scene_node_lower_to_bottom(&c->droparea->node);
|
||||
wlr_scene_node_set_position(&c->droparea->node, 0, 0);
|
||||
wlr_scene_node_set_enabled(&c->droparea->node, false);
|
||||
|
||||
c->shield = wlr_scene_rect_create(c->scene_surface, 0, 0,
|
||||
(float[4]){0, 0, 0, 0xff});
|
||||
|
|
@ -4446,6 +4459,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
|||
double dy, double dx_unaccel, double dy_unaccel) {
|
||||
double sx = 0, sy = 0, sx_confined, sy_confined;
|
||||
Client *c = NULL, *w = NULL;
|
||||
Client *closet_drop_client = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct wlr_pointer_constraint_v1 *constraint;
|
||||
|
|
@ -4517,6 +4531,24 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
|||
.y = (int32_t)round(cursor->y) - grabcy,
|
||||
.width = grabc->geom.width,
|
||||
.height = grabc->geom.height};
|
||||
if (config.drag_tile_to_tile && grabc->drag_to_tile) {
|
||||
closet_drop_client = find_closest_tiled_client(grabc);
|
||||
if (closet_drop_client && dropc && closet_drop_client != dropc) {
|
||||
dropc->enable_drop_area_draw = false;
|
||||
client_set_drop_area(dropc);
|
||||
dropc = closet_drop_client;
|
||||
dropc->enable_drop_area_draw = true;
|
||||
client_set_drop_area(dropc);
|
||||
} else if (closet_drop_client) {
|
||||
dropc = closet_drop_client;
|
||||
dropc->enable_drop_area_draw = true;
|
||||
client_set_drop_area(dropc);
|
||||
} else if (dropc) {
|
||||
dropc->enable_drop_area_draw = false;
|
||||
client_set_drop_area(dropc);
|
||||
dropc = NULL;
|
||||
}
|
||||
}
|
||||
resize(grabc, grabc->float_geom, 1);
|
||||
return;
|
||||
} else if (cursor_mode == CurResize) {
|
||||
|
|
@ -6217,6 +6249,10 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
grabc = NULL;
|
||||
}
|
||||
|
||||
if (c == dropc) {
|
||||
dropc = NULL;
|
||||
}
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (!m->wlr_output->enabled) {
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue