opt: format code

fix: correct version message
This commit is contained in:
DreamMaoMao
2025-02-17 13:37:59 +08:00
parent 8ef33dacc0
commit 6287b292fe
7 changed files with 1958 additions and 1918 deletions

255
IM.h
View File

@@ -1,7 +1,7 @@
#ifdef IM #ifdef IM
#include <assert.h> #include <assert.h>
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_input_method_v2.h> #include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_text_input_v3.h>
/** /**
* The relay structure manages the relationship between text-input and * The relay structure manages the relationship between text-input and
@@ -53,7 +53,6 @@ struct dwl_text_input {
struct wl_listener text_input_destroy; struct wl_listener text_input_destroy;
}; };
struct dwl_input_popup { struct dwl_input_popup {
struct dwl_input_method_relay *relay; struct dwl_input_method_relay *relay;
struct wlr_input_popup_surface_v2 *popup_surface; struct wlr_input_popup_surface_v2 *popup_surface;
@@ -66,7 +65,6 @@ struct dwl_input_popup {
int x, y; int x, y;
bool visible; bool visible;
struct wl_listener popup_map; struct wl_listener popup_map;
struct wl_listener popup_unmap; struct wl_listener popup_unmap;
struct wl_listener popup_destroy; struct wl_listener popup_destroy;
@@ -74,7 +72,6 @@ struct dwl_input_popup {
// struct wl_listener focused_surface_unmap; // struct wl_listener focused_surface_unmap;
}; };
void dwl_input_method_relay_init(struct dwl_input_method_relay *relay); void dwl_input_method_relay_init(struct dwl_input_method_relay *relay);
// Updates currently focused surface. Surface must belong to the same // Updates currently focused surface. Surface must belong to the same
// seat. // seat.
@@ -98,21 +95,26 @@ struct dwl_input_method_relay *input_relay;
* or if event is from virtual keyboard of the same client as grab. * or if event is from virtual keyboard of the same client as grab.
* TODO: see https://github.com/swaywm/wlroots/issues/2322 * TODO: see https://github.com/swaywm/wlroots/issues/2322
*/ */
static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(Keyboard* kb) { static struct wlr_input_method_keyboard_grab_v2 *
keyboard_get_im_grab(Keyboard *kb) {
struct wlr_input_method_v2 *input_method = input_relay->input_method; struct wlr_input_method_v2 *input_method = input_relay->input_method;
struct wlr_virtual_keyboard_v1 *virtual_keyboard = struct wlr_virtual_keyboard_v1 *virtual_keyboard =
wlr_input_device_get_virtual_keyboard(&kb->wlr_keyboard->base); wlr_input_device_get_virtual_keyboard(&kb->wlr_keyboard->base);
if (!input_method || !input_method->keyboard_grab || (virtual_keyboard && if (!input_method || !input_method->keyboard_grab ||
(virtual_keyboard &&
wl_resource_get_client(virtual_keyboard->resource) == wl_resource_get_client(virtual_keyboard->resource) ==
wl_resource_get_client(input_method->keyboard_grab->resource))) { wl_resource_get_client(input_method->keyboard_grab->resource))) {
if (!input_method) { if (!input_method) {
wlr_log(WLR_DEBUG, "keypress keyboard_get_im_grab return NULL:no input_method"); wlr_log(WLR_DEBUG,
"keypress keyboard_get_im_grab return NULL:no input_method");
} else if (!input_method->keyboard_grab) { } else if (!input_method->keyboard_grab) {
wlr_log(WLR_DEBUG, "keypress keyboard_get_im_grab return NULL:no input_method->keyboard_grab"); wlr_log(WLR_DEBUG, "keypress keyboard_get_im_grab return NULL:no "
"input_method->keyboard_grab");
} }
if (virtual_keyboard) { if (virtual_keyboard) {
wlr_log(WLR_DEBUG, "keypress keyboard_get_im_grab return NULL:virtual_keyboard"); wlr_log(WLR_DEBUG,
"keypress keyboard_get_im_grab return NULL:virtual_keyboard");
} }
return NULL; return NULL;
@@ -121,31 +123,33 @@ static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(Keyboard*
} }
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) { static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
input_method_grab_keyboard); wl_container_of(listener, relay, input_method_grab_keyboard);
//wl_container_of 宏的第二个参数sample, 这里是relay,无须是已经初始化的变量,只要是返回值类型的变量就可以了,这里就是dwl_input_method_relay类型的变量 // wl_container_of 宏的第二个参数sample,
// 这里是relay,无须是已经初始化的变量,只要是返回值类型的变量就可以了,这里就是dwl_input_method_relay类型的变量
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
// send modifier state to grab // send modifier state to grab
struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(seat); struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(seat);
if (active_keyboard) { if (active_keyboard) {
wlr_log(WLR_INFO, "im_grab_keyboard"); wlr_log(WLR_INFO, "im_grab_keyboard");
wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,active_keyboard); wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, &active_keyboard->modifiers); active_keyboard);
} wlr_input_method_keyboard_grab_v2_send_modifiers(
else keyboard_grab, &active_keyboard->modifiers);
} else
wlr_log(WLR_INFO, "im_grab_keyboard but no active keyboard"); wlr_log(WLR_INFO, "im_grab_keyboard but no active keyboard");
wl_signal_add(&keyboard_grab->events.destroy, wl_signal_add(&keyboard_grab->events.destroy,
&relay->input_method_keyboard_grab_destroy); &relay->input_method_keyboard_grab_destroy);
relay->input_method_keyboard_grab_destroy.notify = relay->input_method_keyboard_grab_destroy.notify =
handle_im_keyboard_grab_destroy; handle_im_keyboard_grab_destroy;
} }
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) { static void handle_im_keyboard_grab_destroy(struct wl_listener *listener,
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, void *data) {
input_method_keyboard_grab_destroy); struct dwl_input_method_relay *relay =
wl_container_of(listener, relay, input_method_keyboard_grab_destroy);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
wlr_log(WLR_DEBUG, "im_keyboard_grab_destroy"); wlr_log(WLR_DEBUG, "im_keyboard_grab_destroy");
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link); wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
@@ -156,9 +160,8 @@ static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *
} }
} }
static struct dwl_text_input *
static struct dwl_text_input *relay_get_focusable_text_input( relay_get_focusable_text_input(struct dwl_input_method_relay *relay) {
struct dwl_input_method_relay *relay) {
struct dwl_text_input *text_input = NULL; struct dwl_text_input *text_input = NULL;
wl_list_for_each(text_input, &relay->text_inputs, link) { wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->pending_focused_surface) { if (text_input->pending_focused_surface) {
@@ -168,8 +171,8 @@ static struct dwl_text_input *relay_get_focusable_text_input(
return NULL; return NULL;
} }
static struct dwl_text_input *relay_get_focused_text_input( static struct dwl_text_input *
struct dwl_input_method_relay *relay) { relay_get_focused_text_input(struct dwl_input_method_relay *relay) {
struct dwl_text_input *text_input = NULL; struct dwl_text_input *text_input = NULL;
wl_list_for_each(text_input, &relay->text_inputs, link) { wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->input->focused_surface) { if (text_input->input->focused_surface) {
@@ -182,8 +185,8 @@ static struct dwl_text_input *relay_get_focused_text_input(
static void handle_im_commit(struct wl_listener *listener, void *data) { static void handle_im_commit(struct wl_listener *listener, void *data) {
struct wlr_input_method_v2 *context; struct wlr_input_method_v2 *context;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
input_method_commit); wl_container_of(listener, relay, input_method_commit);
struct dwl_text_input *text_input = relay_get_focused_text_input(relay); struct dwl_text_input *text_input = relay_get_focused_text_input(relay);
if (!text_input) { if (!text_input) {
@@ -204,17 +207,18 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
context->current.commit_text); context->current.commit_text);
wlr_log(WLR_DEBUG, "commit_text: %s", context->current.commit_text); wlr_log(WLR_DEBUG, "commit_text: %s", context->current.commit_text);
} }
if (context->current.delete.before_length if (context->current.delete.before_length ||
|| context->current.delete.after_length) { context->current.delete.after_length) {
wlr_text_input_v3_send_delete_surrounding_text(text_input->input, wlr_text_input_v3_send_delete_surrounding_text(
context->current.delete.before_length, text_input->input, context->current.delete.before_length,
context->current.delete.after_length); context->current.delete.after_length);
} }
wlr_text_input_v3_send_done(text_input->input); wlr_text_input_v3_send_done(text_input->input);
} }
static void text_input_set_pending_focused_surface( static void
struct dwl_text_input *text_input, struct wlr_surface *surface) { text_input_set_pending_focused_surface(struct dwl_text_input *text_input,
struct wlr_surface *surface) {
wl_list_remove(&text_input->pending_focused_surface_destroy.link); wl_list_remove(&text_input->pending_focused_surface_destroy.link);
text_input->pending_focused_surface = surface; text_input->pending_focused_surface = surface;
@@ -229,8 +233,8 @@ static void text_input_set_pending_focused_surface(
static void handle_im_destroy(struct wl_listener *listener, void *data) { static void handle_im_destroy(struct wl_listener *listener, void *data) {
struct dwl_text_input *text_input; struct dwl_text_input *text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
input_method_destroy); wl_container_of(listener, relay, input_method_destroy);
struct wlr_input_method_v2 *context = data; struct wlr_input_method_v2 *context = data;
wlr_log(WLR_INFO, "IM destroy"); wlr_log(WLR_INFO, "IM destroy");
assert(context == relay->input_method); assert(context == relay->input_method);
@@ -254,20 +258,21 @@ static void relay_send_im_state(struct dwl_input_method_relay *relay,
return; return;
} }
// TODO: only send each of those if they were modified // TODO: only send each of those if they were modified
wlr_input_method_v2_send_surrounding_text(input_method, wlr_input_method_v2_send_surrounding_text(
input->current.surrounding.text, input->current.surrounding.cursor, input_method, input->current.surrounding.text,
input->current.surrounding.anchor); input->current.surrounding.cursor, input->current.surrounding.anchor);
wlr_input_method_v2_send_text_change_cause(input_method, wlr_input_method_v2_send_text_change_cause(input_method,
input->current.text_change_cause); input->current.text_change_cause);
wlr_input_method_v2_send_content_type(input_method, wlr_input_method_v2_send_content_type(input_method,
input->current.content_type.hint, input->current.content_type.purpose); input->current.content_type.hint,
input->current.content_type.purpose);
wlr_input_method_v2_send_done(input_method); wlr_input_method_v2_send_done(input_method);
// TODO: pass intent, display popup size // TODO: pass intent, display popup size
} }
static void handle_text_input_enable(struct wl_listener *listener, void *data) { static void handle_text_input_enable(struct wl_listener *listener, void *data) {
struct dwl_text_input *text_input = wl_container_of(listener, text_input, struct dwl_text_input *text_input =
text_input_enable); wl_container_of(listener, text_input, text_input_enable);
if (text_input->relay->input_method == NULL) { if (text_input->relay->input_method == NULL) {
wlr_log(WLR_INFO, "text_input_enable but input method is NULL"); wlr_log(WLR_INFO, "text_input_enable but input method is NULL");
return; return;
@@ -284,14 +289,16 @@ static void handle_text_input_enable(struct wl_listener *listener, void *data) {
/* static void handle_text_input_commit(struct wl_listener *listener, */ /* static void handle_text_input_commit(struct wl_listener *listener, */
/* void *data) { */ /* void *data) { */
/* struct dwl_text_input *text_input = wl_container_of(listener, text_input, */ /* struct dwl_text_input *text_input = wl_container_of(listener,
* text_input, */
/* text_input_commit); */ /* text_input_commit); */
/* if (!text_input->input->current_enabled) { */ /* if (!text_input->input->current_enabled) { */
/* wlr_log(WLR_INFO, "text_input_commit but not enabled"); */ /* wlr_log(WLR_INFO, "text_input_commit but not enabled"); */
/* return; */ /* return; */
/* } */ /* } */
/* if (text_input->relay->input_method == NULL) { */ /* if (text_input->relay->input_method == NULL) { */
/* wlr_log(WLR_INFO, "text_input_commit but input method is NULL"); */ /* wlr_log(WLR_INFO, "text_input_commit but input method is NULL");
*/
/* return; */ /* return; */
/* } */ /* } */
/* wlr_log(WLR_DEBUG, "text_input_commit"); */ /* wlr_log(WLR_DEBUG, "text_input_commit"); */
@@ -311,21 +318,20 @@ static void relay_disable_text_input(struct dwl_input_method_relay *relay,
wlr_input_method_v2_send_deactivate(relay->input_method); wlr_input_method_v2_send_deactivate(relay->input_method);
wlr_log(WLR_INFO, "input_method deactivate for xwayland"); wlr_log(WLR_INFO, "input_method deactivate for xwayland");
#endif #endif
//but if you keep the line above while remove the line below, input Chinese in geogebra(xwayland) won't work // but if you keep the line above while remove the line below, input Chinese
// in geogebra(xwayland) won't work
relay_send_im_state(relay, text_input->input); relay_send_im_state(relay, text_input->input);
} }
static void handle_text_input_destroy(struct wl_listener *listener, static void handle_text_input_destroy(struct wl_listener *listener,
void *data) { void *data) {
struct dwl_text_input *text_input = wl_container_of(listener, text_input, struct dwl_text_input *text_input =
text_input_destroy); wl_container_of(listener, text_input, text_input_destroy);
if (text_input->input->current_enabled) { if (text_input->input->current_enabled) {
wlr_log(WLR_INFO, "text_input_destroy when still enabled"); wlr_log(WLR_INFO, "text_input_destroy when still enabled");
relay_disable_text_input(text_input->relay, text_input); relay_disable_text_input(text_input->relay, text_input);
} } else {
else {
wlr_log(WLR_INFO, "text_input_destroy"); wlr_log(WLR_INFO, "text_input_destroy");
} }
@@ -340,8 +346,8 @@ static void handle_text_input_destroy(struct wl_listener *listener,
static void handle_pending_focused_surface_destroy(struct wl_listener *listener, static void handle_pending_focused_surface_destroy(struct wl_listener *listener,
void *data) { void *data) {
struct dwl_text_input *text_input = wl_container_of(listener, text_input, struct dwl_text_input *text_input =
pending_focused_surface_destroy); wl_container_of(listener, text_input, pending_focused_surface_destroy);
struct wlr_surface *surface = data; struct wlr_surface *surface = data;
assert(text_input->pending_focused_surface == surface); assert(text_input->pending_focused_surface == surface);
text_input->pending_focused_surface = NULL; text_input->pending_focused_surface = NULL;
@@ -349,11 +355,10 @@ static void handle_pending_focused_surface_destroy(struct wl_listener *listener,
wl_list_init(&text_input->pending_focused_surface_destroy.link); wl_list_init(&text_input->pending_focused_surface_destroy.link);
} }
static void relay_handle_text_input_new(struct wl_listener *listener, static void relay_handle_text_input_new(struct wl_listener *listener,
void *data) { void *data) {
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
text_input_new); wl_container_of(listener, relay, text_input_new);
struct wlr_text_input_v3 *wlr_text_input = data; struct wlr_text_input_v3 *wlr_text_input = data;
if (seat != wlr_text_input->seat) { if (seat != wlr_text_input->seat) {
return; return;
@@ -388,22 +393,22 @@ static void relay_handle_text_input_new(struct wl_listener *listener,
wl_list_init(&input->pending_focused_surface_destroy.link); wl_list_init(&input->pending_focused_surface_destroy.link);
} }
static LayerSurface *layer_surface_from_wlr_layer_surface_v1( static LayerSurface *layer_surface_from_wlr_layer_surface_v1(
struct wlr_layer_surface_v1 *layer_surface) { struct wlr_layer_surface_v1 *layer_surface) {
return layer_surface->data; return layer_surface->data;
} }
static void get_parent_and_output_box(struct wlr_surface *focused_surface, static void get_parent_and_output_box(struct wlr_surface *focused_surface,
struct wlr_box *parent, struct wlr_box *output_box) { struct wlr_box *parent,
struct wlr_box *output_box) {
struct wlr_output *output; struct wlr_output *output;
struct wlr_box output_box_tmp; struct wlr_box output_box_tmp;
struct wlr_layer_surface_v1 *layer_surface; struct wlr_layer_surface_v1 *layer_surface;
Client *client = NULL; Client *client = NULL;
LayerSurface *l = NULL; LayerSurface *l = NULL;
if ((layer_surface=wlr_layer_surface_v1_try_from_wlr_surface(focused_surface))) { if ((layer_surface =
wlr_layer_surface_v1_try_from_wlr_surface(focused_surface))) {
LayerSurface *layer = LayerSurface *layer =
layer_surface_from_wlr_layer_surface_v1(layer_surface); layer_surface_from_wlr_layer_surface_v1(layer_surface);
output = layer->layer_surface->output; output = layer->layer_surface->output;
@@ -411,33 +416,48 @@ static void get_parent_and_output_box(struct wlr_surface *focused_surface,
*parent = layer->geom; *parent = layer->geom;
parent->x += output_box_tmp.x; parent->x += output_box_tmp.x;
parent->y += output_box_tmp.y; parent->y += output_box_tmp.y;
wlr_log(WLR_INFO,"get_parent_and_output_box layersurface output_box_tmp->x %d y %d",output_box_tmp.x, output_box_tmp.y); wlr_log(WLR_INFO,
wlr_log(WLR_INFO,"get_parent_and_output_box layersurface parent->x %d y %d",parent->x,parent->y); "get_parent_and_output_box layersurface output_box_tmp->x %d y %d",
output_box_tmp.x, output_box_tmp.y);
wlr_log(WLR_INFO,
"get_parent_and_output_box layersurface parent->x %d y %d",
parent->x, parent->y);
} else { } else {
toplevel_from_wlr_surface(focused_surface, &client, &l); toplevel_from_wlr_surface(focused_surface, &client, &l);
output = wlr_output_layout_output_at(output_layout, output = wlr_output_layout_output_at(output_layout, client->geom.x,
client->geom.x, client->geom.y); client->geom.y);
wlr_output_layout_get_box(output_layout, output, &output_box_tmp); wlr_output_layout_get_box(output_layout, output, &output_box_tmp);
parent->x = client->geom.x + client->bw; parent->x = client->geom.x + client->bw;
parent->y = client->geom.y + client->bw; parent->y = client->geom.y + client->bw;
parent->width = client->geom.width; parent->width = client->geom.width;
parent->height = client->geom.height; parent->height = client->geom.height;
wlr_log(WLR_INFO,"get_parent_and_output_box client output_box_tmp->x %d y %d",output_box_tmp.x, output_box_tmp.y); wlr_log(WLR_INFO,
wlr_log(WLR_INFO,"get_parent_and_output_box client client->geom.x %d y %d",client->geom.x,client->geom.y); "get_parent_and_output_box client output_box_tmp->x %d y %d",
wlr_log(WLR_INFO,"get_parent_and_output_box client client->bw %d",client->bw); output_box_tmp.x, output_box_tmp.y);
wlr_log(WLR_INFO,"get_parent_and_output_box client parent->x %d y %d",parent->x,parent->y); wlr_log(WLR_INFO,
"get_parent_and_output_box client client->geom.x %d y %d",
client->geom.x, client->geom.y);
wlr_log(WLR_INFO, "get_parent_and_output_box client client->bw %d",
client->bw);
wlr_log(WLR_INFO, "get_parent_and_output_box client parent->x %d y %d",
parent->x, parent->y);
} }
//*output_box = output_box_tmp; //*output_box = output_box_tmp;
memcpy(output_box, &output_box_tmp, sizeof(struct wlr_box)); memcpy(output_box, &output_box_tmp, sizeof(struct wlr_box));
wlr_log(WLR_INFO,"get_parent_and_output_box output_box x %d y %d width %d height %d",output_box->x,output_box->y,output_box->width,output_box->height); wlr_log(WLR_INFO,
"get_parent_and_output_box output_box x %d y %d width %d height %d",
output_box->x, output_box->y, output_box->width, output_box->height);
} }
// 如果当前focused wlr_text_input_v3.features 满足 WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE, 不含这个feature就弹出在父窗口左上角 // 如果当前focused wlr_text_input_v3.features 满足
// 根据 wlr_text_input_v3.current.cursor_rectangle 计算出一个wlr_box // WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE,
// 再调用 wlr_input_popup_surface_v2_send_text_input_rectangle 和 wlr_scene_node_set_position // 不含这个feature就弹出在父窗口左上角 根据
// wlr_text_input_v3.current.cursor_rectangle 计算出一个wlr_box 再调用
// wlr_input_popup_surface_v2_send_text_input_rectangle 和
// wlr_scene_node_set_position
static void input_popup_update(struct dwl_input_popup *popup) { static void input_popup_update(struct dwl_input_popup *popup) {
struct wlr_surface *focused_surface; struct wlr_surface *focused_surface;
struct wlr_box output_box, parent, input_cursor; struct wlr_box output_box, parent, input_cursor;
@@ -451,14 +471,15 @@ static void input_popup_update(struct dwl_input_popup *popup) {
return; return;
} }
//TODO: https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/743da5c0ae723098fe772aadb93810f60e700ab9 // TODO:
// https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/743da5c0ae723098fe772aadb93810f60e700ab9
if (!popup->popup_surface->surface->mapped) { if (!popup->popup_surface->surface->mapped) {
return; return;
} }
cursor_rect = text_input->input->current.features cursor_rect = text_input->input->current.features &
& WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE; WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE;
focused_surface = text_input->input->focused_surface; focused_surface = text_input->input->focused_surface;
input_cursor = text_input->input->current.cursor_rectangle; input_cursor = text_input->input->current.cursor_rectangle;
@@ -478,9 +499,11 @@ static void input_popup_update(struct dwl_input_popup *popup) {
popup->x = parent.x; popup->x = parent.x;
popup->y = parent.y; popup->y = parent.y;
popup->visible = true; popup->visible = true;
} } else {
else { wlr_log(WLR_INFO,
wlr_log(WLR_INFO,"input_popup_update input_cursor x %d y %d width %d height %d",input_cursor.x,input_cursor.y,input_cursor.width,input_cursor.height); "input_popup_update input_cursor x %d y %d width %d height %d",
input_cursor.x, input_cursor.y, input_cursor.width,
input_cursor.height);
x1 = parent.x + input_cursor.x; x1 = parent.x + input_cursor.x;
x2 = parent.x + input_cursor.x + input_cursor.width; x2 = parent.x + input_cursor.x + input_cursor.width;
@@ -489,19 +512,26 @@ static void input_popup_update(struct dwl_input_popup *popup) {
x = x1; x = x1;
y = y2; y = y2;
wlr_log(WLR_INFO,"input_popup_update x1 %d x2 %d y1 %d y2 %d; x %d y %d",x1,x2,y1,y2,x,y); wlr_log(WLR_INFO, "input_popup_update x1 %d x2 %d y1 %d y2 %d; x %d y %d",
x1, x2, y1, y2, x, y);
available_right = output_box.x + output_box.width - x1; available_right = output_box.x + output_box.width - x1;
available_left = x2 - output_box.x; available_left = x2 - output_box.x;
if (available_right < popup_width && available_left > available_right) { if (available_right < popup_width && available_left > available_right) {
x = x2 - popup_width; x = x2 - popup_width;
wlr_log(WLR_INFO,"input_popup_update available_left %d popup_width %d available_right %d; x %d",available_left,popup_width,available_right,x); wlr_log(WLR_INFO,
"input_popup_update available_left %d popup_width %d "
"available_right %d; x %d",
available_left, popup_width, available_right, x);
} }
available_down = output_box.y + output_box.height - y2; available_down = output_box.y + output_box.height - y2;
available_up = y1 - output_box.y; available_up = y1 - output_box.y;
if (available_down < popup_height && available_up > available_down) { if (available_down < popup_height && available_up > available_down) {
y = y1 - popup_height; y = y1 - popup_height;
wlr_log(WLR_INFO,"input_popup_update available up %d popup_height %d available_down %d; y %d",available_up,popup_height,available_down,y); wlr_log(WLR_INFO,
"input_popup_update available up %d popup_height %d "
"available_down %d; y %d",
available_up, popup_height, available_down, y);
} }
popup->x = x; popup->x = x;
@@ -510,10 +540,10 @@ static void input_popup_update(struct dwl_input_popup *popup) {
// Hide popup if input_cursor position is completely out of bounds // Hide popup if input_cursor position is completely out of bounds
x1_in_bounds = (input_cursor.x >= 0 && input_cursor.x < parent.width); x1_in_bounds = (input_cursor.x >= 0 && input_cursor.x < parent.width);
y1_in_bounds = (input_cursor.y >= 0 && input_cursor.y < parent.height); y1_in_bounds = (input_cursor.y >= 0 && input_cursor.y < parent.height);
x2_in_bounds = (input_cursor.x + input_cursor.width >= 0 x2_in_bounds = (input_cursor.x + input_cursor.width >= 0 &&
&& input_cursor.x + input_cursor.width < parent.width); input_cursor.x + input_cursor.width < parent.width);
y2_in_bounds = (input_cursor.y + input_cursor.height >= 0 y2_in_bounds = (input_cursor.y + input_cursor.height >= 0 &&
&& input_cursor.y + input_cursor.height < parent.height); input_cursor.y + input_cursor.height < parent.height);
popup->visible = popup->visible =
(x1_in_bounds && y1_in_bounds) || (x2_in_bounds && y2_in_bounds); (x1_in_bounds && y1_in_bounds) || (x2_in_bounds && y2_in_bounds);
@@ -523,26 +553,29 @@ static void input_popup_update(struct dwl_input_popup *popup) {
.width = input_cursor.width, .width = input_cursor.width,
.height = input_cursor.height, .height = input_cursor.height,
}; };
wlr_input_popup_surface_v2_send_text_input_rectangle( wlr_input_popup_surface_v2_send_text_input_rectangle(popup->popup_surface,
popup->popup_surface, &box); &box);
wlr_log(WLR_INFO,"input_popup_update send_text_input_rect box.x %d box.y %d",box.x,box.y); wlr_log(WLR_INFO,
"input_popup_update send_text_input_rect box.x %d box.y %d", box.x,
box.y);
} }
wlr_log(WLR_INFO,"input_popup_update x %d y %d visible %s",popup->x,popup->y,popup->visible?"true":"false"); wlr_log(WLR_INFO, "input_popup_update x %d y %d visible %s", popup->x,
popup->y, popup->visible ? "true" : "false");
wlr_scene_node_set_position(&popup->scene->node, popup->x, popup->y); wlr_scene_node_set_position(&popup->scene->node, popup->x, popup->y);
} }
static void handle_im_popup_map(struct wl_listener *listener, void *data) { static void handle_im_popup_map(struct wl_listener *listener, void *data) {
struct dwl_input_popup *popup = struct dwl_input_popup *popup = wl_container_of(listener, popup, popup_map);
wl_container_of(listener, popup, popup_map);
wlr_log(WLR_INFO, "IM_popup_map"); wlr_log(WLR_INFO, "IM_popup_map");
// popup->scene = &wlr_scene_tree_create(layers[LyrIMPopup])->node; // popup->scene = &wlr_scene_tree_create(layers[LyrIMPopup])->node;
popup->scene = wlr_scene_tree_create(layers[LyrIMPopup]); popup->scene = wlr_scene_tree_create(layers[LyrIMPopup]);
popup->scene_surface = wlr_scene_subsurface_tree_create(popup->scene,popup->popup_surface->surface); popup->scene_surface = wlr_scene_subsurface_tree_create(
//popup->scene_surface = &wlr_scene_subsurface_tree_create(popup->scene->parent,popup->popup_surface->surface)->node; popup->scene, popup->popup_surface->surface);
// popup->scene_surface =
// &wlr_scene_subsurface_tree_create(popup->scene->parent,popup->popup_surface->surface)->node;
// popup->scene_surface->data = popup; // popup->scene_surface->data = popup;
popup->scene_surface->node.data = popup; popup->scene_surface->node.data = popup;
@@ -552,8 +585,7 @@ static void handle_im_popup_map(struct wl_listener *listener, void *data) {
} }
static void handle_im_popup_unmap(struct wl_listener *listener, void *data) { static void handle_im_popup_unmap(struct wl_listener *listener, void *data) {
struct dwl_input_popup *popup = struct dwl_input_popup *popup = wl_container_of(listener, popup, popup_unmap);
wl_container_of(listener, popup, popup_unmap);
// input_popup_update(popup); // input_popup_update(popup);
wlr_log(WLR_INFO, "im_popup_unmap"); wlr_log(WLR_INFO, "im_popup_unmap");
@@ -576,12 +608,12 @@ static void handle_im_popup_destroy(struct wl_listener *listener, void *data) {
relay->popup = NULL; relay->popup = NULL;
} }
static void handle_im_new_popup_surface(struct wl_listener *listener,
static void handle_im_new_popup_surface(struct wl_listener *listener, void *data) { void *data) {
// struct dwl_text_input* text_input; // struct dwl_text_input* text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
input_method_new_popup_surface); wl_container_of(listener, relay, input_method_new_popup_surface);
struct dwl_input_popup *popup = calloc(1, sizeof(*popup)); struct dwl_input_popup *popup = calloc(1, sizeof(*popup));
wlr_log(WLR_INFO, "IM_new_popup_surface"); wlr_log(WLR_INFO, "IM_new_popup_surface");
@@ -591,25 +623,23 @@ static void handle_im_new_popup_surface(struct wl_listener *listener, void *data
popup->popup_surface = data; popup->popup_surface = data;
popup->popup_surface->data = popup; popup->popup_surface->data = popup;
wl_signal_add(&popup->popup_surface->surface->events.map, &popup->popup_map); wl_signal_add(&popup->popup_surface->surface->events.map, &popup->popup_map);
popup->popup_map.notify = handle_im_popup_map; popup->popup_map.notify = handle_im_popup_map;
wl_signal_add(&popup->popup_surface->surface->events.unmap, &popup->popup_unmap); wl_signal_add(&popup->popup_surface->surface->events.unmap,
&popup->popup_unmap);
popup->popup_unmap.notify = handle_im_popup_unmap; popup->popup_unmap.notify = handle_im_popup_unmap;
wl_signal_add( wl_signal_add(&popup->popup_surface->events.destroy, &popup->popup_destroy);
&popup->popup_surface->events.destroy, &popup->popup_destroy);
popup->popup_destroy.notify = handle_im_popup_destroy; popup->popup_destroy.notify = handle_im_popup_destroy;
} }
static void relay_handle_input_method_new(struct wl_listener *listener, static void relay_handle_input_method_new(struct wl_listener *listener,
void *data) { void *data) {
struct dwl_text_input *text_input; struct dwl_text_input *text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, struct dwl_input_method_relay *relay =
input_method_new); wl_container_of(listener, relay, input_method_new);
struct wlr_input_method_v2 *input_method = data; struct wlr_input_method_v2 *input_method = data;
if (seat != input_method->seat) { if (seat != input_method->seat) {
@@ -618,7 +648,9 @@ static void relay_handle_input_method_new(struct wl_listener *listener,
} }
if (relay->input_method != NULL) { if (relay->input_method != NULL) {
wlr_log(WLR_INFO, "input_method_new Attempted to connect second input method to a seat"); wlr_log(
WLR_INFO,
"input_method_new Attempted to connect second input method to a seat");
wlr_input_method_v2_send_unavailable(input_method); wlr_input_method_v2_send_unavailable(input_method);
return; return;
} }
@@ -655,8 +687,7 @@ void dwl_input_method_relay_init(struct dwl_input_method_relay *relay) {
relay->popup = NULL; relay->popup = NULL;
relay->text_input_new.notify = relay_handle_text_input_new; relay->text_input_new.notify = relay_handle_text_input_new;
wl_signal_add(&text_input_manager->events.text_input, wl_signal_add(&text_input_manager->events.text_input, &relay->text_input_new);
&relay->text_input_new);
relay->input_method_new.notify = relay_handle_input_method_new; relay->input_method_new.notify = relay_handle_input_method_new;
wl_signal_add(&input_method_manager->events.input_method, wl_signal_add(&input_method_manager->events.input_method,
@@ -684,13 +715,13 @@ void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
} }
} }
if (surface if (surface && wl_resource_get_client(text_input->input->resource) ==
&& wl_resource_get_client(text_input->input->resource) wl_resource_get_client(surface->resource)) {
== wl_resource_get_client(surface->resource)) {
if (relay->input_method) { if (relay->input_method) {
wlr_text_input_v3_send_enter(text_input->input, surface); wlr_text_input_v3_send_enter(text_input->input, surface);
wlr_log(WLR_INFO, "wlr_text_input_send_enter"); wlr_log(WLR_INFO, "wlr_text_input_send_enter");
if (relay->popup) input_popup_update(relay->popup); if (relay->popup)
input_popup_update(relay->popup);
} else { } else {
text_input_set_pending_focused_surface(text_input, surface); text_input_set_pending_focused_surface(text_input, surface);
} }

175
client.h
View File

@@ -6,18 +6,14 @@
*/ */
/* Leave these functions first; they're used in the others */ /* Leave these functions first; they're used in the others */
static inline int static inline int client_is_x11(Client *c) {
client_is_x11(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
return c->type == X11; return c->type == X11;
#endif #endif
return 0; return 0;
} }
static inline struct wlr_surface * static inline struct wlr_surface *client_surface(Client *c) {
client_surface(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->surface; return c->surface.xwayland->surface;
@@ -25,9 +21,8 @@ client_surface(Client *c)
return c->surface.xdg->surface; return c->surface.xdg->surface;
} }
static inline int static inline int toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc,
toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) LayerSurface **pl) {
{
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
struct wlr_surface *root_surface; struct wlr_surface *root_surface;
struct wlr_layer_surface_v1 *layer_surface; struct wlr_layer_surface_v1 *layer_surface;
@@ -50,7 +45,8 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
} }
#endif #endif
if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { if ((layer_surface =
wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) {
l = layer_surface->data; l = layer_surface->data;
type = LayerShell; type = LayerShell;
goto end; goto end;
@@ -64,7 +60,8 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
if (!xdg_surface->popup || !xdg_surface->popup->parent) if (!xdg_surface->popup || !xdg_surface->popup->parent)
return -1; return -1;
tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); tmp_xdg_surface =
wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent);
if (!tmp_xdg_surface) if (!tmp_xdg_surface)
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
@@ -89,9 +86,8 @@ end:
} }
/* The others */ /* The others */
static inline void static inline void client_activate_surface(struct wlr_surface *s,
client_activate_surface(struct wlr_surface *s, int activated) int activated) {
{
struct wlr_xdg_toplevel *toplevel; struct wlr_xdg_toplevel *toplevel;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
@@ -104,16 +100,16 @@ client_activate_surface(struct wlr_surface *s, int activated)
wlr_xdg_toplevel_set_activated(toplevel, activated); wlr_xdg_toplevel_set_activated(toplevel, activated);
} }
static inline uint32_t static inline uint32_t client_set_bounds(Client *c, int32_t width,
client_set_bounds(Client *c, int32_t width, int32_t height) int32_t height) {
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return 0; return 0;
#endif #endif
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >=
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0 XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION &&
&& (c->bounds.width != width || c->bounds.height != height)) { width >= 0 && height >= 0 &&
(c->bounds.width != width || c->bounds.height != height)) {
c->bounds.width = width; c->bounds.width = width;
c->bounds.height = height; c->bounds.height = height;
return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height);
@@ -121,9 +117,7 @@ client_set_bounds(Client *c, int32_t width, int32_t height)
return 0; return 0;
} }
static inline const char * static inline const char *client_get_appid(Client *c) {
client_get_appid(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->class; return c->surface.xwayland->class;
@@ -131,9 +125,7 @@ client_get_appid(Client *c)
return c->surface.xdg->toplevel->app_id; return c->surface.xdg->toplevel->app_id;
} }
static inline void static inline void client_get_clip(Client *c, struct wlr_box *clip) {
client_get_clip(Client *c, struct wlr_box *clip)
{
struct wlr_box xdg_geom = {0}; struct wlr_box xdg_geom = {0};
*clip = (struct wlr_box){ *clip = (struct wlr_box){
.x = 0, .x = 0,
@@ -152,9 +144,7 @@ client_get_clip(Client *c, struct wlr_box *clip)
clip->y = xdg_geom.y; clip->y = xdg_geom.y;
} }
static inline void static inline void client_get_geometry(Client *c, struct wlr_box *geom) {
client_get_geometry(Client *c, struct wlr_box *geom)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
geom->x = c->surface.xwayland->x; geom->x = c->surface.xwayland->x;
@@ -167,9 +157,7 @@ client_get_geometry(Client *c, struct wlr_box *geom)
wlr_xdg_surface_get_geometry(c->surface.xdg, geom); wlr_xdg_surface_get_geometry(c->surface.xdg, geom);
} }
static inline Client * static inline Client *client_get_parent(Client *c) {
client_get_parent(Client *c)
{
Client *p = NULL; Client *p = NULL;
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
@@ -179,13 +167,12 @@ client_get_parent(Client *c)
} }
#endif #endif
if (c->surface.xdg->toplevel->parent) if (c->surface.xdg->toplevel->parent)
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface,
&p, NULL);
return p; return p;
} }
static inline int static inline int client_has_children(Client *c) {
client_has_children(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return !wl_list_empty(&c->surface.xwayland->children); return !wl_list_empty(&c->surface.xwayland->children);
@@ -195,9 +182,7 @@ client_has_children(Client *c)
return wl_list_length(&c->surface.xdg->link) > 1; return wl_list_length(&c->surface.xdg->link) > 1;
} }
static inline const char * static inline const char *client_get_title(Client *c) {
client_get_title(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->title; return c->surface.xwayland->title;
@@ -205,9 +190,7 @@ client_get_title(Client *c)
return c->surface.xdg->toplevel->title; return c->surface.xdg->toplevel->title;
} }
static inline int static inline int client_is_float_type(Client *c) {
client_is_float_type(Client *c)
{
struct wlr_xdg_toplevel *toplevel; struct wlr_xdg_toplevel *toplevel;
struct wlr_xdg_toplevel_state state; struct wlr_xdg_toplevel_state state;
@@ -220,28 +203,27 @@ client_is_float_type(Client *c)
return 1; return 1;
for (i = 0; i < surface->window_type_len; i++) for (i = 0; i < surface->window_type_len; i++)
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] ||
|| surface->window_type[i] == netatom[NetWMWindowTypeSplash] surface->window_type[i] == netatom[NetWMWindowTypeSplash] ||
|| surface->window_type[i] == netatom[NetWMWindowTypeToolbar] surface->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
|| surface->window_type[i] == netatom[NetWMWindowTypeUtility]) surface->window_type[i] == netatom[NetWMWindowTypeUtility])
return 1; return 1;
return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 return size_hints && size_hints->min_width > 0 &&
&& (size_hints->max_width == size_hints->min_width size_hints->min_height > 0 &&
|| size_hints->max_height == size_hints->min_height); (size_hints->max_width == size_hints->min_width ||
size_hints->max_height == size_hints->min_height);
} }
#endif #endif
toplevel = c->surface.xdg->toplevel; toplevel = c->surface.xdg->toplevel;
state = toplevel->current; state = toplevel->current;
return toplevel->parent || (state.min_width != 0 && state.min_height != 0 return toplevel->parent || (state.min_width != 0 && state.min_height != 0 &&
&& (state.min_width == state.max_width (state.min_width == state.max_width ||
|| state.min_height == state.max_height)); state.min_height == state.max_height));
} }
static inline int static inline int client_is_rendered_on_mon(Client *c, Monitor *m) {
client_is_rendered_on_mon(Client *c, Monitor *m)
{
/* This is needed for when you don't want to check formal assignment, /* This is needed for when you don't want to check formal assignment,
* but rather actual displaying of the pixels. * but rather actual displaying of the pixels.
* Usually VISIBLEON suffices and is also faster. */ * Usually VISIBLEON suffices and is also faster. */
@@ -249,15 +231,12 @@ client_is_rendered_on_mon(Client *c, Monitor *m)
int unused_lx, unused_ly; int unused_lx, unused_ly;
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
return 0; return 0;
wl_list_for_each(s, &client_surface(c)->current_outputs, link) wl_list_for_each(s, &client_surface(c)->current_outputs,
if (s->output == m->wlr_output) link) if (s->output == m->wlr_output) return 1;
return 1;
return 0; return 0;
} }
static inline int static inline int client_is_stopped(Client *c) {
client_is_stopped(Client *c)
{
int pid; int pid;
siginfo_t in = {0}; siginfo_t in = {0};
#ifdef XWAYLAND #ifdef XWAYLAND
@@ -281,9 +260,7 @@ client_is_stopped(Client *c)
return 0; return 0;
} }
static inline int static inline int client_is_unmanaged(Client *c) {
client_is_unmanaged(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->override_redirect; return c->surface.xwayland->override_redirect;
@@ -291,19 +268,16 @@ client_is_unmanaged(Client *c)
return 0; return 0;
} }
static inline void static inline void client_notify_enter(struct wlr_surface *s,
client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) struct wlr_keyboard *kb) {
{
if (kb) if (kb)
wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, kb->num_keycodes,
kb->num_keycodes, &kb->modifiers); &kb->modifiers);
else else
wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL);
} }
static inline void static inline void client_restack_surface(Client *c) {
client_restack_surface(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
wlr_xwayland_surface_restack(c->surface.xwayland, NULL, wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
@@ -312,9 +286,7 @@ client_restack_surface(Client *c)
return; return;
} }
static inline void static inline void client_send_close(Client *c) {
client_send_close(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
wlr_xwayland_surface_close(c->surface.xwayland); wlr_xwayland_surface_close(c->surface.xwayland);
@@ -324,17 +296,14 @@ client_send_close(Client *c)
wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel);
} }
static inline void static inline void client_set_border_color(Client *c,
client_set_border_color(Client *c, const float color[static 4]) const float color[static 4]) {
{
int i; int i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
wlr_scene_rect_set_color(c->border[i], color); wlr_scene_rect_set_color(c->border[i], color);
} }
static inline void static inline void client_set_fullscreen(Client *c, int fullscreen) {
client_set_fullscreen(Client *c, int fullscreen)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
@@ -344,40 +313,37 @@ client_set_fullscreen(Client *c, int fullscreen)
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
} }
static inline uint32_t static inline uint32_t client_set_size(Client *c, uint32_t width,
client_set_size(Client *c, uint32_t width, uint32_t height) uint32_t height) {
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
wlr_xwayland_surface_configure(c->surface.xwayland, wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x, c->geom.y,
c->geom.x, c->geom.y, width, height); width, height);
return 0; return 0;
} }
#endif #endif
if ((int32_t)width == c->surface.xdg->toplevel->current.width if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
&& (int32_t)height == c->surface.xdg->toplevel->current.height) (int32_t)height == c->surface.xdg->toplevel->current.height)
return 0; return 0;
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height); return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width,
(int32_t)height);
} }
static inline void static inline void client_set_tiled(Client *c, uint32_t edges) {
client_set_tiled(Client *c, uint32_t edges)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return; return;
#endif #endif
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >=
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
} else { } else {
wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != WLR_EDGE_NONE); wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel,
edges != WLR_EDGE_NONE);
} }
} }
static inline void static inline void client_set_suspended(Client *c, int suspended) {
client_set_suspended(Client *c, int suspended)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return; return;
@@ -386,20 +352,17 @@ client_set_suspended(Client *c, int suspended)
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
} }
static inline int static inline int client_wants_focus(Client *c) {
client_wants_focus(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
return client_is_unmanaged(c) return client_is_unmanaged(c) &&
&& wlr_xwayland_or_surface_wants_focus(c->surface.xwayland) wlr_xwayland_or_surface_wants_focus(c->surface.xwayland) &&
&& wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE; wlr_xwayland_icccm_input_model(c->surface.xwayland) !=
WLR_ICCCM_INPUT_MODEL_NONE;
#endif #endif
return 0; return 0;
} }
static inline int static inline int client_wants_fullscreen(Client *c) {
client_wants_fullscreen(Client *c)
{
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->fullscreen; return c->surface.xwayland->fullscreen;

311
maomao.c
View File

@@ -1,11 +1,9 @@
/* /*
* See LICENSE file for copyright and license details. * See LICENSE file for copyright and license details.
*/ */
#include <execinfo.h>
#include <getopt.h> #include <getopt.h>
#include <libinput.h> #include <libinput.h>
#include <wordexp.h>
#include <signal.h>
#include <execinfo.h>
#include <limits.h> #include <limits.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <signal.h> #include <signal.h>
@@ -30,6 +28,7 @@
#include <wlr/types/wlr_pointer_constraints_v1.h> #include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include <wordexp.h>
// #include <wlr/types/wlr_idle.h> // #include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_cursor_shape_v1.h> #include <wlr/types/wlr_cursor_shape_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_idle_inhibit_v1.h>
@@ -367,7 +366,8 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
struct wlr_box *usable_area, int exclusive); struct wlr_box *usable_area, int exclusive);
static void arrangelayers(Monitor *m); static void arrangelayers(Monitor *m);
static void autostartexec(void); // 自启动命令执行 static void autostartexec(void); // 自启动命令执行
static void axisnotify(struct wl_listener *listener, void *data); // 滚轮事件处理 static void axisnotify(struct wl_listener *listener,
void *data); // 滚轮事件处理
static void buttonpress(struct wl_listener *listener, static void buttonpress(struct wl_listener *listener,
void *data); // 鼠标按键事件处理 void *data); // 鼠标按键事件处理
static void checkidleinhibitor(struct wlr_surface *exclude); static void checkidleinhibitor(struct wlr_surface *exclude);
@@ -635,8 +635,8 @@ static Atom netatom[NetLast];
#endif #endif
/* configuration, allows nested code to access above variables */ /* configuration, allows nested code to access above variables */
#include "preset_config.h"
#include "parse_config.h" #include "parse_config.h"
#include "preset_config.h"
/* attempt to encapsulate suck into one file */ /* attempt to encapsulate suck into one file */
#include "client.h" #include "client.h"
@@ -784,53 +784,50 @@ void client_actual_size(Client *c, uint32_t *width, uint32_t *height) {
: c->current.height; : c->current.height;
} }
void apply_border(Client *c, struct wlr_box clip_box, int offset) void apply_border(Client *c, struct wlr_box clip_box, int offset) {
{
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
wlr_scene_rect_set_size(c->border[0], clip_box.width, c->bw); wlr_scene_rect_set_size(c->border[0], clip_box.width, c->bw);
wlr_scene_rect_set_size(c->border[1], clip_box.width, c->bw); wlr_scene_rect_set_size(c->border[1], clip_box.width, c->bw);
if (c->animation.tagining || c->animation.tagouted || c->animation.tagouting) if (c->animation.tagining || c->animation.tagouted ||
{ c->animation.tagouting) {
if (c->animation.current.x < c->mon->m.x) if (c->animation.current.x < c->mon->m.x) {
{
wlr_scene_rect_set_size(c->border[2], 0, 0); wlr_scene_rect_set_size(c->border[2], 0, 0);
wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_node_set_position(&c->border[0]->node, offset, 0); wlr_scene_node_set_position(&c->border[0]->node, offset, 0);
wlr_scene_node_set_position(&c->border[2]->node, 0 + offset, c->bw); wlr_scene_node_set_position(&c->border[2]->node, 0 + offset, c->bw);
wlr_scene_node_set_position(&c->border[1]->node, offset, clip_box.height - c->bw); wlr_scene_node_set_position(&c->border[1]->node, offset,
wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw + offset, clip_box.height - c->bw);
c->bw); wlr_scene_node_set_position(&c->border[3]->node,
} clip_box.width - c->bw + offset, c->bw);
else if (c->animation.current.x + c->geom.width > c->mon->m.x + c->mon->m.width) } else if (c->animation.current.x + c->geom.width >
{ c->mon->m.x + c->mon->m.width) {
wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_rect_set_size(c->border[3], 0, 0); wlr_scene_rect_set_size(c->border[3], 0, 0);
wlr_scene_node_set_position(&c->border[0]->node, 0, 0); wlr_scene_node_set_position(&c->border[0]->node, 0, 0);
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
wlr_scene_node_set_position(&c->border[1]->node, 0, clip_box.height - c->bw); wlr_scene_node_set_position(&c->border[1]->node, 0,
clip_box.height - c->bw);
wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw, wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw,
c->bw); c->bw);
} } else {
else
{
wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_node_set_position(&c->border[0]->node, 0, 0); wlr_scene_node_set_position(&c->border[0]->node, 0, 0);
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
wlr_scene_node_set_position(&c->border[1]->node, 0, clip_box.height - c->bw); wlr_scene_node_set_position(&c->border[1]->node, 0,
clip_box.height - c->bw);
wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw, wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw,
c->bw); c->bw);
} }
} } else {
else
{
wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[2], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw); wlr_scene_rect_set_size(c->border[3], c->bw, clip_box.height - 2 * c->bw);
wlr_scene_node_set_position(&c->border[0]->node, 0, 0); wlr_scene_node_set_position(&c->border[0]->node, 0, 0);
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
wlr_scene_node_set_position(&c->border[1]->node, 0, clip_box.height - c->bw); wlr_scene_node_set_position(&c->border[1]->node, 0,
clip_box.height - c->bw);
wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw, wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw,
c->bw); c->bw);
} }
@@ -856,13 +853,17 @@ void client_apply_clip(Client *c) {
} }
// make tagout tagin animations not visible in other monitors // make tagout tagin animations not visible in other monitors
if(c->animation.tagouting || c->animation.tagining || c->animation.tagouted) { if (c->animation.tagouting || c->animation.tagining ||
c->animation.tagouted) {
if (c->animation.current.x <= c->mon->m.x) { if (c->animation.current.x <= c->mon->m.x) {
offset = c->mon->m.x - c->animation.current.x; offset = c->mon->m.x - c->animation.current.x;
clip_box.x = clip_box.x + offset; clip_box.x = clip_box.x + offset;
clip_box.width = clip_box.width - offset; clip_box.width = clip_box.width - offset;
} else if(c->animation.current.x + c->geom.width >= c->mon->m.x + c->mon->m.width) { } else if (c->animation.current.x + c->geom.width >=
clip_box.width = clip_box.width - (c->animation.current.x + c->animation.current.width - c->mon->m.x - c->mon->m.width); c->mon->m.x + c->mon->m.width) {
clip_box.width = clip_box.width -
(c->animation.current.x + c->animation.current.width -
c->mon->m.x - c->mon->m.width);
} }
} }
@@ -1125,7 +1126,8 @@ applyrulesgeom(Client *c) {
if (config.window_rules_count < 1) if (config.window_rules_count < 1)
break; break;
r = &config.window_rules[ji]; r = &config.window_rules[ji];
if ( (r->title && strstr(title, r->title)) || (r->id && strstr(appid, r->id))) { 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.width = r->width > 0 ? r->width : c->geom.width;
c->geom.height = r->height > 0 ? r->height : c->geom.height; c->geom.height = r->height > 0 ? r->height : c->geom.height;
// 重新计算居中的坐标 // 重新计算居中的坐标
@@ -1156,10 +1158,14 @@ applyrules(Client *c) {
break; break;
r = &config.window_rules[ji]; r = &config.window_rules[ji];
if ( (r->title && strstr(title, r->title)) || (r->id && strstr(appid, r->id))) { if ((r->title && strstr(title, r->title)) ||
(r->id && strstr(appid, r->id))) {
c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating; c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating;
c->animation_type = r->animation_type == NULL ? c->animation_type : r->animation_type; c->animation_type =
c->scroller_proportion = r->scroller_proportion > 0 ? r->scroller_proportion : scroller_default_proportion; 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 > 0 ? r->isnoborder : c->isnoborder; c->isnoborder = r->isnoborder > 0 ? r->isnoborder : c->isnoborder;
newtags = r->tags > 0 ? r->tags | newtags : newtags; newtags = r->tags > 0 ? r->tags | newtags : newtags;
i = 0; i = 0;
@@ -1225,10 +1231,13 @@ arrange(Monitor *m, bool want_animation) {
m->pertag->prevtag != 0 && m->pertag->curtag != 0) { m->pertag->prevtag != 0 && m->pertag->curtag != 0) {
c->animation.tagining = true; c->animation.tagining = true;
if (m->pertag->curtag > m->pertag->prevtag) { if (m->pertag->curtag > m->pertag->prevtag) {
c->animainit_geom.x = c->animation.running? c->animation.current.x: c->animainit_geom.x =
c->geom.x + c->mon->m.width - (c->geom.x - c->mon->m.x); c->animation.running
? c->animation.current.x
: c->geom.x + c->mon->m.width - (c->geom.x - c->mon->m.x);
} else { } else {
c->animainit_geom.x = c->animation.running? c->animation.current.x : m->m.x - c->geom.width; c->animainit_geom.x = c->animation.running ? c->animation.current.x
: m->m.x - c->geom.width;
} }
} }
@@ -1249,7 +1258,8 @@ arrange(Monitor *m, bool want_animation) {
resize(c, c->geom, 0); resize(c, c->geom, 0);
} else { } else {
c->pending = c->geom; c->pending = c->geom;
c->pending.x = c->geom.x + c->mon->m.width - (c->geom.x - c->mon->m.x); c->pending.x =
c->geom.x + c->mon->m.width - (c->geom.x - c->mon->m.x);
resize(c, c->geom, 0); resize(c, c->geom, 0);
} }
} else { } else {
@@ -1364,7 +1374,8 @@ Client *direction_select(const Arg *arg) {
if (tempClients[_i]->geom.y < sel_y) { if (tempClients[_i]->geom.y < sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x; int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y; int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance = dis_x * dis_x + dis_y * dis_y; // 计算距离 long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) { if (tmp_distance < distance) {
distance = tmp_distance; distance = tmp_distance;
tempFocusClients = tempClients[_i]; tempFocusClients = tempClients[_i];
@@ -1390,7 +1401,8 @@ Client *direction_select(const Arg *arg) {
if (tempClients[_i]->geom.y > sel_y) { if (tempClients[_i]->geom.y > sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x; int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y; int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance = dis_x * dis_x + dis_y * dis_y; // 计算距离 long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) { if (tmp_distance < distance) {
distance = tmp_distance; distance = tmp_distance;
tempFocusClients = tempClients[_i]; tempFocusClients = tempClients[_i];
@@ -1416,7 +1428,8 @@ Client *direction_select(const Arg *arg) {
if (tempClients[_i]->geom.x < sel_x) { if (tempClients[_i]->geom.x < sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x; int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y; int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance = dis_x * dis_x + dis_y * dis_y; // 计算距离 long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) { if (tmp_distance < distance) {
distance = tmp_distance; distance = tmp_distance;
tempFocusClients = tempClients[_i]; tempFocusClients = tempClients[_i];
@@ -1442,7 +1455,8 @@ Client *direction_select(const Arg *arg) {
if (tempClients[_i]->geom.x > sel_x) { if (tempClients[_i]->geom.x > sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x; int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y; int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance = dis_x * dis_x + dis_y * dis_y; // 计算距离 long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) { if (tmp_distance < distance) {
distance = tmp_distance; distance = tmp_distance;
tempFocusClients = tempClients[_i]; tempFocusClients = tempClients[_i];
@@ -1847,15 +1861,14 @@ void client_commit(Client *c) {
wlr_output_schedule_frame(c->mon->wlr_output); wlr_output_schedule_frame(c->mon->wlr_output);
} }
void void commitnotify(struct wl_listener *listener, void *data) {
commitnotify(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, commit); Client *c = wl_container_of(listener, c, commit);
if(!c || c->iskilling || c->animation.tagining || c->animation.tagining || c->animation.tagouted) if (!c || c->iskilling || c->animation.tagining || c->animation.tagining ||
c->animation.tagouted)
return; return;
// if don't do this, some client may resize uncompleted // if don't do this, some client may resize uncompleted
resize(c, c->geom, (c->isfloating && !c->isfullscreen)); resize(c, c->geom, (c->isfloating && !c->isfullscreen));
} }
void // 0.5 void // 0.5
@@ -2097,12 +2110,10 @@ createmon(struct wl_listener *listener, void *data) {
} }
} }
} }
} }
printstatus(); printstatus();
/* The xdg-protocol specifies: /* The xdg-protocol specifies:
* *
* If the fullscreened surface is not opaque, the compositor must make * If the fullscreened surface is not opaque, the compositor must make
@@ -2546,10 +2557,10 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
title = focused ? client_get_title(focused) : ""; title = focused ? client_get_title(focused) : "";
appid = focused ? client_get_appid(focused) : ""; appid = focused ? client_get_appid(focused) : "";
symbol = symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
zdwl_ipc_output_v2_send_layout(ipc_output->resource, zdwl_ipc_output_v2_send_layout(
ipc_output->resource,
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts); monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);
zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken); zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken); zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
@@ -2631,8 +2642,10 @@ void dwl_ipc_output_release(struct wl_client *client,
} }
void focusclient(Client *c, int lift) { void focusclient(Client *c, int lift) {
struct wlr_surface *old_keyboard_focus_surface = seat->keyboard_state.focused_surface; struct wlr_surface *old_keyboard_focus_surface =
struct wlr_surface *old_pointer_focus_surface = seat->pointer_state.focused_surface; seat->keyboard_state.focused_surface;
struct wlr_surface *old_pointer_focus_surface =
seat->pointer_state.focused_surface;
if (locked) if (locked)
return; return;
@@ -2647,7 +2660,8 @@ void focusclient(Client *c, int lift) {
if (c && lift) if (c && lift)
wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层
if (c && client_surface(c) == old_keyboard_focus_surface && client_surface(c) == old_pointer_focus_surface) if (c && client_surface(c) == old_keyboard_focus_surface &&
client_surface(c) == old_pointer_focus_surface)
return; return;
else { else {
wlr_seat_pointer_notify_clear_focus(seat); wlr_seat_pointer_notify_clear_focus(seat);
@@ -2665,7 +2679,11 @@ void focusclient(Client *c, int lift) {
if (selmon) { if (selmon) {
selmon->prevsel = selmon->sel; selmon->prevsel = selmon->sel;
selmon->sel = c; selmon->sel = c;
if (c && selmon->prevsel && selmon->prevsel->istiled && selmon->prevsel->tags == c->tags && c->istiled && !c->isfloating && !c->isfullscreen && strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name , "scroller") == 0) { if (c && selmon->prevsel && selmon->prevsel->istiled &&
selmon->prevsel->tags == c->tags && c->istiled && !c->isfloating &&
!c->isfullscreen &&
strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name,
"scroller") == 0) {
arrange(selmon, false); arrange(selmon, false);
} else if (selmon->prevsel) { } else if (selmon->prevsel) {
selmon->prevsel = NULL; selmon->prevsel = NULL;
@@ -2687,7 +2705,8 @@ void focusclient(Client *c, int lift) {
} }
/* Deactivate old client if focus is changing */ /* Deactivate old client if focus is changing */
if (old_keyboard_focus_surface && (!c || client_surface(c) != old_keyboard_focus_surface)) { if (old_keyboard_focus_surface &&
(!c || client_surface(c) != old_keyboard_focus_surface)) {
/* If an overlay is focused, don't focus or activate the client, /* If an overlay is focused, don't focus or activate the client,
* but only update its position in fstack to render its border with * but only update its position in fstack to render its border with
* focuscolor and focus it after the overlay is closed. */ * focuscolor and focus it after the overlay is closed. */
@@ -2699,8 +2718,8 @@ void focusclient(Client *c, int lift) {
return; return;
} else if (w && w == exclusive_focus && client_wants_focus(w)) { } else if (w && w == exclusive_focus && client_wants_focus(w)) {
return; return;
/* Don't deactivate old_keyboard_focus_surface client if the new one wants focus, as this causes /* Don't deactivate old_keyboard_focus_surface client if the new one wants
* issues with winecfg and probably other clients */ * focus, as this causes issues with winecfg and probably other clients */
} else if (w && !client_is_unmanaged(w) && (!c || !client_wants_focus(c))) { } else if (w && !client_is_unmanaged(w) && (!c || !client_wants_focus(c))) {
setborder_color(w); setborder_color(w);
@@ -2937,7 +2956,8 @@ keypress(struct wl_listener *listener, void *data) {
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
// ov tab mode detect moe key release // ov tab mode detect moe key release
if (ov_tab_mode && !locked && event->state == WL_KEYBOARD_KEY_STATE_RELEASED && if (ov_tab_mode && !locked &&
event->state == WL_KEYBOARD_KEY_STATE_RELEASED &&
(keycode == 133 || keycode == 37 || keycode == 64 || keycode == 50 || (keycode == 133 || keycode == 37 || keycode == 64 || keycode == 50 ||
keycode == 134 || keycode == 105 || keycode == 108 || keycode == 62) && keycode == 134 || keycode == 105 || keycode == 108 || keycode == 62) &&
selmon->sel) { selmon->sel) {
@@ -3110,10 +3130,14 @@ mapnotify(struct wl_listener *listener, void *data) {
c->scroller_proportion = scroller_default_proportion; c->scroller_proportion = scroller_default_proportion;
c->is_open_animation = true; c->is_open_animation = true;
// nop // nop
if (new_is_master && strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name , "scroller") != 0) if (new_is_master &&
strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name,
"scroller") != 0)
// tile at the top // tile at the top
wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈 wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈
else if (strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name , "scroller") == 0 && selmon->sel && selmon->sel->istiled) { else if (strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name,
"scroller") == 0 &&
selmon->sel && selmon->sel->istiled) {
selmon->sel->link.next->prev = &c->link; selmon->sel->link.next->prev = &c->link;
c->link.prev = &selmon->sel->link; c->link.prev = &selmon->sel->link;
c->link.next = selmon->sel->link.next; c->link.next = selmon->sel->link.next;
@@ -3246,7 +3270,8 @@ monocle(Monitor *m,unsigned int gappo, unsigned int gappi) {
int n = 0; int n = 0;
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen || c->ismaxmizescreen || c->iskilling || c->animation.tagouting) if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen ||
c->ismaxmizescreen || c->iskilling || c->animation.tagouting)
continue; continue;
resize(c, m->w, 0); resize(c, m->w, 0);
n++; n++;
@@ -3563,7 +3588,8 @@ printstatus(void) {
printf("%s selmon %u\n", m->wlr_output->name, m == selmon); printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ,
m->tagset[m->seltags], sel, urg); m->tagset[m->seltags], sel, urg);
printf("%s layout %s\n", m->wlr_output->name, m->pertag->ltidxs[m->pertag->curtag]->symbol); printf("%s layout %s\n", m->wlr_output->name,
m->pertag->ltidxs[m->pertag->curtag]->symbol);
dwl_ipc_output_printstatus(m); // 更新waybar上tag的状态 这里很关键 dwl_ipc_output_printstatus(m); // 更新waybar上tag的状态 这里很关键
} }
fflush(stdout); fflush(stdout);
@@ -3789,7 +3815,9 @@ int is_special_animaiton_rule(Client *c) {
} }
} }
if (strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name , "scroller") == 0 && !c->isfloating) { if (strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name,
"scroller") == 0 &&
!c->isfloating) {
return DOWN; return DOWN;
} else if (visible_client_number < 2 && !c->isfloating) { } else if (visible_client_number < 2 && !c->isfloating) {
return DOWN; return DOWN;
@@ -3882,7 +3910,8 @@ void resize(Client *c, struct wlr_box geo, int interact) {
// oldgeom = c->geom; // oldgeom = c->geom;
bbox = interact ? &sgeom : &c->mon->w; bbox = interact ? &sgeom : &c->mon->w;
if(strcmp(c->mon->pertag->ltidxs[c->mon->pertag->curtag]->name , "scroller") == 0) { if (strcmp(c->mon->pertag->ltidxs[c->mon->pertag->curtag]->name,
"scroller") == 0) {
c->geom = geo; c->geom = geo;
} else { // 这里会限制不允许窗口划出屏幕 } else { // 这里会限制不允许窗口划出屏幕
client_set_bounds( client_set_bounds(
@@ -4169,15 +4198,15 @@ void switch_layout(const Arg *arg) {
int jk; int jk;
for (jk = 0; jk < LENGTH(layouts); jk++) { for (jk = 0; jk < LENGTH(layouts); jk++) {
if(strcmp(layouts[jk].name , selmon->pertag->ltidxs[selmon->pertag->curtag]->name) == 0) { if (strcmp(layouts[jk].name,
selmon->pertag->ltidxs[selmon->pertag->curtag] = jk == LENGTH(layouts) - 1? &layouts[0] : &layouts[jk+1]; selmon->pertag->ltidxs[selmon->pertag->curtag]->name) == 0) {
selmon->pertag->ltidxs[selmon->pertag->curtag] =
jk == LENGTH(layouts) - 1 ? &layouts[0] : &layouts[jk + 1];
arrange(selmon, false); arrange(selmon, false);
printstatus(); printstatus();
return; return;
} }
} }
} }
/* arg > 1.0 will set mfact absolutely */ /* arg > 1.0 will set mfact absolutely */
@@ -4186,7 +4215,8 @@ void // 17
setmfact(const Arg *arg) { setmfact(const Arg *arg) {
float f; float f;
if (!arg || !selmon || !selmon->pertag->ltidxs[selmon->pertag->curtag]->arrange) if (!arg || !selmon ||
!selmon->pertag->ltidxs[selmon->pertag->curtag]->arrange)
return; return;
f = arg->f < 1.0 ? arg->f + selmon->pertag->mfacts[selmon->pertag->curtag] f = arg->f < 1.0 ? arg->f + selmon->pertag->mfacts[selmon->pertag->curtag]
: arg->f - 1.0; : arg->f - 1.0;
@@ -4306,9 +4336,7 @@ void handle_foreign_destroy(struct wl_listener *listener, void *data) {
} }
} }
void signalhandler(int signalnumber) {
void signalhandler(int signalnumber)
{
void *array[64]; void *array[64];
size_t size; size_t size;
char **strings; char **strings;
@@ -4356,16 +4384,21 @@ void free_config(void) {
int i; int i;
for (i = 0; i < config.window_rules_count; i++) { for (i = 0; i < config.window_rules_count; i++) {
ConfigWinRule *rule = &config.window_rules[i]; ConfigWinRule *rule = &config.window_rules[i];
if (rule->id) free((void *)rule->id); if (rule->id)
if (rule->title) free((void *)rule->title); free((void *)rule->id);
if (rule->animation_type) free((void *)rule->animation_type); if (rule->title)
free((void *)rule->title);
if (rule->animation_type)
free((void *)rule->animation_type);
} }
free(config.window_rules); free(config.window_rules);
for (i = 0; i < config.monitor_rules_count; i++) { for (i = 0; i < config.monitor_rules_count; i++) {
ConfigMonitorRule *rule = &config.monitor_rules[i]; ConfigMonitorRule *rule = &config.monitor_rules[i];
if (rule->name) free((void *)rule->name); if (rule->name)
if (rule->layout) free((void *)rule->layout); free((void *)rule->name);
if (rule->layout)
free((void *)rule->layout);
} }
free(config.monitor_rules); free(config.monitor_rules);
@@ -4392,7 +4425,6 @@ void free_config(void) {
} }
} }
free(config.axis_bindings); free(config.axis_bindings);
} }
void override_config(void) { void override_config(void) {
@@ -4407,7 +4439,8 @@ void override_config(void) {
// 复制数组类型的变量 // 复制数组类型的变量
memcpy(animation_curve, config.animation_curve, sizeof(animation_curve)); memcpy(animation_curve, config.animation_curve, sizeof(animation_curve));
memcpy(scroller_proportion_preset, config.scroller_proportion_preset, sizeof(scroller_proportion_preset)); memcpy(scroller_proportion_preset, config.scroller_proportion_preset,
sizeof(scroller_proportion_preset));
scroller_structs = config.scroller_structs; scroller_structs = config.scroller_structs;
scroller_default_proportion = config.scroller_default_proportion; scroller_default_proportion = config.scroller_default_proportion;
@@ -4438,7 +4471,8 @@ void override_config(void) {
memcpy(rootcolor, config.rootcolor, sizeof(rootcolor)); memcpy(rootcolor, config.rootcolor, sizeof(rootcolor));
memcpy(bordercolor, config.bordercolor, sizeof(bordercolor)); memcpy(bordercolor, config.bordercolor, sizeof(bordercolor));
memcpy(focuscolor, config.focuscolor, sizeof(focuscolor)); memcpy(focuscolor, config.focuscolor, sizeof(focuscolor));
memcpy(maxmizescreencolor, config.maxmizescreencolor, sizeof(maxmizescreencolor)); memcpy(maxmizescreencolor, config.maxmizescreencolor,
sizeof(maxmizescreencolor));
memcpy(urgentcolor, config.urgentcolor, sizeof(urgentcolor)); memcpy(urgentcolor, config.urgentcolor, sizeof(urgentcolor));
memcpy(scratchpadcolor, config.scratchpadcolor, sizeof(scratchpadcolor)); memcpy(scratchpadcolor, config.scratchpadcolor, sizeof(scratchpadcolor));
memcpy(globalcolor, config.globalcolor, sizeof(globalcolor)); memcpy(globalcolor, config.globalcolor, sizeof(globalcolor));
@@ -4468,13 +4502,12 @@ void parse_config(void) {
} }
// 构建日志文件路径 // 构建日志文件路径
snprintf(filename, sizeof(filename), "%s/.config/maomao/config.conf", homedir); snprintf(filename, sizeof(filename), "%s/.config/maomao/config.conf",
homedir);
parse_config_file(&config, filename); parse_config_file(&config, filename);
override_config(); override_config();
} }
void reload_config(const Arg *arg) { void reload_config(const Arg *arg) {
@@ -4484,7 +4517,6 @@ void reload_config(const Arg *arg) {
void setup(void) { void setup(void) {
signal(SIGSEGV, signalhandler); signal(SIGSEGV, signalhandler);
parse_config(); parse_config();
@@ -4834,16 +4866,14 @@ void overview(Monitor *m, unsigned int gappo, unsigned int gappi) {
grid(m, overviewgappo, overviewgappi); grid(m, overviewgappo, overviewgappi);
} }
void fibonacci(Monitor *mon, int s) { void fibonacci(Monitor *mon, int s) {
unsigned int i = 0, n = 0, nx, ny, nw, nh; unsigned int i = 0, n = 0, nx, ny, nw, nh;
Client *c; Client *c;
wl_list_for_each(c, &clients, link) wl_list_for_each(c, &clients, link) if (VISIBLEON(c, mon) && !c->isfloating &&
if (VISIBLEON(c, mon) && !c->isfloating && !c->iskilling !c->iskilling && !c->isfullscreen &&
&& !c->isfullscreen && !c->ismaxmizescreen !c->ismaxmizescreen &&
&& !c->animation.tagouting) !c->animation.tagouting) n++;
n++;
if (n == 0) if (n == 0)
return; return;
@@ -4852,12 +4882,11 @@ void fibonacci(Monitor *mon, int s) {
nw = mon->w.width - gappoh; nw = mon->w.width - gappoh;
nh = mon->w.height - gappov; nh = mon->w.height - gappov;
wl_list_for_each(c, &clients, link) wl_list_for_each(c, &clients, link) if (VISIBLEON(c, mon) && !c->isfloating &&
if (VISIBLEON(c, mon) && !c->isfloating && !c->iskilling !c->iskilling && !c->isfullscreen &&
&& !c->isfullscreen && !c->ismaxmizescreen !c->ismaxmizescreen &&
&& !c->animation.tagouting) { !c->animation.tagouting) {
if((i % 2 && nh / 2 > 2 * c->bw) if ((i % 2 && nh / 2 > 2 * c->bw) || (!(i % 2) && nw / 2 > 2 * c->bw)) {
|| (!(i % 2) && nw / 2 > 2 * c->bw)) {
if (i < n - 1) { if (i < n - 1) {
if (i % 2) if (i % 2)
nh /= 2; nh /= 2;
@@ -4873,8 +4902,7 @@ void fibonacci(Monitor *mon, int s) {
ny += nh; ny += nh;
else else
ny -= nh; ny -= nh;
} } else if ((i % 4) == 1)
else if((i % 4) == 1)
nx += nw; nx += nw;
else if ((i % 4) == 2) else if ((i % 4) == 2)
ny += nh; ny += nh;
@@ -4884,29 +4912,28 @@ void fibonacci(Monitor *mon, int s) {
else else
nx -= nw; nx -= nw;
} }
if(i == 0) if (i == 0) {
{
if (n != 1) if (n != 1)
nw = (mon->w.width - gappoh) * mon->pertag->mfacts[mon->pertag->curtag]; nw = (mon->w.width - gappoh) *
mon->pertag->mfacts[mon->pertag->curtag];
ny = mon->w.y + gappov; ny = mon->w.y + gappov;
} } else if (i == 1)
else if(i == 1)
nw = mon->w.width - gappoh - nw; nw = mon->w.width - gappoh - nw;
i++; i++;
} }
resize(c, (struct wlr_box){.x = nx, .y = ny, resize(c,
.width = nw - gappih, .height = nh - gappiv}, 0); (struct wlr_box){
.x = nx, .y = ny, .width = nw - gappih, .height = nh - gappiv},
0);
} }
} }
void void dwindle(Monitor *mon, unsigned int gappo, unsigned int gappi) {
dwindle(Monitor *mon,unsigned int gappo, unsigned int gappi) {
fibonacci(mon, 1); fibonacci(mon, 1);
} }
void void spiral(Monitor *mon, unsigned int gappo, unsigned int gappi) {
spiral(Monitor *mon, unsigned int gappo, unsigned int gappi) {
fibonacci(mon, 0); fibonacci(mon, 0);
} }
@@ -4922,7 +4949,8 @@ void grid(Monitor *m, unsigned int gappo, unsigned int gappi) {
// 第一次遍历,计算 n 的值 // 第一次遍历,计算 n 的值
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, c->mon) && !c->iskilling && !c->animation.tagouting && c->mon == selmon) { if (VISIBLEON(c, c->mon) && !c->iskilling && !c->animation.tagouting &&
c->mon == selmon) {
n++; n++;
} }
} }
@@ -4941,7 +4969,8 @@ void grid(Monitor *m, unsigned int gappo, unsigned int gappi) {
// 第二次遍历,填充 tempClients // 第二次遍历,填充 tempClients
n = 0; n = 0;
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, c->mon) && !c->iskilling && !c->animation.tagouting && c->mon == selmon) { if (VISIBLEON(c, c->mon) && !c->iskilling && !c->animation.tagouting &&
c->mon == selmon) {
tempClients[n] = c; tempClients[n] = c;
n++; n++;
} }
@@ -5018,8 +5047,9 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
// 第一次遍历,计算 n 的值 // 第一次遍历,计算 n 的值
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, c->mon) && !c->isfloating && !c->isfullscreen && !c->ismaxmizescreen && !c->iskilling && if (VISIBLEON(c, c->mon) && !c->isfloating && !c->isfullscreen &&
!c->animation.tagouting && c->mon == selmon) { !c->ismaxmizescreen && !c->iskilling && !c->animation.tagouting &&
c->mon == selmon) {
n++; n++;
} }
} }
@@ -5038,8 +5068,9 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
// 第二次遍历,填充 tempClients // 第二次遍历,填充 tempClients
n = 0; n = 0;
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, c->mon) && !c->isfloating && !c->isfullscreen && !c->ismaxmizescreen && !c->iskilling && if (VISIBLEON(c, c->mon) && !c->isfloating && !c->isfullscreen &&
!c->animation.tagouting && c->mon == selmon) { !c->ismaxmizescreen && !c->iskilling && !c->animation.tagouting &&
c->mon == selmon) {
tempClients[n] = c; tempClients[n] = c;
n++; n++;
} }
@@ -5051,14 +5082,17 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
target_geom.width = max_client_width * c->scroller_proportion; target_geom.width = max_client_width * c->scroller_proportion;
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; 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; 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); resizeclient(c, target_geom.x, target_geom.y, target_geom.width,
target_geom.height, 0);
free(tempClients); // 释放内存 free(tempClients); // 释放内存
return; return;
} }
if (selmon->sel && selmon->sel->istiled && !c->ismaxmizescreen && !c->isfullscreen) { if (selmon->sel && selmon->sel->istiled && !c->ismaxmizescreen &&
!c->isfullscreen) {
root_client = selmon->sel; root_client = selmon->sel;
} else if (selmon->prevsel && selmon->prevsel->istiled && !c->ismaxmizescreen && !c->isfullscreen) { } else if (selmon->prevsel && selmon->prevsel->istiled &&
!c->ismaxmizescreen && !c->isfullscreen) {
root_client = selmon->prevsel; root_client = selmon->prevsel;
} else { } else {
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
@@ -5089,14 +5123,18 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
if (need_scroller) { if (need_scroller) {
if (scoller_focus_center || if (scoller_focus_center || selmon->prevsel == NULL ||
selmon->prevsel == NULL || (selmon->prevsel->scroller_proportion * max_client_width) +
(selmon->prevsel->scroller_proportion * max_client_width) + (root_client->scroller_proportion * max_client_width) > m->w.width - 2 * scroller_structs - gappih) { (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; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
} else { } else {
target_geom.x = root_client->geom.x > m->w.x + (m->w.width) / 2 ? target_geom.x =
m->w.x + (m->w.width - root_client->scroller_proportion * max_client_width - scroller_structs) : root_client->geom.x > m->w.x + (m->w.width) / 2
m->w.x + scroller_structs; ? 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); resize(tempClients[focus_client_index], target_geom, 0);
} else { } else {
@@ -5106,13 +5144,15 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) {
for (i = 1; i <= focus_client_index; i++) { for (i = 1; i <= focus_client_index; i++) {
c = tempClients[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; target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - gappih -
target_geom.width;
resize(c, target_geom, 0); resize(c, target_geom, 0);
} }
for (i = 1; i < n - focus_client_index; i++) { for (i = 1; i < n - focus_client_index; i++) {
c = tempClients[focus_client_index + 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; 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); resize(c, target_geom, 0);
} }
@@ -5228,7 +5268,8 @@ void switch_proportion_preset(const Arg *arg) {
target_proportion = scroller_proportion_preset[0]; target_proportion = scroller_proportion_preset[0];
} }
unsigned int max_client_width = selmon->w.width - 2 * scroller_structs - gappih; unsigned int max_client_width =
selmon->w.width - 2 * scroller_structs - gappih;
selmon->sel->scroller_proportion = target_proportion; selmon->sel->scroller_proportion = target_proportion;
selmon->sel->geom.width = max_client_width * target_proportion; selmon->sel->geom.width = max_client_width * target_proportion;
// resize(selmon->sel, selmon->sel->geom, 0); // resize(selmon->sel, selmon->sel->geom, 0);
@@ -5238,7 +5279,8 @@ void switch_proportion_preset(const Arg *arg) {
void set_proportion(const Arg *arg) { void set_proportion(const Arg *arg) {
if (selmon->sel) { if (selmon->sel) {
unsigned int max_client_width = selmon->w.width - 2 * scroller_structs - gappih; unsigned int max_client_width =
selmon->w.width - 2 * scroller_structs - gappih;
selmon->sel->scroller_proportion = arg->f; selmon->sel->scroller_proportion = arg->f;
selmon->sel->geom.width = max_client_width * arg->f; selmon->sel->geom.width = max_client_width * arg->f;
// resize(selmon->sel, selmon->sel->geom, 0); // resize(selmon->sel, selmon->sel->geom, 0);
@@ -5288,8 +5330,7 @@ void toggleoverview(const Arg *arg) {
} }
} else { } else {
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (c && if (c && !c->iskilling && client_surface(c)->mapped)
!c->iskilling && client_surface(c)->mapped)
overview_restore(c, &(Arg){.ui = target}); overview_restore(c, &(Arg){.ui = target});
} }
} }
@@ -5299,7 +5340,6 @@ void toggleoverview(const Arg *arg) {
if (ov_tab_mode && selmon->isoverview && selmon->sel) { if (ov_tab_mode && selmon->isoverview && selmon->sel) {
focusstack(&(Arg){.i = 1}); focusstack(&(Arg){.i = 1});
} }
} }
void tile(Monitor *m, unsigned int gappo, unsigned int uappi) { void tile(Monitor *m, unsigned int gappo, unsigned int uappi) {
@@ -5934,7 +5974,9 @@ void toggleglobal(const Arg *arg) {
void zoom(const Arg *arg) { void zoom(const Arg *arg) {
Client *c, *sel = focustop(selmon); Client *c, *sel = focustop(selmon);
if (!sel || !selmon || !selmon->pertag->ltidxs[selmon->pertag->curtag]->arrange || sel->isfloating) if (!sel || !selmon ||
!selmon->pertag->ltidxs[selmon->pertag->curtag]->arrange ||
sel->isfloating)
return; return;
/* Search for the first tiled window that is not sel, marking sel as /* Search for the first tiled window that is not sel, marking sel as
@@ -6007,7 +6049,8 @@ configurex11(struct wl_listener *listener, void *data) {
event->width, event->height); event->width, event->height);
return; return;
} }
if ((c->isfloating && c != grabc) || !c->mon->pertag->ltidxs[c->mon->pertag->curtag]->arrange) if ((c->isfloating && c != grabc) ||
!c->mon->pertag->ltidxs[c->mon->pertag->curtag]->arrange)
resize(c, resize(c,
(struct wlr_box){.x = event->x - c->bw, (struct wlr_box){.x = event->x - c->bw,
.y = event->y - c->bw, .y = event->y - c->bw,
@@ -6105,7 +6148,7 @@ int main(int argc, char *argv[]) {
else if (c == 'd') else if (c == 'd')
log_level = WLR_DEBUG; log_level = WLR_DEBUG;
else if (c == 'v') else if (c == 'v')
die("dwl " VERSION); die("maomao " VERSION);
else else
goto usage; goto usage;
} }

View File

@@ -1,5 +1,5 @@
project('maomao', ['c', 'cpp'], project('maomao', ['c', 'cpp'],
version : '0.1' version : '0.1.1'
) )
subdir('protocols') subdir('protocols')

View File

@@ -1,7 +1,7 @@
#include <stdint.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <string.h>
typedef struct { typedef struct {
const char *id; const char *id;
@@ -48,7 +48,6 @@ typedef struct {
Arg arg; Arg arg;
} AxisBinding; } AxisBinding;
typedef struct { typedef struct {
int animations; int animations;
char animation_type[10]; char animation_type[10];
@@ -177,16 +176,20 @@ uint32_t parse_mod(const char *mod_str) {
lower_str[i] = '\0'; // 确保字符串以 NULL 结尾 lower_str[i] = '\0'; // 确保字符串以 NULL 结尾
// 检查修饰键,忽略左右键标识(如 "_l" 和 "_r" // 检查修饰键,忽略左右键标识(如 "_l" 和 "_r"
if (strstr(lower_str, "super") || strstr(lower_str, "super_l") || strstr(lower_str, "super_r")) { if (strstr(lower_str, "super") || strstr(lower_str, "super_l") ||
strstr(lower_str, "super_r")) {
mod |= WLR_MODIFIER_LOGO; mod |= WLR_MODIFIER_LOGO;
} }
if (strstr(lower_str, "ctrl") || strstr(lower_str, "ctrl_l") || strstr(lower_str, "ctrl_r")) { if (strstr(lower_str, "ctrl") || strstr(lower_str, "ctrl_l") ||
strstr(lower_str, "ctrl_r")) {
mod |= WLR_MODIFIER_CTRL; mod |= WLR_MODIFIER_CTRL;
} }
if (strstr(lower_str, "shift") || strstr(lower_str, "shift_l") || strstr(lower_str, "shift_r")) { if (strstr(lower_str, "shift") || strstr(lower_str, "shift_l") ||
strstr(lower_str, "shift_r")) {
mod |= WLR_MODIFIER_SHIFT; mod |= WLR_MODIFIER_SHIFT;
} }
if (strstr(lower_str, "alt") || strstr(lower_str, "alt_l") || strstr(lower_str, "alt_r")) { if (strstr(lower_str, "alt") || strstr(lower_str, "alt_l") ||
strstr(lower_str, "alt_r")) {
mod |= WLR_MODIFIER_ALT; mod |= WLR_MODIFIER_ALT;
} }
@@ -223,7 +226,6 @@ xkb_keysym_t parse_keysym(const char *keysym_str) {
typedef void (*FuncType)(const Arg *); typedef void (*FuncType)(const Arg *);
int parseButton(const char *str) { int parseButton(const char *str) {
// 将输入字符串转换为小写 // 将输入字符串转换为小写
char lowerStr[20]; char lowerStr[20];
@@ -256,7 +258,6 @@ int parseButton(const char *str) {
} }
} }
int parseMouseAction(const char *str) { int parseMouseAction(const char *str) {
// 将输入字符串转换为小写 // 将输入字符串转换为小写
char lowerStr[20]; char lowerStr[20];
@@ -410,7 +411,9 @@ void parse_config_line(Config *config, const char *line) {
} else if (strcmp(key, "animation_duration_tag") == 0) { } else if (strcmp(key, "animation_duration_tag") == 0) {
config->animation_duration_tag = atoi(value); config->animation_duration_tag = atoi(value);
} else if (strcmp(key, "animation_curve") == 0) { } 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) { 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); fprintf(stderr, "Error: Invalid animation_curve format: %s\n", value);
} }
} else if (strcmp(key, "scroller_structs") == 0) { } else if (strcmp(key, "scroller_structs") == 0) {
@@ -420,8 +423,11 @@ void parse_config_line(Config *config, const char *line) {
} else if (strcmp(key, "scoller_focus_center") == 0) { } else if (strcmp(key, "scoller_focus_center") == 0) {
config->scoller_focus_center = atoi(value); config->scoller_focus_center = atoi(value);
} else if (strcmp(key, "scroller_proportion_preset") == 0) { } 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) { if (sscanf(value, "%f,%f,%f", &config->scroller_proportion_preset[0],
fprintf(stderr, "Error: Invalid scroller_proportion_preset format: %s\n", value); &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) { } else if (strcmp(key, "new_is_master") == 0) {
config->new_is_master = atoi(value); config->new_is_master = atoi(value);
@@ -513,7 +519,8 @@ void parse_config_line(Config *config, const char *line) {
parseColoer(config->globalcolor, color); parseColoer(config->globalcolor, color);
} }
} else if (strcmp(key, "autostart") == 0) { } else if (strcmp(key, "autostart") == 0) {
if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0], config->autostart[1], config->autostart[2]) != 3) { if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0],
config->autostart[1], config->autostart[2]) != 3) {
fprintf(stderr, "Error: Invalid autostart format: %s\n", value); fprintf(stderr, "Error: Invalid autostart format: %s\n", value);
} }
} else if (strcmp(key, "tags") == 0) { } else if (strcmp(key, "tags") == 0) {
@@ -522,7 +529,8 @@ void parse_config_line(Config *config, const char *line) {
if (sscanf(value, "id:%d,layout_name:%255[^\n]", &id, layout_name) == 2) { if (sscanf(value, "id:%d,layout_name:%255[^\n]", &id, layout_name) == 2) {
if (id >= 1 && id <= 9) { if (id >= 1 && id <= 9) {
config->tags[id - 1].id = id; config->tags[id - 1].id = id;
strncpy(config->tags[id - 1].layout_name, layout_name, sizeof(config->tags[id - 1].layout_name)); strncpy(config->tags[id - 1].layout_name, layout_name,
sizeof(config->tags[id - 1].layout_name));
} else { } else {
fprintf(stderr, "Error: Invalid tag id: %d\n", id); fprintf(stderr, "Error: Invalid tag id: %d\n", id);
} }
@@ -530,7 +538,9 @@ void parse_config_line(Config *config, const char *line) {
fprintf(stderr, "Error: Invalid tags format: %s\n", value); fprintf(stderr, "Error: Invalid tags format: %s\n", value);
} }
} else if (strcmp(key, "windowrule") == 0) { } else if (strcmp(key, "windowrule") == 0) {
config->window_rules = realloc(config->window_rules, (config->window_rules_count + 1) * sizeof(ConfigWinRule)); config->window_rules =
realloc(config->window_rules,
(config->window_rules_count + 1) * sizeof(ConfigWinRule));
if (!config->window_rules) { if (!config->window_rules) {
fprintf(stderr, "Error: Failed to allocate memory for window rules\n"); fprintf(stderr, "Error: Failed to allocate memory for window rules\n");
return; return;
@@ -551,7 +561,6 @@ void parse_config_line(Config *config, const char *line) {
rule->title = NULL; rule->title = NULL;
rule->tags = 0; rule->tags = 0;
char *token = strtok(value, ","); char *token = strtok(value, ",");
while (token != NULL) { while (token != NULL) {
char *colon = strchr(token, ':'); char *colon = strchr(token, ':');
@@ -588,33 +597,32 @@ void parse_config_line(Config *config, const char *line) {
} }
config->window_rules_count++; config->window_rules_count++;
} else if (strcmp(key, "monitorrule") == 0) { } else if (strcmp(key, "monitorrule") == 0) {
config->monitor_rules = realloc(config->monitor_rules, (config->monitor_rules_count + 1) * sizeof(ConfigMonitorRule)); config->monitor_rules =
realloc(config->monitor_rules,
(config->monitor_rules_count + 1) * sizeof(ConfigMonitorRule));
if (!config->monitor_rules) { if (!config->monitor_rules) {
fprintf(stderr, "Error: Failed to allocate memory for monitor rules\n"); fprintf(stderr, "Error: Failed to allocate memory for monitor rules\n");
return; return;
} }
ConfigMonitorRule *rule = &config->monitor_rules[config->monitor_rules_count]; ConfigMonitorRule *rule =
&config->monitor_rules[config->monitor_rules_count];
memset(rule, 0, sizeof(ConfigMonitorRule)); memset(rule, 0, sizeof(ConfigMonitorRule));
char layout[256], name[256]; char layout[256], name[256];
int parsed = sscanf(value, "%255[^,],%f,%d,%255[^,],%d,%f,%d,%d", int parsed = sscanf(value, "%255[^,],%f,%d,%255[^,],%d,%f,%d,%d", name,
name, &rule->mfact, &rule->nmaster, layout, &rule->rr,
&rule->mfact, &rule->scale, &rule->x, &rule->y);
&rule->nmaster,
layout,
&rule->rr,
&rule->scale,
&rule->x,
&rule->y);
if (parsed == 8) { if (parsed == 8) {
rule->name = strdup(name); rule->name = strdup(name);
rule->layout = strdup(layout); rule->layout = strdup(layout);
if (!rule->name || !rule->layout) { if (!rule->name || !rule->layout) {
if (rule->name) free((void *)rule->name); if (rule->name)
if (rule->layout) free((void *)rule->layout); free((void *)rule->name);
if (rule->layout)
free((void *)rule->layout);
fprintf(stderr, "Error: Failed to allocate memory for monitor rule\n"); fprintf(stderr, "Error: Failed to allocate memory for monitor rule\n");
return; return;
} }
@@ -624,7 +632,9 @@ void parse_config_line(Config *config, const char *line) {
fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value); fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value);
} }
} else if (strncmp(key, "bind", 4) == 0) { } else if (strncmp(key, "bind", 4) == 0) {
config->key_bindings = realloc(config->key_bindings, (config->key_bindings_count + 1) * sizeof(KeyBinding)); config->key_bindings =
realloc(config->key_bindings,
(config->key_bindings_count + 1) * sizeof(KeyBinding));
if (!config->key_bindings) { if (!config->key_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for key bindings\n"); fprintf(stderr, "Error: Failed to allocate memory for key bindings\n");
return; return;
@@ -634,7 +644,8 @@ void parse_config_line(Config *config, const char *line) {
memset(binding, 0, sizeof(KeyBinding)); memset(binding, 0, sizeof(KeyBinding));
char mod_str[256], keysym_str[256], func_name[256], arg_value[256] = "none"; 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) { if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, keysym_str,
func_name, arg_value) < 3) {
fprintf(stderr, "Error: Invalid bind format: %s\n", value); fprintf(stderr, "Error: Invalid bind format: %s\n", value);
return; return;
} }
@@ -650,17 +661,21 @@ void parse_config_line(Config *config, const char *line) {
} }
} else if (strncmp(key, "mousebind", 9) == 0) { } else if (strncmp(key, "mousebind", 9) == 0) {
config->mouse_bindings = realloc(config->mouse_bindings, (config->mouse_bindings_count + 1) * sizeof(MouseBinding)); config->mouse_bindings =
realloc(config->mouse_bindings,
(config->mouse_bindings_count + 1) * sizeof(MouseBinding));
if (!config->mouse_bindings) { if (!config->mouse_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for mouse bindings\n"); fprintf(stderr, "Error: Failed to allocate memory for mouse bindings\n");
return; return;
} }
MouseBinding *binding = &config->mouse_bindings[config->mouse_bindings_count]; MouseBinding *binding =
&config->mouse_bindings[config->mouse_bindings_count];
memset(binding, 0, sizeof(MouseBinding)); memset(binding, 0, sizeof(MouseBinding));
char mod_str[256], button_str[256], func_name[256], arg_value[256] = "none"; 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) { if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, button_str,
func_name, arg_value) < 3) {
fprintf(stderr, "Error: Invalid mousebind format: %s\n", value); fprintf(stderr, "Error: Invalid mousebind format: %s\n", value);
return; return;
} }
@@ -675,7 +690,9 @@ void parse_config_line(Config *config, const char *line) {
config->mouse_bindings_count++; config->mouse_bindings_count++;
} }
} else if (strncmp(key, "axisbind", 8) == 0) { } else if (strncmp(key, "axisbind", 8) == 0) {
config->axis_bindings = realloc(config->axis_bindings, (config->axis_bindings_count + 1) * sizeof(AxisBinding)); config->axis_bindings =
realloc(config->axis_bindings,
(config->axis_bindings_count + 1) * sizeof(AxisBinding));
if (!config->axis_bindings) { if (!config->axis_bindings) {
fprintf(stderr, "Error: Failed to allocate memory for axis bindings\n"); fprintf(stderr, "Error: Failed to allocate memory for axis bindings\n");
return; return;
@@ -685,7 +702,8 @@ void parse_config_line(Config *config, const char *line) {
memset(binding, 0, sizeof(AxisBinding)); memset(binding, 0, sizeof(AxisBinding));
char mod_str[256], dir_str[256], func_name[256], arg_value[256] = "none"; 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) { if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, dir_str, func_name,
arg_value) < 3) {
fprintf(stderr, "Error: Invalid axisbind format: %s\n", value); fprintf(stderr, "Error: Invalid axisbind format: %s\n", value);
return; return;
} }
@@ -715,7 +733,8 @@ void parse_config_file(Config *config, const char *file_path) {
char line[512]; char line[512];
while (fgets(line, sizeof(line), file)) { while (fgets(line, sizeof(line), file)) {
if (line[0] == '#' || line[0] == '\n') continue; if (line[0] == '#' || line[0] == '\n')
continue;
parse_config_line(config, line); parse_config_line(config, line);
} }

View File

@@ -1,9 +1,8 @@
/* speedie's maomao config */ /* speedie's maomao config */
#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \ #define COLOR(hex) \
((hex >> 16) & 0xFF) / 255.0f, \ {((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f, \
((hex >> 8) & 0xFF) / 255.0f, \ ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f}
(hex & 0xFF) / 255.0f }
/* animaion */ /* animaion */
char *animation_type = "slide"; // 是否启用动画 //slide,zoom char *animation_type = "slide"; // 是否启用动画 //slide,zoom
@@ -36,13 +35,14 @@ unsigned int gappiv = 5; /* vert inner gap between windows */
unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ unsigned int gappov = 10; /* vert outer gap between windows and screen edge */
int scroller_structs = 20; int scroller_structs = 20;
float scroller_default_proportion = 0.9; float scroller_default_proportion = 0.9;
int scoller_focus_center = 0; int scoller_focus_center = 0;
float scroller_proportion_preset[] = {0.5, 0.9, 1.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 */ 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 */ unsigned int borderpx = 4; /* border pixel of windows */
float rootcolor[] = COLOR(0x323232ff); float rootcolor[] = COLOR(0x323232ff);
float bordercolor[] = COLOR(0x444444ff); float bordercolor[] = COLOR(0x444444ff);
@@ -56,27 +56,24 @@ float globalcolor[] = COLOR(0xb153a7ff);
int overviewgappi = 5; /* overview时 窗口与边缘 缝隙大小 */ int overviewgappi = 5; /* overview时 窗口与边缘 缝隙大小 */
int overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */ int overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ /* 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}; float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
int warpcursor = 1; /* Warp cursor to focused client */ int warpcursor = 1; /* Warp cursor to focused client */
/* layout(s) */ /* layout(s) */
Layout overviewlayout = {"󰃇", overview, "overview"}; Layout overviewlayout = {"󰃇", overview, "overview"};
Layout layouts[] = { //最少两个,不能删除少于两个 Layout layouts[] = {
// 最少两个,不能删除少于两个
/* symbol arrange function name */ /* symbol arrange function name */
{"S", scroller, "scroller"}, // 滚动布局 {"S", scroller, "scroller"}, // 滚动布局
{"T", tile, "tile"}, // 堆栈布局 {"T", tile, "tile"}, // 堆栈布局
{"G", grid, "grid"}, {"G", grid, "grid"}, {"M", monocle, "monocle"},
{"M",monocle,"monocle"}, {"D", dwindle, "dwindle"}, {"P", spiral, "spiral"},
{"D",dwindle,"dwindle"},
{"P",spiral,"spiral"},
}; };
/* keyboard */ /* keyboard */
struct xkb_rule_names xkb_rules = { struct xkb_rule_names xkb_rules = {
/* can specify fields: rules, model, layout, variant, options */ /* can specify fields: rules, model, layout, variant, options */
@@ -110,7 +107,8 @@ LIBINPUT_CONFIG_CLICK_METHOD_NONE
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
*/ */
enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; enum libinput_config_click_method click_method =
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
/* You can choose between: /* You can choose between:
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
@@ -123,7 +121,8 @@ uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
*/ */
enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; enum libinput_config_accel_profile accel_profile =
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
double accel_speed = 0.0; double accel_speed = 0.0;
/* You can choose between: /* You can choose between:
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
@@ -135,21 +134,9 @@ enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
#define MODKEY WLR_MODIFIER_ALT #define MODKEY WLR_MODIFIER_ALT
static const char *tags[] = { static const char *tags[] = {
"1", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
}; };
static const char *const autostart[] = { static const char *const autostart[] = {
"/bin/sh", "/bin/sh", "-c", "~/.config/maomao/autostart.sh", NULL, NULL,
"-c",
"~/.config/maomao/autostart.sh",
NULL,
NULL,
}; };

7
util.c
View File

@@ -6,8 +6,7 @@
#include "util.h" #include "util.h"
void void die(const char *fmt, ...) {
die(const char *fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@@ -24,9 +23,7 @@ die(const char *fmt, ...) {
exit(1); exit(1);
} }
void * void *ecalloc(size_t nmemb, size_t size) {
ecalloc(size_t nmemb, size_t size)
{
void *p; void *p;
if (!(p = calloc(nmemb, size))) if (!(p = calloc(nmemb, size)))