From 860d186a3481093d8fb4f60364155055d6ad894f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 15 Feb 2025 18:35:22 +0800 Subject: [PATCH] opt: opt project structure --- IM.h | 133 ++-- cursor-shape-v1-protocol.h | 367 --------- main.c => maomao.c | 12 +- meson.build | 4 +- protocols/meson.build | 7 +- protocols/pointer-constraints-unstable-v1.xml | 339 --------- wlr_foreign_toplevel_management_v1.c | 712 ------------------ wlr_foreign_toplevel_management_v1.h | 153 ---- 8 files changed, 76 insertions(+), 1651 deletions(-) delete mode 100644 cursor-shape-v1-protocol.h rename main.c => maomao.c (99%) delete mode 100755 protocols/pointer-constraints-unstable-v1.xml delete mode 100755 wlr_foreign_toplevel_management_v1.c delete mode 100755 wlr_foreign_toplevel_management_v1.h diff --git a/IM.h b/IM.h index 0cb842d..d44c1e6 100644 --- a/IM.h +++ b/IM.h @@ -15,6 +15,9 @@ * in the focused state, wl_keyboard sent an enter as well. However, having * wl_keyboard focused doesn't mean that text-input will be focused. */ +// 这个relay这一层结构嵌套其实在dwl这里没啥用,暴露出结构成员定义作全局变量代码会更清晰,更符合dwl的风格 +// 但这个代码最初是日本人从sway那边抄过来的,sway的架构比较大,我猜会不会是考虑到会有两个input_method实例才这么定义 +// 为了考虑万一以后哪个版本要扩充,就保留外层的结构 struct dwl_input_method_relay { struct wl_list text_inputs; // dwl_text_input::link struct wlr_input_method_v2 *input_method; // doesn't have to be present @@ -46,7 +49,7 @@ struct dwl_text_input { struct wl_listener text_input_enable; //struct wl_listener text_input_commit; - struct wl_listener text_input_disable; + //struct wl_listener text_input_disable; struct wl_listener text_input_destroy; }; @@ -67,7 +70,7 @@ struct dwl_input_popup { struct wl_listener popup_map; struct wl_listener popup_unmap; struct wl_listener popup_destroy; - struct wl_listener popup_surface_commit; + //struct wl_listener popup_surface_commit; //struct wl_listener focused_surface_unmap; }; @@ -77,9 +80,7 @@ void dwl_input_method_relay_init(struct dwl_input_method_relay *relay); // seat. void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay, struct wlr_surface *surface); -struct dwl_text_input *dwl_text_input_create( - struct dwl_input_method_relay *relay, - struct wlr_text_input_v3 *text_input); + static void handle_im_grab_keyboard(struct wl_listener *listener, void *data); static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data); @@ -122,6 +123,7 @@ 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) { struct dwl_input_method_relay *relay = wl_container_of(listener, relay, input_method_grab_keyboard); + //wl_container_of 宏的第二个参数sample, 这里是relay,无须是已经初始化的变量,只要是返回值类型的变量就可以了,这里就是dwl_input_method_relay类型的变量 struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; // send modifier state to grab @@ -347,41 +349,8 @@ static void handle_pending_focused_surface_destroy(struct wl_listener *listener, wl_list_init(&text_input->pending_focused_surface_destroy.link); } -struct dwl_text_input *dwl_text_input_create( - struct dwl_input_method_relay *relay, - struct wlr_text_input_v3 *text_input) { - struct dwl_text_input *input; - input = calloc(1, sizeof(*input)); - if (!input) { - wlr_log(WLR_ERROR, "dwl_text_input_create calloc failed"); - return NULL; - } - wlr_log(WLR_INFO, "dwl_text_input_create"); - input->input = text_input; - input->relay = relay; - wl_list_insert(&relay->text_inputs, &input->link); - - input->text_input_enable.notify = handle_text_input_enable; - wl_signal_add(&text_input->events.enable, &input->text_input_enable); - - //input->text_input_commit.notify = handle_text_input_commit; - //wl_signal_add(&text_input->events.commit, &input->text_input_commit); - - /* input->text_input_disable.notify = handle_text_input_disable; */ - /* wl_signal_add(&text_input->events.disable, &input->text_input_disable); */ - - input->text_input_destroy.notify = handle_text_input_destroy; - wl_signal_add(&text_input->events.destroy, &input->text_input_destroy); - - input->pending_focused_surface_destroy.notify = - handle_pending_focused_surface_destroy; - wl_list_init(&input->pending_focused_surface_destroy.link); - - return input; -} - -static void relay_handle_text_input(struct wl_listener *listener, +static void relay_handle_text_input_new(struct wl_listener *listener, void *data) { struct dwl_input_method_relay *relay = wl_container_of(listener, relay, text_input_new); @@ -390,7 +359,33 @@ static void relay_handle_text_input(struct wl_listener *listener, return; } - dwl_text_input_create(relay, wlr_text_input); + struct dwl_text_input *input; + input = calloc(1, sizeof(*input)); + if (!input) { + wlr_log(WLR_ERROR, "dwl_text_input calloc failed"); + return; + } + wlr_log(WLR_INFO, "dwl_text_input calloc"); + input->input = wlr_text_input; + input->relay = relay; + + wl_list_insert(&relay->text_inputs, &input->link); + + input->text_input_enable.notify = handle_text_input_enable; + wl_signal_add(&wlr_text_input->events.enable, &input->text_input_enable); + + //input->text_input_commit.notify = handle_text_input_commit; + //wl_signal_add(&text_input->events.commit, &input->text_input_commit); + + /* input->text_input_disable.notify = handle_text_input_disable; */ + /* wl_signal_add(&text_input->events.disable, &input->text_input_disable); */ + + input->text_input_destroy.notify = handle_text_input_destroy; + wl_signal_add(&wlr_text_input->events.destroy, &input->text_input_destroy); + + input->pending_focused_surface_destroy.notify = + handle_pending_focused_surface_destroy; + wl_list_init(&input->pending_focused_surface_destroy.link); } @@ -405,6 +400,8 @@ static void get_parent_and_output_box(struct wlr_surface *focused_surface, struct wlr_output *output; struct wlr_box output_box_tmp; struct wlr_layer_surface_v1 *layer_surface; + Client *client = NULL; + LayerSurface *l = NULL; if ((layer_surface=wlr_layer_surface_v1_try_from_wlr_surface(focused_surface))) { LayerSurface* layer = @@ -417,10 +414,7 @@ static void get_parent_and_output_box(struct wlr_surface *focused_surface, 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,"get_parent_and_output_box layersurface parent->x %d y %d",parent->x,parent->y); } else { - //Client *client = client_from_wlr_surface(focused_surface); - Client *client = NULL; - LayerSurface *l = NULL; - int type = toplevel_from_wlr_surface(focused_surface, &client, &l); + toplevel_from_wlr_surface(focused_surface, &client, &l); output = wlr_output_layout_output_at(output_layout, client->geom.x, client->geom.y); @@ -441,9 +435,12 @@ static void get_parent_and_output_box(struct wlr_surface *focused_surface, 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就弹出在父窗口左上角 +// 根据 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) { struct wlr_surface* focused_surface; - struct wlr_box output_box, parent, cursor; + struct wlr_box output_box, parent, input_cursor; int x1, x2, y1, y2, x, y, available_right, available_left, available_down, available_up, popup_width, popup_height; bool cursor_rect, x1_in_bounds, y1_in_bounds, x2_in_bounds, y2_in_bounds; @@ -464,7 +461,7 @@ static void input_popup_update(struct dwl_input_popup *popup) { & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE; focused_surface = text_input->input->focused_surface; - cursor = text_input->input->current.cursor_rectangle; + input_cursor = text_input->input->current.cursor_rectangle; get_parent_and_output_box(focused_surface, &parent, &output_box); @@ -472,10 +469,10 @@ static void input_popup_update(struct dwl_input_popup *popup) { popup_height = popup->popup_surface->surface->current.height; if (!cursor_rect) { - cursor.x = 0; - cursor.y = 0; - cursor.width = parent.width; - cursor.height = parent.height; + input_cursor.x = 0; + input_cursor.y = 0; + input_cursor.width = parent.width; + input_cursor.height = parent.height; wlr_log(WLR_INFO,"input_popup_update !cursor_rect"); popup->x=parent.x; @@ -483,12 +480,12 @@ static void input_popup_update(struct dwl_input_popup *popup) { popup->visible=true; } else { - wlr_log(WLR_INFO,"input_popup_update cursor x %d y %d width %d height %d",cursor.x,cursor.y,cursor.width,cursor.height); + 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); - x1 = parent.x + cursor.x; - x2 = parent.x + cursor.x + cursor.width; - y1 = parent.y + cursor.y; - y2 = parent.y + cursor.y + cursor.height; + x1 = parent.x + input_cursor.x; + x2 = parent.x + input_cursor.x + input_cursor.width; + y1 = parent.y + input_cursor.y; + y2 = parent.y + input_cursor.y + input_cursor.height; x = x1; y = y2; @@ -510,21 +507,21 @@ static void input_popup_update(struct dwl_input_popup *popup) { popup->x = x; popup->y = y; - // Hide popup if cursor position is completely out of bounds - x1_in_bounds = (cursor.x >= 0 && cursor.x < parent.width); - y1_in_bounds = (cursor.y >= 0 && cursor.y < parent.height); - x2_in_bounds = (cursor.x + cursor.width >= 0 - && cursor.x + cursor.width < parent.width); - y2_in_bounds = (cursor.y + cursor.height >= 0 - && cursor.y + cursor.height < parent.height); + // Hide popup if input_cursor position is completely out of bounds + x1_in_bounds = (input_cursor.x >= 0 && input_cursor.x < parent.width); + y1_in_bounds = (input_cursor.y >= 0 && input_cursor.y < parent.height); + x2_in_bounds = (input_cursor.x + input_cursor.width >= 0 + && input_cursor.x + input_cursor.width < parent.width); + y2_in_bounds = (input_cursor.y + input_cursor.height >= 0 + && input_cursor.y + input_cursor.height < parent.height); popup->visible = (x1_in_bounds && y1_in_bounds) || (x2_in_bounds && y2_in_bounds); struct wlr_box box = { .x = x1 - x, .y = y1 - y, - .width = cursor.width, - .height = cursor.height, + .width = input_cursor.width, + .height = input_cursor.height, }; wlr_input_popup_surface_v2_send_text_input_rectangle( popup->popup_surface, &box); @@ -581,7 +578,7 @@ static void handle_im_popup_destroy(struct wl_listener *listener, void *data) { static void handle_im_new_popup_surface(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, input_method_new_popup_surface); @@ -607,7 +604,7 @@ static void handle_im_new_popup_surface(struct wl_listener *listener, void *data } -static void relay_handle_input_method(struct wl_listener *listener, +static void relay_handle_input_method_new(struct wl_listener *listener, void *data) { struct dwl_text_input *text_input; @@ -657,11 +654,11 @@ void dwl_input_method_relay_init(struct dwl_input_method_relay *relay) { relay->popup=NULL; - relay->text_input_new.notify = relay_handle_text_input; + relay->text_input_new.notify = relay_handle_text_input_new; wl_signal_add(&text_input_manager->events.text_input, &relay->text_input_new); - relay->input_method_new.notify = relay_handle_input_method; + relay->input_method_new.notify = relay_handle_input_method_new; wl_signal_add(&input_method_manager->events.input_method, &relay->input_method_new); } diff --git a/cursor-shape-v1-protocol.h b/cursor-shape-v1-protocol.h deleted file mode 100644 index 83e18af..0000000 --- a/cursor-shape-v1-protocol.h +++ /dev/null @@ -1,367 +0,0 @@ -/* Generated by wayland-scanner 1.22.0 */ - -#ifndef CURSOR_SHAPE_V1_SERVER_PROTOCOL_H -#define CURSOR_SHAPE_V1_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_cursor_shape_v1 The cursor_shape_v1 protocol - * @section page_ifaces_cursor_shape_v1 Interfaces - * - @subpage page_iface_wp_cursor_shape_manager_v1 - cursor shape manager - * - @subpage page_iface_wp_cursor_shape_device_v1 - cursor shape for a device - * @section page_copyright_cursor_shape_v1 Copyright - *
- *
- * Copyright 2018 The Chromium Authors
- * Copyright 2023 Simon Ser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- */ -struct wl_pointer; -struct wp_cursor_shape_device_v1; -struct wp_cursor_shape_manager_v1; -struct zwp_tablet_tool_v2; - -#ifndef WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE -#define WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE -/** - * @page page_iface_wp_cursor_shape_manager_v1 wp_cursor_shape_manager_v1 - * @section page_iface_wp_cursor_shape_manager_v1_desc Description - * - * This global offers an alternative, optional way to set cursor images. This - * new way uses enumerated cursors instead of a wl_surface like - * wl_pointer.set_cursor does. - * - * Warning! The protocol described in this file is currently in the testing - * phase. Backward compatible changes may be added together with the - * corresponding interface version bump. Backward incompatible changes can - * only be done by creating a new major version of the extension. - * @section page_iface_wp_cursor_shape_manager_v1_api API - * See @ref iface_wp_cursor_shape_manager_v1. - */ -/** - * @defgroup iface_wp_cursor_shape_manager_v1 The wp_cursor_shape_manager_v1 interface - * - * This global offers an alternative, optional way to set cursor images. This - * new way uses enumerated cursors instead of a wl_surface like - * wl_pointer.set_cursor does. - * - * Warning! The protocol described in this file is currently in the testing - * phase. Backward compatible changes may be added together with the - * corresponding interface version bump. Backward incompatible changes can - * only be done by creating a new major version of the extension. - */ -extern const struct wl_interface wp_cursor_shape_manager_v1_interface; -#endif -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE -#define WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE -/** - * @page page_iface_wp_cursor_shape_device_v1 wp_cursor_shape_device_v1 - * @section page_iface_wp_cursor_shape_device_v1_desc Description - * - * This interface advertises the list of supported cursor shapes for a - * device, and allows clients to set the cursor shape. - * @section page_iface_wp_cursor_shape_device_v1_api API - * See @ref iface_wp_cursor_shape_device_v1. - */ -/** - * @defgroup iface_wp_cursor_shape_device_v1 The wp_cursor_shape_device_v1 interface - * - * This interface advertises the list of supported cursor shapes for a - * device, and allows clients to set the cursor shape. - */ -extern const struct wl_interface wp_cursor_shape_device_v1_interface; -#endif - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - * @struct wp_cursor_shape_manager_v1_interface - */ -struct wp_cursor_shape_manager_v1_interface { - /** - * destroy the manager - * - * Destroy the cursor shape manager. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * manage the cursor shape of a pointer device - * - * Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. - */ - void (*get_pointer)(struct wl_client *client, - struct wl_resource *resource, - uint32_t cursor_shape_device, - struct wl_resource *pointer); - /** - * manage the cursor shape of a tablet tool device - * - * Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 - * object. - */ - void (*get_tablet_tool_v2)(struct wl_client *client, - struct wl_resource *resource, - uint32_t cursor_shape_device, - struct wl_resource *tablet_tool); -}; - - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2_SINCE_VERSION 1 - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * cursor shapes - * - * This enum describes cursor shapes. - * - * The names are taken from the CSS W3C specification: - * https://w3c.github.io/csswg-drafts/css-ui/#cursor - */ -enum wp_cursor_shape_device_v1_shape { - /** - * default cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT = 1, - /** - * a context menu is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU = 2, - /** - * help is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP = 3, - /** - * pointer that indicates a link or another interactive element - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER = 4, - /** - * progress indicator - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS = 5, - /** - * program is busy, user should wait - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT = 6, - /** - * a cell or set of cells may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL = 7, - /** - * simple crosshair - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR = 8, - /** - * text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT = 9, - /** - * vertical text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT = 10, - /** - * drag-and-drop: alias of/shortcut to something is to be created - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS = 11, - /** - * drag-and-drop: something is to be copied - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY = 12, - /** - * drag-and-drop: something is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE = 13, - /** - * drag-and-drop: the dragged item cannot be dropped at the current cursor location - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP = 14, - /** - * drag-and-drop: the requested action will not be carried out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED = 15, - /** - * drag-and-drop: something can be grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB = 16, - /** - * drag-and-drop: something is being grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING = 17, - /** - * resizing: the east border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE = 18, - /** - * resizing: the north border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE = 19, - /** - * resizing: the north-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE = 20, - /** - * resizing: the north-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE = 21, - /** - * resizing: the south border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE = 22, - /** - * resizing: the south-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE = 23, - /** - * resizing: the south-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE = 24, - /** - * resizing: the west border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE = 25, - /** - * resizing: the east and west borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE = 26, - /** - * resizing: the north and south borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE = 27, - /** - * resizing: the north-east and south-west corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE = 28, - /** - * resizing: the north-west and south-east corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE = 29, - /** - * resizing: that the item/column can be resized horizontally - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE = 30, - /** - * resizing: that the item/row can be resized vertically - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE = 31, - /** - * something can be scrolled in any direction - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL = 32, - /** - * something can be zoomed in - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN = 33, - /** - * something can be zoomed out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT = 34, -}; -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM */ - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -enum wp_cursor_shape_device_v1_error { - /** - * the specified shape value is invalid - */ - WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE = 1, -}; -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM */ - -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * @struct wp_cursor_shape_device_v1_interface - */ -struct wp_cursor_shape_device_v1_interface { - /** - * destroy the cursor shape device - * - * Destroy the cursor shape device. - * - * The device cursor shape remains unchanged. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * set device cursor to the shape - * - * Sets the device cursor to the specified shape. The compositor - * will change the cursor image based on the specified shape. - * - * The cursor actually changes only if the input device focus is - * one of the requesting client's surfaces. If any, the previous - * cursor image (surface or shape) is replaced. - * - * The "shape" argument must be a valid enum entry, otherwise the - * invalid_shape protocol error is raised. - * - * This is similar to the wl_pointer.set_cursor and - * zwp_tablet_tool_v2.set_cursor requests, but this request accepts - * a shape instead of contents in the form of a surface. Clients - * can mix set_cursor and set_shape requests. - * - * The serial parameter must match the latest wl_pointer.enter or - * zwp_tablet_tool_v2.proximity_in serial number sent to the - * client. Otherwise the request will be ignored. - * @param serial serial number of the enter event - */ - void (*set_shape)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - uint32_t shape); -}; - - -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE_SINCE_VERSION 1 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/main.c b/maomao.c similarity index 99% rename from main.c rename to maomao.c index 1f7e04e..c0a99c2 100644 --- a/main.c +++ b/maomao.c @@ -1,7 +1,6 @@ /* * See LICENSE file for copyright and license details. */ -#define XWAYLNAD 1 #include #include #include @@ -73,7 +72,7 @@ #include "dwl-ipc-unstable-v2-protocol.h" #include "util.h" -#include "wlr_foreign_toplevel_management_v1.h" +#include /* macros */ #define MAX(A, B) ((A) > (B) ? (A) : (B)) @@ -565,6 +564,7 @@ static unsigned int get_tags_first_tag(unsigned int tags); void client_commit(Client *c); void apply_border(Client *c, struct wlr_box clip_box,int offset); void client_set_opacity(Client *c, double opacity); +void init_baked_points(void); /* variables */ static const char broken[] = "broken"; @@ -697,7 +697,7 @@ struct vec2 calculate_animation_curve_at(double t) { return point; } -void init_baked_points() { +void init_baked_points(void) { baked_points = calloc(BAKED_POINTS_COUNT, sizeof(*baked_points)); for (size_t i = 0; i < BAKED_POINTS_COUNT; i++) { @@ -4226,11 +4226,11 @@ setsel(struct wl_listener *listener, void *data) { } // 获取tags中最坐标的tag的tagmask -unsigned int get_tags_first_tag(unsigned int tags) { +unsigned int get_tags_first_tag(unsigned int source_tags) { unsigned int i, target, tag; tag = 0; for (i = 0; !(tag & 1); i++) { - tag = tags >> i; + tag = source_tags >> i; } target = 1 << (i - 1); return target; @@ -4765,7 +4765,7 @@ void grid(Monitor *m, unsigned int gappo, unsigned int gappi) { void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) { unsigned int i, n; - Client *c, *root_client; + Client *c, *root_client = NULL; Client **tempClients = NULL; // 初始化为 NULL n = 0; struct wlr_box target_geom; diff --git a/meson.build b/meson.build index 09ab015..499bcac 100644 --- a/meson.build +++ b/meson.build @@ -34,10 +34,8 @@ if xcb.found() and xlibs.found() endif executable('maomao', - 'main.c', + 'maomao.c', 'util.c', - 'wlr_foreign_toplevel_management_v1.c', - 'wlr_foreign_toplevel_management_v1.h', wayland_sources, dependencies : [ libm, diff --git a/protocols/meson.build b/protocols/meson.build index 1e3d777..bf5796f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -12,11 +12,12 @@ wayland_scanner_client = generator( wayland_xmls = [ wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', - 'wlr-layer-shell-unstable-v1.xml', - 'pointer-constraints-unstable-v1.xml', + wl_protocol_dir + '/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', + wl_protocol_dir + '/staging/cursor-shape/cursor-shape-v1.xml', + wl_protocol_dir + '/stable/tablet/tablet-v2.xml', 'wlr-foreign-toplevel-management-unstable-v1.xml', 'dwl-ipc-unstable-v2.xml', - # 'cursor-shape-v1.xml' + 'wlr-layer-shell-unstable-v1.xml', ] wayland_sources = [ wayland_scanner_code.process(wayland_xmls), diff --git a/protocols/pointer-constraints-unstable-v1.xml b/protocols/pointer-constraints-unstable-v1.xml deleted file mode 100755 index efd64b6..0000000 --- a/protocols/pointer-constraints-unstable-v1.xml +++ /dev/null @@ -1,339 +0,0 @@ - - - - - Copyright © 2014 Jonas Ådahl - Copyright © 2015 Red Hat Inc. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - This protocol specifies a set of interfaces used for adding constraints to - the motion of a pointer. Possible constraints include confining pointer - motions to a given region, or locking it to its current position. - - In order to constrain the pointer, a client must first bind the global - interface "wp_pointer_constraints" which, if a compositor supports pointer - constraints, is exposed by the registry. Using the bound global object, the - client uses the request that corresponds to the type of constraint it wants - to make. See wp_pointer_constraints for more details. - - Warning! The protocol described in this file is experimental and backward - incompatible changes may be made. Backward compatible changes may be added - together with the corresponding interface version bump. Backward - incompatible changes are done by bumping the version number in the protocol - and interface names and resetting the interface version. Once the protocol - is to be declared stable, the 'z' prefix and the version number in the - protocol and interface names are removed and the interface version number is - reset. - - - - - The global interface exposing pointer constraining functionality. It - exposes two requests: lock_pointer for locking the pointer to its - position, and confine_pointer for locking the pointer to a region. - - The lock_pointer and confine_pointer requests create the objects - wp_locked_pointer and wp_confined_pointer respectively, and the client can - use these objects to interact with the lock. - - For any surface, only one lock or confinement may be active across all - wl_pointer objects of the same seat. If a lock or confinement is requested - when another lock or confinement is active or requested on the same surface - and with any of the wl_pointer objects of the same seat, an - 'already_constrained' error will be raised. - - - - - These errors can be emitted in response to wp_pointer_constraints - requests. - - - - - - - These values represent different lifetime semantics. They are passed - as arguments to the factory requests to specify how the constraint - lifetimes should be managed. - - - - A oneshot pointer constraint will never reactivate once it has been - deactivated. See the corresponding deactivation event - (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for - details. - - - - - A persistent pointer constraint may again reactivate once it has - been deactivated. See the corresponding deactivation event - (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for - details. - - - - - - - Used by the client to notify the server that it will no longer use this - pointer constraints object. - - - - - - The lock_pointer request lets the client request to disable movements of - the virtual pointer (i.e. the cursor), effectively locking the pointer - to a position. This request may not take effect immediately; in the - future, when the compositor deems implementation-specific constraints - are satisfied, the pointer lock will be activated and the compositor - sends a locked event. - - The protocol provides no guarantee that the constraints are ever - satisfied, and does not require the compositor to send an error if the - constraints cannot ever be satisfied. It is thus possible to request a - lock that will never activate. - - There may not be another pointer constraint of any kind requested or - active on the surface for any of the wl_pointer objects of the seat of - the passed pointer when requesting a lock. If there is, an error will be - raised. See general pointer lock documentation for more details. - - The intersection of the region passed with this request and the input - region of the surface is used to determine where the pointer must be - in order for the lock to activate. It is up to the compositor whether to - warp the pointer or require some kind of user interaction for the lock - to activate. If the region is null the surface input region is used. - - A surface may receive pointer focus without the lock being activated. - - The request creates a new object wp_locked_pointer which is used to - interact with the lock as well as receive updates about its state. See - the the description of wp_locked_pointer for further information. - - Note that while a pointer is locked, the wl_pointer objects of the - corresponding seat will not emit any wl_pointer.motion events, but - relative motion events will still be emitted via wp_relative_pointer - objects of the same seat. wl_pointer.axis and wl_pointer.button events - are unaffected. - - - - - - - - - - - The confine_pointer request lets the client request to confine the - pointer cursor to a given region. This request may not take effect - immediately; in the future, when the compositor deems implementation- - specific constraints are satisfied, the pointer confinement will be - activated and the compositor sends a confined event. - - The intersection of the region passed with this request and the input - region of the surface is used to determine where the pointer must be - in order for the confinement to activate. It is up to the compositor - whether to warp the pointer or require some kind of user interaction for - the confinement to activate. If the region is null the surface input - region is used. - - The request will create a new object wp_confined_pointer which is used - to interact with the confinement as well as receive updates about its - state. See the the description of wp_confined_pointer for further - information. - - - - - - - - - - - - The wp_locked_pointer interface represents a locked pointer state. - - While the lock of this object is active, the wl_pointer objects of the - associated seat will not emit any wl_pointer.motion events. - - This object will send the event 'locked' when the lock is activated. - Whenever the lock is activated, it is guaranteed that the locked surface - will already have received pointer focus and that the pointer will be - within the region passed to the request creating this object. - - To unlock the pointer, send the destroy request. This will also destroy - the wp_locked_pointer object. - - If the compositor decides to unlock the pointer the unlocked event is - sent. See wp_locked_pointer.unlock for details. - - When unlocking, the compositor may warp the cursor position to the set - cursor position hint. If it does, it will not result in any relative - motion events emitted via wp_relative_pointer. - - If the surface the lock was requested on is destroyed and the lock is not - yet activated, the wp_locked_pointer object is now defunct and must be - destroyed. - - - - - Destroy the locked pointer object. If applicable, the compositor will - unlock the pointer. - - - - - - Set the cursor position hint relative to the top left corner of the - surface. - - If the client is drawing its own cursor, it should update the position - hint to the position of its own cursor. A compositor may use this - information to warp the pointer upon unlock in order to avoid pointer - jumps. - - The cursor position hint is double buffered. The new hint will only take - effect when the associated surface gets it pending state applied. See - wl_surface.commit for details. - - - - - - - - Set a new region used to lock the pointer. - - The new lock region is double-buffered. The new lock region will - only take effect when the associated surface gets its pending state - applied. See wl_surface.commit for details. - - For details about the lock region, see wp_locked_pointer. - - - - - - - Notification that the pointer lock of the seat's pointer is activated. - - - - - - Notification that the pointer lock of the seat's pointer is no longer - active. If this is a oneshot pointer lock (see - wp_pointer_constraints.lifetime) this object is now defunct and should - be destroyed. If this is a persistent pointer lock (see - wp_pointer_constraints.lifetime) this pointer lock may again - reactivate in the future. - - - - - - - The wp_confined_pointer interface represents a confined pointer state. - - This object will send the event 'confined' when the confinement is - activated. Whenever the confinement is activated, it is guaranteed that - the surface the pointer is confined to will already have received pointer - focus and that the pointer will be within the region passed to the request - creating this object. It is up to the compositor to decide whether this - requires some user interaction and if the pointer will warp to within the - passed region if outside. - - To unconfine the pointer, send the destroy request. This will also destroy - the wp_confined_pointer object. - - If the compositor decides to unconfine the pointer the unconfined event is - sent. The wp_confined_pointer object is at this point defunct and should - be destroyed. - - - - - Destroy the confined pointer object. If applicable, the compositor will - unconfine the pointer. - - - - - - Set a new region used to confine the pointer. - - The new confine region is double-buffered. The new confine region will - only take effect when the associated surface gets its pending state - applied. See wl_surface.commit for details. - - If the confinement is active when the new confinement region is applied - and the pointer ends up outside of newly applied region, the pointer may - warped to a position within the new confinement region. If warped, a - wl_pointer.motion event will be emitted, but no - wp_relative_pointer.relative_motion event. - - The compositor may also, instead of using the new region, unconfine the - pointer. - - For details about the confine region, see wp_confined_pointer. - - - - - - - Notification that the pointer confinement of the seat's pointer is - activated. - - - - - - Notification that the pointer confinement of the seat's pointer is no - longer active. If this is a oneshot pointer confinement (see - wp_pointer_constraints.lifetime) this object is now defunct and should - be destroyed. If this is a persistent pointer confinement (see - wp_pointer_constraints.lifetime) this pointer confinement may again - reactivate in the future. - - - - - diff --git a/wlr_foreign_toplevel_management_v1.c b/wlr_foreign_toplevel_management_v1.c deleted file mode 100755 index 46c1ae7..0000000 --- a/wlr_foreign_toplevel_management_v1.c +++ /dev/null @@ -1,712 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include -#include -#include -#include -#include -#include -#include -#include "wlr-foreign-toplevel-management-unstable-v1-protocol.h" - -#define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 3 - -static const struct zwlr_foreign_toplevel_handle_v1_interface toplevel_handle_impl; - -static struct wlr_foreign_toplevel_handle_v1 *toplevel_handle_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, - &zwlr_foreign_toplevel_handle_v1_interface, - &toplevel_handle_impl)); - return wl_resource_get_user_data(resource); -} - -static void toplevel_handle_send_maximized_event(struct wl_resource *resource, - bool state) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - struct wlr_foreign_toplevel_handle_v1_maximized_event event = { - .toplevel = toplevel, - .maximized = state, - }; - wl_signal_emit_mutable(&toplevel->events.request_maximize, &event); -} - -static void foreign_toplevel_handle_set_maximized(struct wl_client *client, - struct wl_resource *resource) { - toplevel_handle_send_maximized_event(resource, true); -} - -static void foreign_toplevel_handle_unset_maximized(struct wl_client *client, - struct wl_resource *resource) { - toplevel_handle_send_maximized_event(resource, false); -} - -static void toplevel_send_minimized_event(struct wl_resource *resource, - bool state) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - - struct wlr_foreign_toplevel_handle_v1_minimized_event event = { - .toplevel = toplevel, - .minimized = state, - }; - wl_signal_emit_mutable(&toplevel->events.request_minimize, &event); -} - -static void foreign_toplevel_handle_set_minimized(struct wl_client *client, - struct wl_resource *resource) { - toplevel_send_minimized_event(resource, true); -} - -static void foreign_toplevel_handle_unset_minimized(struct wl_client *client, - struct wl_resource *resource) { - toplevel_send_minimized_event(resource, false); -} - -static void toplevel_send_fullscreen_event(struct wl_resource *resource, - bool state, struct wl_resource *output_resource) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - - struct wlr_output *output = NULL; - if (output_resource) { - output = wlr_output_from_resource(output_resource); - } - struct wlr_foreign_toplevel_handle_v1_fullscreen_event event = { - .toplevel = toplevel, - .fullscreen = state, - .output = output, - }; - wl_signal_emit_mutable(&toplevel->events.request_fullscreen, &event); -} - -static void foreign_toplevel_handle_set_fullscreen(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *output) { - toplevel_send_fullscreen_event(resource, true, output); -} - -static void foreign_toplevel_handle_unset_fullscreen(struct wl_client *client, - struct wl_resource *resource) { - toplevel_send_fullscreen_event(resource, false, NULL); -} - -static void foreign_toplevel_handle_activate(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *seat) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - struct wlr_seat_client *seat_client = wlr_seat_client_from_resource(seat); - if (!seat_client) { - return; - } - - struct wlr_foreign_toplevel_handle_v1_activated_event event = { - .toplevel = toplevel, - .seat = seat_client->seat, - }; - wl_signal_emit_mutable(&toplevel->events.request_activate, &event); -} - -static void foreign_toplevel_handle_close(struct wl_client *client, - struct wl_resource *resource) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - wl_signal_emit_mutable(&toplevel->events.request_close, toplevel); -} - -static void foreign_toplevel_handle_set_rectangle(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *surface, - int32_t x, int32_t y, int32_t width, int32_t height) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = - toplevel_handle_from_resource(resource); - if (!toplevel) { - return; - } - - if (width < 0 || height < 0) { - wl_resource_post_error(resource, - ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ERROR_INVALID_RECTANGLE, - "invalid rectangle passed to set_rectangle: width/height < 0"); - return; - } - - struct wlr_foreign_toplevel_handle_v1_set_rectangle_event event = { - .toplevel = toplevel, - .surface = wlr_surface_from_resource(surface), - .x = x, - .y = y, - .width = width, - .height = height, - }; - wl_signal_emit_mutable(&toplevel->events.set_rectangle, &event); -} - -static void foreign_toplevel_handle_destroy(struct wl_client *client, - struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static const struct zwlr_foreign_toplevel_handle_v1_interface toplevel_handle_impl = { - .set_maximized = foreign_toplevel_handle_set_maximized, - .unset_maximized = foreign_toplevel_handle_unset_maximized, - .set_minimized = foreign_toplevel_handle_set_minimized, - .unset_minimized = foreign_toplevel_handle_unset_minimized, - .activate = foreign_toplevel_handle_activate, - .close = foreign_toplevel_handle_close, - .set_rectangle = foreign_toplevel_handle_set_rectangle, - .destroy = foreign_toplevel_handle_destroy, - .set_fullscreen = foreign_toplevel_handle_set_fullscreen, - .unset_fullscreen = foreign_toplevel_handle_unset_fullscreen, -}; - -static void toplevel_idle_send_done(void *data) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = data; - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - zwlr_foreign_toplevel_handle_v1_send_done(resource); - } - - toplevel->idle_source = NULL; -} - -static void toplevel_update_idle_source( - struct wlr_foreign_toplevel_handle_v1 *toplevel) { - if (toplevel->idle_source) { - return; - } - - toplevel->idle_source = wl_event_loop_add_idle(toplevel->manager->event_loop, - toplevel_idle_send_done, toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_title( - struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *title) { - free(toplevel->title); - toplevel->title = strdup(title); - if (toplevel->title == NULL) { - wlr_log(WLR_ERROR, "failed to allocate memory for toplevel title"); - return; - } - - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - zwlr_foreign_toplevel_handle_v1_send_title(resource, title); - } - - toplevel_update_idle_source(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_app_id( - struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *app_id) { - free(toplevel->app_id); - toplevel->app_id = strdup(app_id); - if (toplevel->app_id == NULL) { - wlr_log(WLR_ERROR, "failed to allocate memory for toplevel app_id"); - return; - } - - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - zwlr_foreign_toplevel_handle_v1_send_app_id(resource, app_id); - } - - toplevel_update_idle_source(toplevel); -} - -static void send_output_to_resource(struct wl_resource *resource, - struct wlr_output *output, bool enter) { - struct wl_client *client = wl_resource_get_client(resource); - struct wl_resource *output_resource; - - wl_resource_for_each(output_resource, &output->resources) { - if (wl_resource_get_client(output_resource) == client) { - if (enter) { - zwlr_foreign_toplevel_handle_v1_send_output_enter(resource, - output_resource); - } else { - zwlr_foreign_toplevel_handle_v1_send_output_leave(resource, - output_resource); - } - } - } -} - -static void toplevel_send_output(struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wlr_output *output, bool enter) { - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - send_output_to_resource(resource, output, enter); - } - - toplevel_update_idle_source(toplevel); -} - -static void toplevel_handle_output_bind(struct wl_listener *listener, - void *data) { - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output = - wl_container_of(listener, toplevel_output, output_bind); - struct wlr_output_event_bind *event = data; - struct wl_client *client = wl_resource_get_client(event->resource); - - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel_output->toplevel->resources) { - if (wl_resource_get_client(resource) == client) { - send_output_to_resource(resource, toplevel_output->output, true); - } - } - - toplevel_update_idle_source(toplevel_output->toplevel); -} - -static void toplevel_handle_output_destroy(struct wl_listener *listener, - void *data) { - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output = - wl_container_of(listener, toplevel_output, output_destroy); - wlr_foreign_toplevel_handle_v1_output_leave(toplevel_output->toplevel, - toplevel_output->output); -} - -void wlr_foreign_toplevel_handle_v1_output_enter( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wlr_output *output) { - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output; - wl_list_for_each(toplevel_output, &toplevel->outputs, link) { - if (toplevel_output->output == output) { - return; // we have already sent output_enter event - } - } - - toplevel_output = - calloc(1, sizeof(struct wlr_foreign_toplevel_handle_v1_output)); - if (!toplevel_output) { - wlr_log(WLR_ERROR, "failed to allocate memory for toplevel output"); - return; - } - - toplevel_output->output = output; - toplevel_output->toplevel = toplevel; - wl_list_insert(&toplevel->outputs, &toplevel_output->link); - - toplevel_output->output_bind.notify = toplevel_handle_output_bind; - wl_signal_add(&output->events.bind, &toplevel_output->output_bind); - - toplevel_output->output_destroy.notify = toplevel_handle_output_destroy; - wl_signal_add(&output->events.destroy, &toplevel_output->output_destroy); - - toplevel_send_output(toplevel, output, true); -} - -static void toplevel_output_destroy( - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output) { - wl_list_remove(&toplevel_output->link); - wl_list_remove(&toplevel_output->output_bind.link); - wl_list_remove(&toplevel_output->output_destroy.link); - free(toplevel_output); -} - -void wlr_foreign_toplevel_handle_v1_output_leave( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wlr_output *output) { - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output_iterator; - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output = NULL; - - wl_list_for_each(toplevel_output_iterator, &toplevel->outputs, link) { - if (toplevel_output_iterator->output == output) { - toplevel_output = toplevel_output_iterator; - break; - } - } - - if (toplevel_output) { - toplevel_send_output(toplevel, output, false); - toplevel_output_destroy(toplevel_output); - } else { - // XXX: log an error? crash? - } -} - -static bool fill_array_from_toplevel_state(struct wl_array *array, - uint32_t state) { - if (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED) { - uint32_t *index = wl_array_add(array, sizeof(uint32_t)); - if (index == NULL) { - return false; - } - *index = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED; - } - if (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED) { - uint32_t *index = wl_array_add(array, sizeof(uint32_t)); - if (index == NULL) { - return false; - } - *index = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED; - } - if (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED) { - uint32_t *index = wl_array_add(array, sizeof(uint32_t)); - if (index == NULL) { - return false; - } - *index = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED; - } - if (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN) { - uint32_t *index = wl_array_add(array, sizeof(uint32_t)); - if (index == NULL) { - return false; - } - *index = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN; - } - - return true; -} - -static void toplevel_send_state(struct wlr_foreign_toplevel_handle_v1 *toplevel) { - struct wl_array states; - wl_array_init(&states); - bool r = fill_array_from_toplevel_state(&states, toplevel->state); - if (!r) { - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - wl_resource_post_no_memory(resource); - } - - wl_array_release(&states); - return; - } - - struct wl_resource *resource; - wl_resource_for_each(resource, &toplevel->resources) { - zwlr_foreign_toplevel_handle_v1_send_state(resource, &states); - } - - wl_array_release(&states); - toplevel_update_idle_source(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_maximized( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool maximized) { - if (maximized == !!(toplevel->state & - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED)) { - return; - } - if (maximized) { - toplevel->state |= WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED; - } else { - toplevel->state &= ~WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED; - } - toplevel_send_state(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_minimized( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool minimized) { - if (minimized == !!(toplevel->state & - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED)) { - return; - } - if (minimized) { - toplevel->state |= WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED; - } else { - toplevel->state &= ~WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED; - } - toplevel_send_state(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_activated( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool activated) { - if (activated == !!(toplevel->state & - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED)) { - return; - } - if (activated) { - toplevel->state |= WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED; - } else { - toplevel->state &= ~WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED; - } - toplevel_send_state(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_set_fullscreen( - struct wlr_foreign_toplevel_handle_v1 * toplevel, bool fullscreen) { - if (fullscreen == !!(toplevel->state & - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN)) { - return; - } - if (fullscreen) { - toplevel->state |= WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN; - } else { - toplevel->state &= ~WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN; - } - toplevel_send_state(toplevel); -} - -static void toplevel_resource_send_parent( - struct wl_resource *toplevel_resource, - struct wlr_foreign_toplevel_handle_v1 *parent) { - if (wl_resource_get_version(toplevel_resource) < - ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_PARENT_SINCE_VERSION) { - return; - } - struct wl_client *client = wl_resource_get_client(toplevel_resource); - struct wl_resource *parent_resource = NULL; - if (parent) { - parent_resource = wl_resource_find_for_client(&parent->resources, client); - if (!parent_resource) { - /* don't send an event if this client destroyed the parent handle */ - return; - } - } - zwlr_foreign_toplevel_handle_v1_send_parent(toplevel_resource, - parent_resource); -} - -void wlr_foreign_toplevel_handle_v1_set_parent( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wlr_foreign_toplevel_handle_v1 *parent) { - if (parent == toplevel->parent) { - /* only send parent event to the clients if there was a change */ - return; - } - struct wl_resource *toplevel_resource, *tmp; - wl_resource_for_each_safe(toplevel_resource, tmp, &toplevel->resources) { - toplevel_resource_send_parent(toplevel_resource, parent); - } - toplevel->parent = parent; - toplevel_update_idle_source(toplevel); -} - -void wlr_foreign_toplevel_handle_v1_destroy( - struct wlr_foreign_toplevel_handle_v1 *toplevel) { - if (!toplevel) { - return; - } - - wl_signal_emit_mutable(&toplevel->events.destroy, toplevel); - - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe(resource, tmp, &toplevel->resources) { - zwlr_foreign_toplevel_handle_v1_send_closed(resource); - wl_resource_set_user_data(resource, NULL); - wl_list_remove(wl_resource_get_link(resource)); - wl_list_init(wl_resource_get_link(resource)); - } - - struct wlr_foreign_toplevel_handle_v1_output *toplevel_output, *tmp2; - wl_list_for_each_safe(toplevel_output, tmp2, &toplevel->outputs, link) { - toplevel_output_destroy(toplevel_output); - } - - if (toplevel->idle_source) { - wl_event_source_remove(toplevel->idle_source); - } - - wl_list_remove(&toplevel->link); - - /* need to ensure no other toplevels hold a pointer to this one as - * a parent, so that a later call to foreign_toplevel_manager_bind() - * will not result in a segfault */ - struct wlr_foreign_toplevel_handle_v1 *tl, *tmp3; - wl_list_for_each_safe(tl, tmp3, &toplevel->manager->toplevels, link) { - if (tl->parent == toplevel) { - /* Note: we send a parent signal to all clients in this case; - * the caller should first destroy the child handles if it - * wishes to avoid this behavior. */ - wlr_foreign_toplevel_handle_v1_set_parent(tl, NULL); - } - } - - free(toplevel->title); - free(toplevel->app_id); - free(toplevel); -} - -static void foreign_toplevel_resource_destroy(struct wl_resource *resource) { - wl_list_remove(wl_resource_get_link(resource)); -} - -static struct wl_resource *create_toplevel_resource_for_resource( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wl_resource *manager_resource) { - struct wl_client *client = wl_resource_get_client(manager_resource); - struct wl_resource *resource = wl_resource_create(client, - &zwlr_foreign_toplevel_handle_v1_interface, - wl_resource_get_version(manager_resource), 0); - if (!resource) { - wl_client_post_no_memory(client); - return NULL; - } - - wl_resource_set_implementation(resource, &toplevel_handle_impl, toplevel, - foreign_toplevel_resource_destroy); - - wl_list_insert(&toplevel->resources, wl_resource_get_link(resource)); - zwlr_foreign_toplevel_manager_v1_send_toplevel(manager_resource, resource); - return resource; -} - -struct wlr_foreign_toplevel_handle_v1 * -wlr_foreign_toplevel_handle_v1_create( - struct wlr_foreign_toplevel_manager_v1 *manager) { - struct wlr_foreign_toplevel_handle_v1 *toplevel = calloc(1, - sizeof(struct wlr_foreign_toplevel_handle_v1)); - if (!toplevel) { - return NULL; - } - - wl_list_insert(&manager->toplevels, &toplevel->link); - toplevel->manager = manager; - - wl_list_init(&toplevel->resources); - wl_list_init(&toplevel->outputs); - - wl_signal_init(&toplevel->events.request_maximize); - wl_signal_init(&toplevel->events.request_minimize); - wl_signal_init(&toplevel->events.request_activate); - wl_signal_init(&toplevel->events.request_fullscreen); - wl_signal_init(&toplevel->events.request_close); - wl_signal_init(&toplevel->events.set_rectangle); - wl_signal_init(&toplevel->events.destroy); - - struct wl_resource *manager_resource, *tmp; - wl_resource_for_each_safe(manager_resource, tmp, &manager->resources) { - create_toplevel_resource_for_resource(toplevel, manager_resource); - } - - return toplevel; -} - -static const struct zwlr_foreign_toplevel_manager_v1_interface - foreign_toplevel_manager_impl; - -static void foreign_toplevel_manager_handle_stop(struct wl_client *client, - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, - &zwlr_foreign_toplevel_manager_v1_interface, - &foreign_toplevel_manager_impl)); - - zwlr_foreign_toplevel_manager_v1_send_finished(resource); - wl_resource_destroy(resource); -} - -static const struct zwlr_foreign_toplevel_manager_v1_interface - foreign_toplevel_manager_impl = { - .stop = foreign_toplevel_manager_handle_stop -}; - -static void foreign_toplevel_manager_resource_destroy( - struct wl_resource *resource) { - wl_list_remove(wl_resource_get_link(resource)); -} - -static void toplevel_send_details_to_toplevel_resource( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wl_resource *resource) { - if (toplevel->title) { - zwlr_foreign_toplevel_handle_v1_send_title(resource, toplevel->title); - } - if (toplevel->app_id) { - zwlr_foreign_toplevel_handle_v1_send_app_id(resource, toplevel->app_id); - } - - struct wlr_foreign_toplevel_handle_v1_output *output; - wl_list_for_each(output, &toplevel->outputs, link) { - send_output_to_resource(resource, output->output, true); - } - - struct wl_array states; - wl_array_init(&states); - bool r = fill_array_from_toplevel_state(&states, toplevel->state); - if (!r) { - wl_resource_post_no_memory(resource); - wl_array_release(&states); - return; - } - - zwlr_foreign_toplevel_handle_v1_send_state(resource, &states); - wl_array_release(&states); - - toplevel_resource_send_parent(resource, toplevel->parent); - - zwlr_foreign_toplevel_handle_v1_send_done(resource); -} - -static void foreign_toplevel_manager_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - struct wlr_foreign_toplevel_manager_v1 *manager = data; - struct wl_resource *resource = wl_resource_create(client, - &zwlr_foreign_toplevel_manager_v1_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - return; - } - wl_resource_set_implementation(resource, &foreign_toplevel_manager_impl, - manager, foreign_toplevel_manager_resource_destroy); - - wl_list_insert(&manager->resources, wl_resource_get_link(resource)); - - struct wlr_foreign_toplevel_handle_v1 *toplevel, *tmp; - /* First loop: create a handle for all toplevels for all clients. - * Separation into two loops avoid the case where a child handle - * is created before a parent handle, so the parent relationship - * could not be sent to a client. */ - wl_list_for_each_safe(toplevel, tmp, &manager->toplevels, link) { - create_toplevel_resource_for_resource(toplevel, resource); - } - /* Second loop: send details about each toplevel. */ - wl_list_for_each_safe(toplevel, tmp, &manager->toplevels, link) { - struct wl_resource *toplevel_resource = - wl_resource_find_for_client(&toplevel->resources, client); - toplevel_send_details_to_toplevel_resource(toplevel, - toplevel_resource); - } -} - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_foreign_toplevel_manager_v1 *manager = - wl_container_of(listener, manager, display_destroy); - wl_signal_emit_mutable(&manager->events.destroy, manager); - wl_list_remove(&manager->display_destroy.link); - wl_global_destroy(manager->global); - free(manager); -} - -struct wlr_foreign_toplevel_manager_v1 *wlr_foreign_toplevel_manager_v1_create( - struct wl_display *display) { - struct wlr_foreign_toplevel_manager_v1 *manager = calloc(1, - sizeof(struct wlr_foreign_toplevel_manager_v1)); - if (!manager) { - return NULL; - } - - manager->event_loop = wl_display_get_event_loop(display); - manager->global = wl_global_create(display, - &zwlr_foreign_toplevel_manager_v1_interface, - FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION, manager, - foreign_toplevel_manager_bind); - if (!manager->global) { - free(manager); - return NULL; - } - - wl_signal_init(&manager->events.destroy); - wl_list_init(&manager->resources); - wl_list_init(&manager->toplevels); - - manager->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &manager->display_destroy); - - return manager; -} diff --git a/wlr_foreign_toplevel_management_v1.h b/wlr_foreign_toplevel_management_v1.h deleted file mode 100755 index c4abcb3..0000000 --- a/wlr_foreign_toplevel_management_v1.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_FOREIGN_TOPLEVEL_MANAGEMENT_V1_H -#define WLR_TYPES_WLR_FOREIGN_TOPLEVEL_MANAGEMENT_V1_H - -#include -#include - -struct wlr_foreign_toplevel_manager_v1 { - struct wl_event_loop *event_loop; - struct wl_global *global; - struct wl_list resources; // wl_resource_get_link() - struct wl_list toplevels; // wlr_foreign_toplevel_handle_v1.link - - struct wl_listener display_destroy; - - struct { - struct wl_signal destroy; - } events; - - void *data; -}; - -enum wlr_foreign_toplevel_handle_v1_state { - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED = (1 << 0), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED = (1 << 1), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED = (1 << 2), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN = (1 << 3), -}; - -struct wlr_foreign_toplevel_handle_v1_output { - struct wl_list link; // wlr_foreign_toplevel_handle_v1.outputs - struct wlr_output *output; - struct wlr_foreign_toplevel_handle_v1 *toplevel; - - // private state - - struct wl_listener output_bind; - struct wl_listener output_destroy; -}; - -struct wlr_foreign_toplevel_handle_v1 { - struct wlr_foreign_toplevel_manager_v1 *manager; - struct wl_list resources; - struct wl_list link; - struct wl_event_source *idle_source; - - char *title; - char *app_id; - struct wlr_foreign_toplevel_handle_v1 *parent; - struct wl_list outputs; // wlr_foreign_toplevel_v1_output.link - uint32_t state; // enum wlr_foreign_toplevel_v1_state - - struct { - // struct wlr_foreign_toplevel_handle_v1_maximized_event - struct wl_signal request_maximize; - // struct wlr_foreign_toplevel_handle_v1_minimized_event - struct wl_signal request_minimize; - // struct wlr_foreign_toplevel_handle_v1_activated_event - struct wl_signal request_activate; - // struct wlr_foreign_toplevel_handle_v1_fullscreen_event - struct wl_signal request_fullscreen; - struct wl_signal request_close; - - // struct wlr_foreign_toplevel_handle_v1_set_rectangle_event - struct wl_signal set_rectangle; - struct wl_signal destroy; - } events; - - void *data; -}; - -struct wlr_foreign_toplevel_handle_v1_maximized_event { - struct wlr_foreign_toplevel_handle_v1 *toplevel; - bool maximized; -}; - -struct wlr_foreign_toplevel_handle_v1_minimized_event { - struct wlr_foreign_toplevel_handle_v1 *toplevel; - bool minimized; -}; - -struct wlr_foreign_toplevel_handle_v1_activated_event { - struct wlr_foreign_toplevel_handle_v1 *toplevel; - struct wlr_seat *seat; -}; - -struct wlr_foreign_toplevel_handle_v1_fullscreen_event { - struct wlr_foreign_toplevel_handle_v1 *toplevel; - bool fullscreen; - struct wlr_output *output; -}; - -struct wlr_foreign_toplevel_handle_v1_set_rectangle_event { - struct wlr_foreign_toplevel_handle_v1 *toplevel; - struct wlr_surface *surface; - int32_t x, y, width, height; -}; - -struct wlr_foreign_toplevel_manager_v1 *wlr_foreign_toplevel_manager_v1_create( - struct wl_display *display); - -struct wlr_foreign_toplevel_handle_v1 *wlr_foreign_toplevel_handle_v1_create( - struct wlr_foreign_toplevel_manager_v1 *manager); -/** - * Destroy the given toplevel handle, sending the closed event to any - * client. Also, if the destroyed toplevel is set as a parent of any - * other valid toplevel, clients still holding a handle to both are - * sent a parent signal with NULL parent. If this is not desired, the - * caller should ensure that any child toplevels are destroyed before - * the parent. - */ -void wlr_foreign_toplevel_handle_v1_destroy( - struct wlr_foreign_toplevel_handle_v1 *toplevel); - -void wlr_foreign_toplevel_handle_v1_set_title( - struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *title); -void wlr_foreign_toplevel_handle_v1_set_app_id( - struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *app_id); - -void wlr_foreign_toplevel_handle_v1_output_enter( - struct wlr_foreign_toplevel_handle_v1 *toplevel, struct wlr_output *output); -void wlr_foreign_toplevel_handle_v1_output_leave( - struct wlr_foreign_toplevel_handle_v1 *toplevel, struct wlr_output *output); - -void wlr_foreign_toplevel_handle_v1_set_maximized( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool maximized); -void wlr_foreign_toplevel_handle_v1_set_minimized( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool minimized); -void wlr_foreign_toplevel_handle_v1_set_activated( - struct wlr_foreign_toplevel_handle_v1 *toplevel, bool activated); -void wlr_foreign_toplevel_handle_v1_set_fullscreen( - struct wlr_foreign_toplevel_handle_v1* toplevel, bool fullscreen); - -/** - * Set the parent of a toplevel. If the parent changed from its previous - * value, also sends a parent event to all clients that hold handles to - * both toplevel and parent (no message is sent to clients that have - * previously destroyed their parent handle). NULL is allowed as the - * parent, meaning no parent exists. - */ -void wlr_foreign_toplevel_handle_v1_set_parent( - struct wlr_foreign_toplevel_handle_v1 *toplevel, - struct wlr_foreign_toplevel_handle_v1 *parent); - - -#endif