mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-19 14:33:16 -04:00
mix: add window share and fix xcursor,text-input,ext-workspace
This commit is contained in:
parent
4f3e6545bf
commit
3b535d4005
7 changed files with 166 additions and 1173 deletions
|
|
@ -33,12 +33,12 @@ libm = cc.find_library('m')
|
||||||
xcb = dependency('xcb', required : get_option('xwayland'))
|
xcb = dependency('xcb', required : get_option('xwayland'))
|
||||||
xlibs = dependency('xcb-icccm', required : get_option('xwayland'))
|
xlibs = dependency('xcb-icccm', required : get_option('xwayland'))
|
||||||
wayland_server_dep = dependency('wayland-server',version: '>=1.23.1')
|
wayland_server_dep = dependency('wayland-server',version: '>=1.23.1')
|
||||||
wlroots_dep = dependency('wlroots-0.19',version: '>=0.19.0')
|
wlroots_dep = dependency('wlroots-0.20',version: '>=0.20.0')
|
||||||
xkbcommon_dep = dependency('xkbcommon')
|
xkbcommon_dep = dependency('xkbcommon')
|
||||||
libinput_dep = dependency('libinput',version: '>=1.27.1')
|
libinput_dep = dependency('libinput',version: '>=1.27.1')
|
||||||
libwayland_client_dep = dependency('wayland-client')
|
libwayland_client_dep = dependency('wayland-client')
|
||||||
pcre2_dep = dependency('libpcre2-8')
|
pcre2_dep = dependency('libpcre2-8')
|
||||||
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
libscenefx_dep = dependency('scenefx-0.5',version: '>=0.5.0')
|
||||||
|
|
||||||
|
|
||||||
# 获取版本信息
|
# 获取版本信息
|
||||||
|
|
@ -97,7 +97,6 @@ endif
|
||||||
executable('mango',
|
executable('mango',
|
||||||
'src/mango.c',
|
'src/mango.c',
|
||||||
'src/common/util.c',
|
'src/common/util.c',
|
||||||
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
|
||||||
wayland_sources,
|
wayland_sources,
|
||||||
dependencies : [
|
dependencies : [
|
||||||
libm,
|
libm,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include "wlr_ext_workspace_v1.h"
|
#include <wlr/types/wlr_ext_workspace_v1.h>
|
||||||
|
|
||||||
#define EXT_WORKSPACE_ENABLE_CAPS \
|
#define EXT_WORKSPACE_ENABLE_CAPS \
|
||||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
||||||
|
|
@ -7,20 +7,20 @@
|
||||||
typedef struct Monitor Monitor;
|
typedef struct Monitor Monitor;
|
||||||
|
|
||||||
struct workspace {
|
struct workspace {
|
||||||
struct wl_list link; // Link in global workspaces list
|
struct wl_list link;
|
||||||
uint32_t tag; // Numeric identifier (1-9, 0=overview)
|
uint32_t tag;
|
||||||
Monitor *m; // Associated monitor
|
Monitor *m;
|
||||||
struct wlr_ext_workspace_handle_v1 *ext_workspace; // Protocol object
|
struct wlr_ext_workspace_handle_v1 *ext_workspace;
|
||||||
/* Event listeners */
|
struct wl_listener commit;
|
||||||
struct wl_listener activate;
|
|
||||||
struct wl_listener deactivate;
|
|
||||||
struct wl_listener assign;
|
|
||||||
struct wl_listener remove;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *ext_manager;
|
struct wlr_ext_workspace_manager_v1 *ext_manager;
|
||||||
struct wl_list workspaces;
|
struct wl_list workspaces;
|
||||||
|
|
||||||
|
static void handle_ext_commit(struct wl_listener *listener, void *data);
|
||||||
|
static struct wl_listener ext_manager_commit_listener = {.notify =
|
||||||
|
handle_ext_commit};
|
||||||
|
|
||||||
void goto_workspace(struct workspace *target) {
|
void goto_workspace(struct workspace *target) {
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
tag = 1 << (target->tag - 1);
|
tag = 1 << (target->tag - 1);
|
||||||
|
|
@ -43,30 +43,60 @@ void toggle_workspace(struct workspace *target) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_ext_workspace_activate(struct wl_listener *listener,
|
static void handle_ext_commit(struct wl_listener *listener, void *data) {
|
||||||
void *data) {
|
struct wlr_ext_workspace_v1_commit_event *event = data;
|
||||||
struct workspace *workspace =
|
struct wlr_ext_workspace_v1_request *request;
|
||||||
wl_container_of(listener, workspace, activate);
|
|
||||||
|
|
||||||
if (workspace->m->isoverview) {
|
wl_list_for_each(request, event->requests, link) {
|
||||||
return;
|
switch (request->type) {
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE: {
|
||||||
|
if (!request->activate.workspace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct workspace *workspace = NULL;
|
||||||
|
struct workspace *w;
|
||||||
|
wl_list_for_each(w, &workspaces, link) {
|
||||||
|
if (w->ext_workspace == request->activate.workspace) {
|
||||||
|
workspace = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace || workspace->m->isoverview) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto_workspace(workspace);
|
||||||
|
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE: {
|
||||||
|
if (!request->deactivate.workspace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct workspace *workspace = NULL;
|
||||||
|
struct workspace *w;
|
||||||
|
wl_list_for_each(w, &workspaces, link) {
|
||||||
|
if (w->ext_workspace == request->deactivate.workspace) {
|
||||||
|
workspace = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace || workspace->m->isoverview) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle_workspace(workspace);
|
||||||
|
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goto_workspace(workspace);
|
|
||||||
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct workspace *workspace =
|
|
||||||
wl_container_of(listener, workspace, deactivate);
|
|
||||||
|
|
||||||
if (workspace->m->isoverview) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_workspace(workspace);
|
|
||||||
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_name_from_tag(uint32_t tag) {
|
static const char *get_name_from_tag(uint32_t tag) {
|
||||||
|
|
@ -76,8 +106,6 @@ static const char *get_name_from_tag(uint32_t tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_workspace(struct workspace *workspace) {
|
void destroy_workspace(struct workspace *workspace) {
|
||||||
wl_list_remove(&workspace->activate.link);
|
|
||||||
wl_list_remove(&workspace->deactivate.link);
|
|
||||||
wlr_ext_workspace_handle_v1_destroy(workspace->ext_workspace);
|
wlr_ext_workspace_handle_v1_destroy(workspace->ext_workspace);
|
||||||
wl_list_remove(&workspace->link);
|
wl_list_remove(&workspace->link);
|
||||||
free(workspace);
|
free(workspace);
|
||||||
|
|
@ -112,17 +140,12 @@ static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
||||||
workspace->m = m;
|
workspace->m = m;
|
||||||
workspace->ext_workspace = wlr_ext_workspace_handle_v1_create(
|
workspace->ext_workspace = wlr_ext_workspace_handle_v1_create(
|
||||||
ext_manager, name, EXT_WORKSPACE_ENABLE_CAPS);
|
ext_manager, name, EXT_WORKSPACE_ENABLE_CAPS);
|
||||||
|
|
||||||
|
workspace->ext_workspace->data = workspace;
|
||||||
|
|
||||||
wlr_ext_workspace_handle_v1_set_group(workspace->ext_workspace,
|
wlr_ext_workspace_handle_v1_set_group(workspace->ext_workspace,
|
||||||
m->ext_group);
|
m->ext_group);
|
||||||
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
||||||
|
|
||||||
workspace->activate.notify = handle_ext_workspace_activate;
|
|
||||||
wl_signal_add(&workspace->ext_workspace->events.activate,
|
|
||||||
&workspace->activate);
|
|
||||||
|
|
||||||
workspace->deactivate.notify = handle_ext_workspace_deactivate;
|
|
||||||
wl_signal_add(&workspace->ext_workspace->events.deactivate,
|
|
||||||
&workspace->deactivate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_ext_workspace_printstatus(Monitor *m) {
|
void dwl_ext_workspace_printstatus(Monitor *m) {
|
||||||
|
|
@ -165,10 +188,10 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
|
||||||
if (m->isoverview) {
|
if (m->isoverview) {
|
||||||
|
add_workspace_by_tag(0, m);
|
||||||
for (i = 1; i <= LENGTH(tags); i++) {
|
for (i = 1; i <= LENGTH(tags); i++) {
|
||||||
remove_workspace_by_tag(i, m);
|
remove_workspace_by_tag(i, m);
|
||||||
}
|
}
|
||||||
add_workspace_by_tag(0, m);
|
|
||||||
} else {
|
} else {
|
||||||
remove_workspace_by_tag(0, m);
|
remove_workspace_by_tag(0, m);
|
||||||
for (i = 1; i <= LENGTH(tags); i++) {
|
for (i = 1; i <= LENGTH(tags); i++) {
|
||||||
|
|
@ -180,8 +203,9 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspaces_init() {
|
void workspaces_init() {
|
||||||
/* Create the global workspace manager with activation capability */
|
|
||||||
ext_manager = wlr_ext_workspace_manager_v1_create(dpy, 1);
|
ext_manager = wlr_ext_workspace_manager_v1_create(dpy, 1);
|
||||||
/* Initialize the global workspaces list */
|
|
||||||
wl_list_init(&workspaces);
|
wl_list_init(&workspaces);
|
||||||
|
|
||||||
|
wl_signal_add(&ext_manager->events.commit, &ext_manager_commit_listener);
|
||||||
}
|
}
|
||||||
|
|
@ -77,15 +77,6 @@ Monitor *output_from_wlr_output(struct wlr_output *wlr_output) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor *output_nearest_to(int32_t lx, int32_t ly) {
|
|
||||||
double closest_x, closest_y;
|
|
||||||
wlr_output_layout_closest_point(output_layout, NULL, lx, ly, &closest_x,
|
|
||||||
&closest_y);
|
|
||||||
|
|
||||||
return output_from_wlr_output(
|
|
||||||
wlr_output_layout_output_at(output_layout, closest_x, closest_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -255,7 +246,7 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
cursor_rect = (struct wlr_box){0};
|
cursor_rect = (struct wlr_box){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
output = output_nearest_to(cursor_rect.x, cursor_rect.y);
|
output = get_monitor_nearest_to(cursor_rect.x, cursor_rect.y);
|
||||||
if (!output_is_usable(output)) {
|
if (!output_is_usable(output)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -301,9 +292,8 @@ static void handle_input_method_commit(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_commit);
|
wl_container_of(listener, relay, input_method_commit);
|
||||||
struct wlr_input_method_v2 *input_method = data;
|
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
assert(relay->input_method == input_method);
|
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||||
|
|
||||||
text_input = relay->active_text_input;
|
text_input = relay->active_text_input;
|
||||||
if (!text_input) {
|
if (!text_input) {
|
||||||
|
|
@ -333,7 +323,8 @@ static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||||
|
relay->input_method->keyboard_grab;
|
||||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||||
|
|
||||||
if (keyboard_grab->keyboard) {
|
if (keyboard_grab->keyboard) {
|
||||||
|
|
@ -365,7 +356,6 @@ static void handle_input_method_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_destroy);
|
wl_container_of(listener, relay, input_method_destroy);
|
||||||
assert(relay->input_method == data);
|
|
||||||
wl_list_remove(&relay->input_method_commit.link);
|
wl_list_remove(&relay->input_method_commit.link);
|
||||||
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
||||||
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
||||||
|
|
@ -571,11 +561,11 @@ struct dwl_input_method_relay *dwl_im_relay_create() {
|
||||||
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
||||||
|
|
||||||
relay->new_text_input.notify = handle_new_text_input;
|
relay->new_text_input.notify = handle_new_text_input;
|
||||||
wl_signal_add(&text_input_manager->events.text_input,
|
wl_signal_add(&text_input_manager->events.new_text_input,
|
||||||
&relay->new_text_input);
|
&relay->new_text_input);
|
||||||
|
|
||||||
relay->new_input_method.notify = handle_new_input_method;
|
relay->new_input_method.notify = handle_new_input_method;
|
||||||
wl_signal_add(&input_method_manager->events.input_method,
|
wl_signal_add(&input_method_manager->events.new_input_method,
|
||||||
&relay->new_input_method);
|
&relay->new_input_method);
|
||||||
|
|
||||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||||
|
|
|
||||||
|
|
@ -1,997 +0,0 @@
|
||||||
// bash on: https://gitlab.freedesktop.org/tokyo4j/wlroots/-/tree/ext-workspace
|
|
||||||
// TODO: remove this file
|
|
||||||
// refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115
|
|
||||||
|
|
||||||
#include "wlr_ext_workspace_v1.h"
|
|
||||||
#include "ext-workspace-v1-protocol.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
|
|
||||||
#define EXT_WORKSPACE_V1_VERSION 1
|
|
||||||
|
|
||||||
enum wlr_ext_workspace_v1_request_type {
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request {
|
|
||||||
enum wlr_ext_workspace_v1_request_type type;
|
|
||||||
|
|
||||||
// CREATE_WORKSPACE
|
|
||||||
char *name;
|
|
||||||
// CREATE_WORKSPACE / ASSIGN
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
// ACTIVATE / DEACTIVATE / ASSIGN / REMOVE
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output {
|
|
||||||
struct wlr_output *output;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
struct wl_listener output_bind;
|
|
||||||
struct wl_listener output_destroy;
|
|
||||||
struct wl_list link;
|
|
||||||
};
|
|
||||||
|
|
||||||
// These structs wrap wl_resource of each interface to access the request queue
|
|
||||||
// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager
|
|
||||||
// resource
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
struct wl_list requests; // wlr_ext_workspace_v1_request.link
|
|
||||||
struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link
|
|
||||||
struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.resources
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
|
||||||
struct wl_list link; // wlr_ext_workspace_group_v1.resources
|
|
||||||
struct wl_list
|
|
||||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
|
||||||
struct wl_list link; // wlr_ext_workspace_v1.resources
|
|
||||||
struct wl_list
|
|
||||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *
|
|
||||||
group_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(
|
|
||||||
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *
|
|
||||||
workspace_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
|
||||||
&workspace_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_manager_v1_resource *
|
|
||||||
manager_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(
|
|
||||||
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_destroy(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_activate(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
|
||||||
req->workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_handle_deactivate(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
|
||||||
req->workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_assign(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource,
|
|
||||||
struct wl_resource *group_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(group_resource);
|
|
||||||
if (!workspace_res || !group_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
|
||||||
req->group = group_res->group;
|
|
||||||
req->workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_remove(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
|
||||||
req->workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
|
||||||
.destroy = workspace_handle_destroy,
|
|
||||||
.activate = workspace_handle_activate,
|
|
||||||
.deactivate = workspace_handle_deactivate,
|
|
||||||
.assign = workspace_handle_assign,
|
|
||||||
.remove = workspace_handle_remove,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void group_handle_create_workspace(struct wl_client *client,
|
|
||||||
struct wl_resource *group_resource,
|
|
||||||
const char *name) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(group_resource);
|
|
||||||
if (!group_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(group_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->name = strdup(name);
|
|
||||||
if (!req->name) {
|
|
||||||
free(req);
|
|
||||||
wl_resource_post_no_memory(group_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
|
||||||
req->group = group_res->group;
|
|
||||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_handle_destroy(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl = {
|
|
||||||
.create_workspace = group_handle_create_workspace,
|
|
||||||
.destroy = group_handle_destroy,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void destroy_workspace_resource(
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
|
||||||
wl_list_remove(&workspace_res->link);
|
|
||||||
wl_list_remove(&workspace_res->manager_resource_link);
|
|
||||||
wl_resource_set_user_data(workspace_res->resource, NULL);
|
|
||||||
free(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(resource);
|
|
||||||
if (workspace_res) {
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
calloc(1, sizeof(*workspace_res));
|
|
||||||
if (!workspace_res) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
|
||||||
workspace_res->resource =
|
|
||||||
wl_resource_create(client, &ext_workspace_handle_v1_interface,
|
|
||||||
wl_resource_get_version(manager_res->resource), 0);
|
|
||||||
if (!workspace_res->resource) {
|
|
||||||
free(workspace_res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(workspace_res->resource, &workspace_impl,
|
|
||||||
workspace_res, workspace_resource_destroy);
|
|
||||||
|
|
||||||
workspace_res->workspace = workspace;
|
|
||||||
workspace_res->manager = manager_res;
|
|
||||||
wl_list_insert(&workspace->resources, &workspace_res->link);
|
|
||||||
wl_list_insert(&manager_res->workspace_resources,
|
|
||||||
&workspace_res->manager_resource_link);
|
|
||||||
|
|
||||||
return workspace_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
|
||||||
wl_list_remove(&group_res->link);
|
|
||||||
wl_list_remove(&group_res->manager_resource_link);
|
|
||||||
wl_resource_set_user_data(group_res->resource, NULL);
|
|
||||||
free(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_handle_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(resource);
|
|
||||||
if (group_res) {
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
calloc(1, sizeof(*group_res));
|
|
||||||
if (!group_res) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
|
||||||
uint32_t version = wl_resource_get_version(manager_res->resource);
|
|
||||||
group_res->resource = wl_resource_create(
|
|
||||||
client, &ext_workspace_group_handle_v1_interface, version, 0);
|
|
||||||
if (group_res->resource == NULL) {
|
|
||||||
free(group_res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(group_res->resource, &group_impl, group_res,
|
|
||||||
group_handle_resource_destroy);
|
|
||||||
|
|
||||||
group_res->group = group;
|
|
||||||
group_res->manager = manager_res;
|
|
||||||
wl_list_insert(&group->resources, &group_res->link);
|
|
||||||
wl_list_insert(&manager_res->group_resources,
|
|
||||||
&group_res->manager_resource_link);
|
|
||||||
|
|
||||||
return group_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy_request(struct wlr_ext_workspace_v1_request *req) {
|
|
||||||
wl_list_remove(&req->link);
|
|
||||||
free(req->name);
|
|
||||||
free(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_commit(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
manager_resource_from_resource(resource);
|
|
||||||
if (!manager_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
|
||||||
switch (req->type) {
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1_create_workspace_event
|
|
||||||
event = {
|
|
||||||
.name = req->name,
|
|
||||||
};
|
|
||||||
wl_signal_emit_mutable(&req->group->events.create_workspace,
|
|
||||||
&event);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.activate, NULL);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.deactivate, NULL);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.assign, req->group);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.remove, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_idle(void *data) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
|
||||||
}
|
|
||||||
manager->idle_source = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
|
||||||
if (!manager->idle_source) {
|
|
||||||
manager->idle_source =
|
|
||||||
wl_event_loop_add_idle(manager->event_loop, handle_idle, manager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
|
||||||
struct wl_resource *resource = workspace_res->resource;
|
|
||||||
|
|
||||||
ext_workspace_handle_v1_send_capabilities(resource, workspace->caps);
|
|
||||||
if (workspace->coordinates.size > 0) {
|
|
||||||
ext_workspace_handle_v1_send_coordinates(resource,
|
|
||||||
&workspace->coordinates);
|
|
||||||
}
|
|
||||||
if (workspace->name) {
|
|
||||||
ext_workspace_handle_v1_send_name(resource, workspace->name);
|
|
||||||
}
|
|
||||||
if (workspace->id) {
|
|
||||||
ext_workspace_handle_v1_send_id(resource, workspace->id);
|
|
||||||
}
|
|
||||||
ext_workspace_handle_v1_send_state(resource, workspace->state);
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_stop(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
ext_workspace_manager_v1_send_finished(resource);
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl = {
|
|
||||||
.commit = manager_handle_commit,
|
|
||||||
.stop = manager_handle_stop,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void destroy_manager_resource(
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
|
||||||
wl_list_for_each_safe(workspace_res, tmp2,
|
|
||||||
&manager_res->workspace_resources,
|
|
||||||
manager_resource_link) {
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3;
|
|
||||||
wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources,
|
|
||||||
manager_resource_link) {
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove(&manager_res->link);
|
|
||||||
wl_resource_set_user_data(manager_res->resource, NULL);
|
|
||||||
free(manager_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
manager_resource_from_resource(resource);
|
|
||||||
if (manager_res) {
|
|
||||||
destroy_manager_resource(manager_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
|
||||||
struct wl_resource *resource = group_res->resource;
|
|
||||||
struct wl_client *client = wl_resource_get_client(resource);
|
|
||||||
|
|
||||||
ext_workspace_group_handle_v1_send_capabilities(resource, group->caps);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
|
||||||
wl_list_for_each(group_output, &group->outputs, link) {
|
|
||||||
struct wl_resource *output_resource;
|
|
||||||
wl_resource_for_each(output_resource,
|
|
||||||
&group_output->output->resources) {
|
|
||||||
if (wl_resource_get_client(output_resource) == client) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(
|
|
||||||
resource, output_resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
|
||||||
uint32_t id) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
calloc(1, sizeof(*manager_res));
|
|
||||||
if (!manager_res) {
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_res->manager = manager;
|
|
||||||
wl_list_init(&manager_res->requests);
|
|
||||||
wl_list_init(&manager_res->workspace_resources);
|
|
||||||
wl_list_init(&manager_res->group_resources);
|
|
||||||
|
|
||||||
manager_res->resource = wl_resource_create(
|
|
||||||
client, &ext_workspace_manager_v1_interface, version, id);
|
|
||||||
if (!manager_res->resource) {
|
|
||||||
free(manager_res);
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(manager_res->resource, &manager_impl,
|
|
||||||
manager_res, manager_resource_destroy);
|
|
||||||
wl_list_insert(&manager->resources, &manager_res->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
wl_list_for_each(group, &manager->groups, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
create_group_resource(group, manager_res);
|
|
||||||
if (!group_res) {
|
|
||||||
wl_resource_post_no_memory(manager_res->resource);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
|
||||||
group_res->resource);
|
|
||||||
group_send_details(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
wl_list_for_each(workspace, &manager->workspaces, link) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
create_workspace_resource(workspace, manager_res);
|
|
||||||
if (!workspace_res) {
|
|
||||||
wl_resource_post_no_memory(manager_res->resource);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
|
||||||
workspace_res->resource);
|
|
||||||
workspace_send_details(workspace_res);
|
|
||||||
|
|
||||||
if (!workspace->group) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &workspace->group->resources, link) {
|
|
||||||
if (group_res->manager == manager_res) {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_display_destroy(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager =
|
|
||||||
wl_container_of(listener, manager, display_destroy);
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
|
||||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
|
||||||
wl_list_for_each_safe(group, tmp, &manager->groups, link) {
|
|
||||||
wlr_ext_workspace_group_handle_v1_destroy(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, *tmp2;
|
|
||||||
wl_list_for_each_safe(workspace, tmp2, &manager->workspaces, link) {
|
|
||||||
wlr_ext_workspace_handle_v1_destroy(workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3;
|
|
||||||
wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) {
|
|
||||||
destroy_manager_resource(manager_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager->idle_source) {
|
|
||||||
wl_event_source_remove(manager->idle_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove(&manager->display_destroy.link);
|
|
||||||
wl_global_destroy(manager->global);
|
|
||||||
free(manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *
|
|
||||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
|
||||||
uint32_t version) {
|
|
||||||
assert(version <= EXT_WORKSPACE_V1_VERSION);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = calloc(1, sizeof(*manager));
|
|
||||||
if (!manager) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->global =
|
|
||||||
wl_global_create(display, &ext_workspace_manager_v1_interface, version,
|
|
||||||
manager, manager_bind);
|
|
||||||
if (!manager->global) {
|
|
||||||
free(manager);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->event_loop = wl_display_get_event_loop(display);
|
|
||||||
|
|
||||||
manager->display_destroy.notify = manager_handle_display_destroy;
|
|
||||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
|
||||||
|
|
||||||
wl_list_init(&manager->groups);
|
|
||||||
wl_list_init(&manager->workspaces);
|
|
||||||
wl_list_init(&manager->resources);
|
|
||||||
wl_signal_init(&manager->events.destroy);
|
|
||||||
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *
|
|
||||||
wlr_ext_workspace_group_handle_v1_create(
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps) {
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group = calloc(1, sizeof(*group));
|
|
||||||
if (!group) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
group->manager = manager;
|
|
||||||
group->caps = caps;
|
|
||||||
|
|
||||||
wl_list_init(&group->outputs);
|
|
||||||
wl_list_init(&group->resources);
|
|
||||||
wl_signal_init(&group->events.create_workspace);
|
|
||||||
wl_signal_init(&group->events.destroy);
|
|
||||||
|
|
||||||
wl_list_insert(manager->groups.prev, &group->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
create_group_resource(group, manager_res);
|
|
||||||
if (!group_res) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
|
||||||
group_res->resource);
|
|
||||||
group_send_details(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(manager);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
bool enter) {
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group->resources, link) {
|
|
||||||
if (group_res->manager != workspace_res->manager) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (enter) {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
} else {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_leave(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
|
||||||
wl_list_remove(&group_output->output_bind.link);
|
|
||||||
wl_list_remove(&group_output->output_destroy.link);
|
|
||||||
wl_list_remove(&group_output->link);
|
|
||||||
free(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output, bool enter) {
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group->resources, link) {
|
|
||||||
struct wl_client *client = wl_resource_get_client(group_res->resource);
|
|
||||||
|
|
||||||
struct wl_resource *output_resource;
|
|
||||||
wl_resource_for_each(output_resource, &output->resources) {
|
|
||||||
if (wl_resource_get_client(output_resource) != client) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (enter) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(
|
|
||||||
group_res->resource, output_resource);
|
|
||||||
} else {
|
|
||||||
ext_workspace_group_handle_v1_send_output_leave(
|
|
||||||
group_res->resource, output_resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
|
||||||
if (!group) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
|
||||||
|
|
||||||
assert(wl_list_empty(&group->events.create_workspace.listener_list));
|
|
||||||
assert(wl_list_empty(&group->events.destroy.listener_list));
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
wl_list_for_each(workspace, &group->manager->workspaces, link) {
|
|
||||||
if (workspace->group == group) {
|
|
||||||
workspace_send_group(workspace, group, false);
|
|
||||||
workspace->group = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp;
|
|
||||||
wl_list_for_each_safe(group_res, tmp, &group->resources, link) {
|
|
||||||
ext_workspace_group_handle_v1_send_removed(group_res->resource);
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp2;
|
|
||||||
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
|
|
||||||
if (req->group == group) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
|
||||||
wl_list_for_each_safe(group_output, tmp3, &group->outputs, link) {
|
|
||||||
group_send_output(group, group_output->output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
|
|
||||||
wl_list_remove(&group->link);
|
|
||||||
free(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_output_bind(struct wl_listener *listener, void *data) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
wl_container_of(listener, group_output, output_bind);
|
|
||||||
struct wlr_output_event_bind *event = data;
|
|
||||||
struct wl_client *client = wl_resource_get_client(event->resource);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group_output->group->resources, link) {
|
|
||||||
if (wl_resource_get_client(group_res->resource) == client) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(group_res->resource,
|
|
||||||
event->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group_output->group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
wl_container_of(listener, group_output, output_destroy);
|
|
||||||
group_send_output(group_output->group, group_output->output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_group_output *
|
|
||||||
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
|
||||||
wl_list_for_each(group_output, &group->outputs, link) {
|
|
||||||
if (group_output->output == output) {
|
|
||||||
return group_output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
if (get_group_output(group, output)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
calloc(1, sizeof(*group_output));
|
|
||||||
if (!group_output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
group_output->output = output;
|
|
||||||
group_output->group = group;
|
|
||||||
wl_list_insert(&group->outputs, &group_output->link);
|
|
||||||
|
|
||||||
group_output->output_bind.notify = handle_output_bind;
|
|
||||||
wl_signal_add(&output->events.bind, &group_output->output_bind);
|
|
||||||
group_output->output_destroy.notify = handle_output_destroy;
|
|
||||||
wl_signal_add(&output->events.destroy, &group_output->output_destroy);
|
|
||||||
|
|
||||||
group_send_output(group, output, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
get_group_output(group, output);
|
|
||||||
if (!group_output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
group_send_output(group, output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *
|
|
||||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
|
||||||
const char *id, uint32_t caps) {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace =
|
|
||||||
calloc(1, sizeof(*workspace));
|
|
||||||
if (!workspace) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace->manager = manager;
|
|
||||||
workspace->caps = caps;
|
|
||||||
|
|
||||||
if (id) {
|
|
||||||
workspace->id = strdup(id);
|
|
||||||
if (!workspace->id) {
|
|
||||||
free(workspace);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&workspace->resources);
|
|
||||||
wl_array_init(&workspace->coordinates);
|
|
||||||
wl_signal_init(&workspace->events.activate);
|
|
||||||
wl_signal_init(&workspace->events.deactivate);
|
|
||||||
wl_signal_init(&workspace->events.remove);
|
|
||||||
wl_signal_init(&workspace->events.assign);
|
|
||||||
wl_signal_init(&workspace->events.destroy);
|
|
||||||
|
|
||||||
wl_list_insert(&manager->workspaces, &workspace->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
create_workspace_resource(workspace, manager_res);
|
|
||||||
if (!workspace_res) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
|
||||||
workspace_res->resource);
|
|
||||||
workspace_send_details(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(manager);
|
|
||||||
|
|
||||||
return workspace;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
|
||||||
if (!workspace) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
|
||||||
|
|
||||||
assert(wl_list_empty(&workspace->events.activate.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.deactivate.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.remove.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.assign.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
|
||||||
|
|
||||||
if (workspace->group) {
|
|
||||||
workspace_send_group(workspace, workspace->group, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp;
|
|
||||||
wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_removed(workspace_res->resource);
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp2;
|
|
||||||
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
|
|
||||||
if (req->workspace == workspace) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
|
|
||||||
wl_list_remove(&workspace->link);
|
|
||||||
wl_array_release(&workspace->coordinates);
|
|
||||||
free(workspace->id);
|
|
||||||
free(workspace->name);
|
|
||||||
free(workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_group(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
|
||||||
if (workspace->group == group) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workspace->group) {
|
|
||||||
workspace_send_group(workspace, workspace->group, false);
|
|
||||||
}
|
|
||||||
workspace->group = group;
|
|
||||||
if (group) {
|
|
||||||
workspace_send_group(workspace, group, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_name(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name) {
|
|
||||||
assert(name);
|
|
||||||
|
|
||||||
if (workspace->name && strcmp(workspace->name, name) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(workspace->name);
|
|
||||||
workspace->name = strdup(name);
|
|
||||||
if (workspace->name == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_name(workspace_res->resource,
|
|
||||||
workspace->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array_equal(struct wl_array *a, struct wl_array *b) {
|
|
||||||
return (a->size == b->size) &&
|
|
||||||
(a->size == 0 || memcmp(a->data, b->data, a->size) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wl_array *coordinates) {
|
|
||||||
assert(coordinates);
|
|
||||||
|
|
||||||
if (array_equal(&workspace->coordinates, coordinates)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_array_release(&workspace->coordinates);
|
|
||||||
wl_array_init(&workspace->coordinates);
|
|
||||||
wl_array_copy(&workspace->coordinates, coordinates);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_coordinates(workspace_res->resource,
|
|
||||||
&workspace->coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
enum ext_workspace_handle_v1_state state,
|
|
||||||
bool enabled) {
|
|
||||||
uint32_t old_state = workspace->state;
|
|
||||||
if (enabled) {
|
|
||||||
workspace->state |= state;
|
|
||||||
} else {
|
|
||||||
workspace->state &= ~state;
|
|
||||||
}
|
|
||||||
if (old_state == workspace->state) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_state(workspace_res->resource,
|
|
||||||
workspace->state);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_active(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
// bash on: https://gitlab.freedesktop.org/tokyo4j/wlroots/-/tree/ext-workspace
|
|
||||||
// TODO: remove this file
|
|
||||||
// refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115
|
|
||||||
|
|
||||||
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
|
||||||
#include <wayland-server-core.h>
|
|
||||||
|
|
||||||
struct wlr_output;
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 {
|
|
||||||
struct wl_global *global;
|
|
||||||
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
|
||||||
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
|
||||||
struct wl_event_source *idle_source;
|
|
||||||
struct wl_event_loop *event_loop;
|
|
||||||
struct wl_listener display_destroy;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1_create_workspace_event {
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
|
||||||
struct {
|
|
||||||
struct wl_signal
|
|
||||||
create_workspace; // wlr_ext_workspace_group_handle_v1_create_workspace_event
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL
|
|
||||||
char *id;
|
|
||||||
char *name;
|
|
||||||
struct wl_array coordinates;
|
|
||||||
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
|
|
||||||
uint32_t state; // ext_workspace_handle_v1_state
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_signal activate;
|
|
||||||
struct wl_signal deactivate;
|
|
||||||
struct wl_signal remove;
|
|
||||||
struct wl_signal assign; // wlr_ext_workspace_group_handle_v1
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *
|
|
||||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
|
||||||
uint32_t version);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *
|
|
||||||
wlr_ext_workspace_group_handle_v1_create(
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps);
|
|
||||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *
|
|
||||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
|
||||||
const char *id, uint32_t caps);
|
|
||||||
void wlr_ext_workspace_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace);
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_group(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_name(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wl_array *coordinates);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_active(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
|
|
@ -96,3 +96,12 @@ Monitor *xytomon(double x, double y) {
|
||||||
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
||||||
return o ? o->data : NULL;
|
return o ? o->data : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Monitor *get_monitor_nearest_to(int32_t lx, int32_t ly) {
|
||||||
|
double closest_x, closest_y;
|
||||||
|
wlr_output_layout_closest_point(output_layout, NULL, lx, ly, &closest_x,
|
||||||
|
&closest_y);
|
||||||
|
|
||||||
|
return output_from_wlr_output(
|
||||||
|
wlr_output_layout_output_at(output_layout, closest_x, closest_y));
|
||||||
|
}
|
||||||
|
|
|
||||||
86
src/mango.c
86
src/mango.c
|
|
@ -40,8 +40,10 @@
|
||||||
#include <wlr/types/wlr_drm_lease_v1.h>
|
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||||
#include <wlr/types/wlr_ext_data_control_v1.h>
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||||
|
#include <wlr/types/wlr_fixes.h>
|
||||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||||
|
|
@ -316,6 +318,10 @@ struct Client {
|
||||||
struct wlr_scene_shadow *shadow;
|
struct wlr_scene_shadow *shadow;
|
||||||
struct wlr_scene_blur *blur;
|
struct wlr_scene_blur *blur;
|
||||||
struct wlr_scene_tree *scene_surface;
|
struct wlr_scene_tree *scene_surface;
|
||||||
|
struct wlr_scene_tree *image_capture_tree;
|
||||||
|
struct wlr_scene *image_capture_scene;
|
||||||
|
struct wlr_ext_image_capture_source_v1 *image_capture_source;
|
||||||
|
struct wlr_scene_surface *image_capture_scene_surface;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wl_list flink;
|
struct wl_list flink;
|
||||||
struct wl_list fadeout_link;
|
struct wl_list fadeout_link;
|
||||||
|
|
@ -407,6 +413,7 @@ struct Client {
|
||||||
float unfocused_opacity;
|
float unfocused_opacity;
|
||||||
char oldmonname[128];
|
char oldmonname[128];
|
||||||
int32_t noblur;
|
int32_t noblur;
|
||||||
|
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
|
||||||
double master_mfact_per, master_inner_per, stack_inner_per;
|
double master_mfact_per, master_inner_per, stack_inner_per;
|
||||||
double old_master_mfact_per, old_master_inner_per, old_stack_inner_per;
|
double old_master_mfact_per, old_master_inner_per, old_stack_inner_per;
|
||||||
double old_scroller_pproportion;
|
double old_scroller_pproportion;
|
||||||
|
|
@ -683,6 +690,7 @@ static void virtualkeyboard(struct wl_listener *listener, void *data);
|
||||||
static void virtualpointer(struct wl_listener *listener, void *data);
|
static void virtualpointer(struct wl_listener *listener, void *data);
|
||||||
static void warp_cursor(const Client *c);
|
static void warp_cursor(const Client *c);
|
||||||
static Monitor *xytomon(double x, double y);
|
static Monitor *xytomon(double x, double y);
|
||||||
|
static Monitor *get_monitor_nearest_to(int32_t x, int32_t y);
|
||||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
static void clear_fullscreen_flag(Client *c);
|
static void clear_fullscreen_flag(Client *c);
|
||||||
|
|
@ -845,7 +853,13 @@ static struct wl_list keyboard_shortcut_inhibitors;
|
||||||
static uint32_t cursor_mode;
|
static uint32_t cursor_mode;
|
||||||
static Client *grabc;
|
static Client *grabc;
|
||||||
static int32_t rzcorner;
|
static int32_t rzcorner;
|
||||||
static int32_t grabcx, grabcy; /* client-relative */
|
static int32_t grabcx, grabcy; /* client-relative */
|
||||||
|
|
||||||
|
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1
|
||||||
|
*ext_foreign_toplevel_image_capture_source_manager_v1;
|
||||||
|
static struct wl_listener new_foreign_toplevel_capture_request;
|
||||||
|
static struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
||||||
|
|
||||||
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
||||||
static bool start_drag_window = false;
|
static bool start_drag_window = false;
|
||||||
static int32_t last_apply_drap_time = 0;
|
static int32_t last_apply_drap_time = 0;
|
||||||
|
|
@ -2147,6 +2161,7 @@ void cleanuplisteners(void) {
|
||||||
wl_list_remove(&request_start_drag.link);
|
wl_list_remove(&request_start_drag.link);
|
||||||
wl_list_remove(&start_drag.link);
|
wl_list_remove(&start_drag.link);
|
||||||
wl_list_remove(&new_session_lock.link);
|
wl_list_remove(&new_session_lock.link);
|
||||||
|
wl_list_remove(&new_foreign_toplevel_capture_request.link);
|
||||||
wl_list_remove(&tearing_new_object.link);
|
wl_list_remove(&tearing_new_object.link);
|
||||||
wl_list_remove(&keyboard_shortcuts_inhibit_new_inhibitor.link);
|
wl_list_remove(&keyboard_shortcuts_inhibit_new_inhibitor.link);
|
||||||
if (drm_lease_manager) {
|
if (drm_lease_manager) {
|
||||||
|
|
@ -3933,6 +3948,18 @@ mapnotify(struct wl_listener *listener, void *data) {
|
||||||
c->geom.width += 2 * c->bw;
|
c->geom.width += 2 * c->bw;
|
||||||
c->geom.height += 2 * c->bw;
|
c->geom.height += 2 * c->bw;
|
||||||
|
|
||||||
|
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
|
||||||
|
.app_id = client_get_appid(c),
|
||||||
|
.title = client_get_title(c),
|
||||||
|
};
|
||||||
|
|
||||||
|
c->image_capture_scene = wlr_scene_create();
|
||||||
|
c->ext_foreign_toplevel = wlr_ext_foreign_toplevel_handle_v1_create(
|
||||||
|
foreign_toplevel_list, &foreign_toplevel_state);
|
||||||
|
c->ext_foreign_toplevel->data = c;
|
||||||
|
c->image_capture_scene_surface = wlr_scene_surface_create(
|
||||||
|
&c->image_capture_scene->tree, client_surface(c));
|
||||||
|
|
||||||
/* Handle unmanaged clients first so we can return prior create borders
|
/* Handle unmanaged clients first so we can return prior create borders
|
||||||
*/
|
*/
|
||||||
if (client_is_unmanaged(c)) {
|
if (client_is_unmanaged(c)) {
|
||||||
|
|
@ -4279,6 +4306,26 @@ void outputmgrapply(struct wl_listener *listener, void *data) {
|
||||||
outputmgrapplyortest(config, 0);
|
outputmgrapplyortest(config, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_new_foreign_toplevel_capture_request(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request
|
||||||
|
*request = data;
|
||||||
|
Client *c = request->toplevel_handle->data;
|
||||||
|
|
||||||
|
if (c->image_capture_source == NULL) {
|
||||||
|
c->image_capture_source =
|
||||||
|
wlr_ext_image_capture_source_v1_create_with_scene_node(
|
||||||
|
&c->image_capture_scene->tree.node, event_loop, alloc, drw);
|
||||||
|
if (c->image_capture_source == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||||
|
request, c->image_capture_source);
|
||||||
|
}
|
||||||
|
|
||||||
void // 0.7 custom
|
void // 0.7 custom
|
||||||
outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int32_t test) {
|
outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int32_t test) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -5285,6 +5332,7 @@ void setup(void) {
|
||||||
wlr_subcompositor_create(dpy);
|
wlr_subcompositor_create(dpy);
|
||||||
wlr_alpha_modifier_v1_create(dpy);
|
wlr_alpha_modifier_v1_create(dpy);
|
||||||
wlr_ext_data_control_manager_v1_create(dpy, 1);
|
wlr_ext_data_control_manager_v1_create(dpy, 1);
|
||||||
|
wlr_fixes_create(dpy, 1);
|
||||||
|
|
||||||
// 在 setup 函数中
|
// 在 setup 函数中
|
||||||
wl_signal_init(&mango_print_status);
|
wl_signal_init(&mango_print_status);
|
||||||
|
|
@ -5300,6 +5348,15 @@ void setup(void) {
|
||||||
power_mgr = wlr_output_power_manager_v1_create(dpy);
|
power_mgr = wlr_output_power_manager_v1_create(dpy);
|
||||||
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode);
|
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode);
|
||||||
|
|
||||||
|
foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(dpy, 1);
|
||||||
|
ext_foreign_toplevel_image_capture_source_manager_v1 =
|
||||||
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(dpy, 1);
|
||||||
|
new_foreign_toplevel_capture_request.notify =
|
||||||
|
handle_new_foreign_toplevel_capture_request;
|
||||||
|
wl_signal_add(&ext_foreign_toplevel_image_capture_source_manager_v1->events
|
||||||
|
.new_request,
|
||||||
|
&new_foreign_toplevel_capture_request);
|
||||||
|
|
||||||
tearing_control = wlr_tearing_control_manager_v1_create(dpy, 1);
|
tearing_control = wlr_tearing_control_manager_v1_create(dpy, 1);
|
||||||
tearing_new_object.notify = handle_tearing_new_object;
|
tearing_new_object.notify = handle_tearing_new_object;
|
||||||
wl_signal_add(&tearing_control->events.new_object, &tearing_new_object);
|
wl_signal_add(&tearing_control->events.new_object, &tearing_new_object);
|
||||||
|
|
@ -5678,6 +5735,11 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
||||||
(!c->mon || VISIBLEON(c, c->mon)))
|
(!c->mon || VISIBLEON(c, c->mon)))
|
||||||
init_fadeout_client(c);
|
init_fadeout_client(c);
|
||||||
|
|
||||||
|
if (c->ext_foreign_toplevel) {
|
||||||
|
wlr_ext_foreign_toplevel_handle_v1_destroy(c->ext_foreign_toplevel);
|
||||||
|
c->ext_foreign_toplevel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// If the client is in a stack, remove it from the stack
|
// If the client is in a stack, remove it from the stack
|
||||||
|
|
||||||
if (c->swallowedby) {
|
if (c->swallowedby) {
|
||||||
|
|
@ -5762,6 +5824,8 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
||||||
c->next_in_stack = NULL;
|
c->next_in_stack = NULL;
|
||||||
c->prev_in_stack = NULL;
|
c->prev_in_stack = NULL;
|
||||||
|
|
||||||
|
wlr_scene_node_destroy(&c->image_capture_scene_surface->buffer->node);
|
||||||
|
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
|
||||||
wlr_scene_node_destroy(&c->scene->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
printstatus();
|
printstatus();
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|
@ -5911,6 +5975,14 @@ void updatetitle(struct wl_listener *listener, void *data) {
|
||||||
title = client_get_title(c);
|
title = client_get_title(c);
|
||||||
if (title && c->foreign_toplevel)
|
if (title && c->foreign_toplevel)
|
||||||
wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title);
|
wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title);
|
||||||
|
if (title && c->ext_foreign_toplevel) {
|
||||||
|
wlr_ext_foreign_toplevel_handle_v1_update_state(
|
||||||
|
c->ext_foreign_toplevel,
|
||||||
|
&(struct wlr_ext_foreign_toplevel_handle_v1_state){
|
||||||
|
.title = title,
|
||||||
|
.app_id = c->ext_foreign_toplevel->app_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (c == focustop(c->mon))
|
if (c == focustop(c->mon))
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
|
@ -6244,11 +6316,13 @@ void xwaylandready(struct wl_listener *listener, void *data) {
|
||||||
wlr_xwayland_set_seat(xwayland, seat);
|
wlr_xwayland_set_seat(xwayland, seat);
|
||||||
|
|
||||||
/* Set the default XWayland cursor to match the rest of dwl. */
|
/* Set the default XWayland cursor to match the rest of dwl. */
|
||||||
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
|
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1))) {
|
||||||
wlr_xwayland_set_cursor(
|
struct wlr_xcursor_image *image = xcursor->images[0];
|
||||||
xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
|
struct wlr_buffer *buffer = wlr_xcursor_image_get_buffer(image);
|
||||||
xcursor->images[0]->width, xcursor->images[0]->height,
|
wlr_xwayland_set_cursor(xwayland, buffer, xcursor->images[0]->hotspot_x,
|
||||||
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
|
xcursor->images[0]->hotspot_y);
|
||||||
|
}
|
||||||
|
|
||||||
/* xwayland can't auto sync the keymap, so we do it manually
|
/* xwayland can't auto sync the keymap, so we do it manually
|
||||||
and we need to wait the xwayland completely inited
|
and we need to wait the xwayland completely inited
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue