mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-11-25 06:59:50 -05:00
opt: opt project structure
This commit is contained in:
parent
72314836ca
commit
860d186a34
8 changed files with 76 additions and 1651 deletions
133
IM.h
133
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#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
|
||||
* <pre>
|
||||
*
|
||||
* 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.
|
||||
* </pre>
|
||||
*/
|
||||
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
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
/*
|
||||
* See LICENSE file for copyright and license details.
|
||||
*/
|
||||
#define XWAYLNAD 1
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -73,7 +72,7 @@
|
|||
|
||||
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||
#include "util.h"
|
||||
#include "wlr_foreign_toplevel_management_v1.h"
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
|
||||
/* 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;
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -1,339 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="pointer_constraints_unstable_v1">
|
||||
|
||||
<copyright>
|
||||
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.
|
||||
</copyright>
|
||||
|
||||
<description summary="protocol for constraining pointer motions">
|
||||
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.
|
||||
</description>
|
||||
|
||||
<interface name="zwp_pointer_constraints_v1" version="1">
|
||||
<description summary="constrain the movement of a pointer">
|
||||
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.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<description summary="wp_pointer_constraints error values">
|
||||
These errors can be emitted in response to wp_pointer_constraints
|
||||
requests.
|
||||
</description>
|
||||
<entry name="already_constrained" value="1"
|
||||
summary="pointer constraint already requested on that surface"/>
|
||||
</enum>
|
||||
|
||||
<enum name="lifetime">
|
||||
<description summary="constraint lifetime">
|
||||
These values represent different lifetime semantics. They are passed
|
||||
as arguments to the factory requests to specify how the constraint
|
||||
lifetimes should be managed.
|
||||
</description>
|
||||
<entry name="oneshot" value="1">
|
||||
<description summary="the pointer constraint is defunct once deactivated">
|
||||
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.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="persistent" value="2">
|
||||
<description summary="the pointer constraint may reactivate">
|
||||
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.
|
||||
</description>
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pointer constraints manager object">
|
||||
Used by the client to notify the server that it will no longer use this
|
||||
pointer constraints object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="lock_pointer">
|
||||
<description summary="lock pointer to a position">
|
||||
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.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_locked_pointer_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="surface to lock pointer to"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"
|
||||
summary="the pointer that should be locked"/>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
<arg name="lifetime" type="uint" enum="lifetime" summary="lock lifetime"/>
|
||||
</request>
|
||||
|
||||
<request name="confine_pointer">
|
||||
<description summary="confine pointer to a region">
|
||||
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.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_confined_pointer_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="surface to lock pointer to"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"
|
||||
summary="the pointer that should be confined"/>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
<arg name="lifetime" type="uint" enum="lifetime" summary="confinement lifetime"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_locked_pointer_v1" version="1">
|
||||
<description summary="receive relative pointer motion events">
|
||||
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.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the locked pointer object">
|
||||
Destroy the locked pointer object. If applicable, the compositor will
|
||||
unlock the pointer.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_cursor_position_hint">
|
||||
<description summary="set the pointer cursor position hint">
|
||||
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.
|
||||
</description>
|
||||
<arg name="surface_x" type="fixed"
|
||||
summary="surface-local x coordinate"/>
|
||||
<arg name="surface_y" type="fixed"
|
||||
summary="surface-local y coordinate"/>
|
||||
</request>
|
||||
|
||||
<request name="set_region">
|
||||
<description summary="set a new lock region">
|
||||
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.
|
||||
</description>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
</request>
|
||||
|
||||
<event name="locked">
|
||||
<description summary="lock activation event">
|
||||
Notification that the pointer lock of the seat's pointer is activated.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="unlocked">
|
||||
<description summary="lock deactivation event">
|
||||
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.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_confined_pointer_v1" version="1">
|
||||
<description summary="confined pointer object">
|
||||
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.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the confined pointer object">
|
||||
Destroy the confined pointer object. If applicable, the compositor will
|
||||
unconfine the pointer.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_region">
|
||||
<description summary="set a new confine region">
|
||||
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.
|
||||
</description>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
</request>
|
||||
|
||||
<event name="confined">
|
||||
<description summary="pointer confined">
|
||||
Notification that the pointer confinement of the seat's pointer is
|
||||
activated.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="unconfined">
|
||||
<description summary="pointer unconfined">
|
||||
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.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
|
@ -1,712 +0,0 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/util/log.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -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 <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue