mirror of
https://github.com/swaywm/sway.git
synced 2026-05-02 06:46:23 -04:00
Merge branch 'ipc-new-window' into multibackend
This commit is contained in:
commit
1c84c3b9b9
9 changed files with 155 additions and 15 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _SWAY_IPC_SERVER_H
|
||||
#define _SWAY_IPC_SERVER_H
|
||||
#include <sys/socket.h>
|
||||
#include "sway/container.h"
|
||||
#include "ipc.h"
|
||||
|
||||
struct sway_server;
|
||||
|
|
@ -9,4 +10,6 @@ void ipc_init(struct sway_server *server);
|
|||
void ipc_terminate(void);
|
||||
struct sockaddr_un *ipc_user_sockaddr(void);
|
||||
|
||||
void ipc_event_window(swayc_t *window, const char *change);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -115,4 +115,6 @@ void view_set_activated(struct sway_view *view, bool activated);
|
|||
|
||||
void view_close(struct sway_view *view);
|
||||
|
||||
void view_update_outputs(struct sway_view *view, const struct wlr_box *before);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static void render_surface(struct wlr_surface *surface,
|
|||
wlr_matrix_project_box(&matrix, &render_box,
|
||||
surface->current->transform, 0, &wlr_output->transform_matrix);
|
||||
wlr_render_with_matrix(server.renderer, surface->texture,
|
||||
&matrix);
|
||||
&matrix, 1.0f); // TODO: configurable alpha
|
||||
|
||||
wlr_surface_send_frame_done(surface, when);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,14 +131,11 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
|
|||
sway_surface->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy);
|
||||
|
||||
// TODO: actual focus semantics
|
||||
swayc_t *parent = root_container.children->items[0];
|
||||
parent = parent->children->items[0]; // workspace
|
||||
|
||||
swayc_t *cont = new_view(parent, sway_view);
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container);
|
||||
swayc_t *cont = new_view(focus, sway_view);
|
||||
sway_view->swayc = cont;
|
||||
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
|
||||
sway_input_manager_set_focus(input_manager, cont);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, sway_surface, commit);
|
||||
struct sway_view *view = sway_surface->view;
|
||||
// NOTE: We intentionally discard the view's desired width here
|
||||
// TODO: Store this for restoration when moving to floating plane
|
||||
// TODO: Let floating views do whatever
|
||||
view->width = sway_surface->pending_width;
|
||||
view->height = sway_surface->pending_height;
|
||||
|
|
|
|||
|
|
@ -226,17 +226,16 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
|
|||
wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify);
|
||||
sway_surface->map_notify.notify = handle_map_notify;
|
||||
|
||||
if (xsurface->override_redirect) {
|
||||
if (wlr_xwayland_surface_is_unmanaged(xsurface)) {
|
||||
// these don't get a container in the tree
|
||||
wl_list_insert(&root_container.sway_root->unmanaged_views,
|
||||
&sway_view->unmanaged_view_link);
|
||||
return;
|
||||
}
|
||||
|
||||
swayc_t *parent = root_container.children->items[0];
|
||||
parent = parent->children->items[0]; // workspace
|
||||
|
||||
swayc_t *cont = new_view(parent, sway_view);
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container);
|
||||
swayc_t *cont = new_view(focus, sway_view);
|
||||
sway_view->swayc = cont;
|
||||
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
|
|
|
|||
|
|
@ -240,6 +240,57 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ipc_send_event(const char *json_string, enum ipc_command_type event) {
|
||||
static struct {
|
||||
enum ipc_command_type event;
|
||||
enum ipc_feature feature;
|
||||
} security_mappings[] = {
|
||||
{ IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE },
|
||||
{ IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT },
|
||||
{ IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE },
|
||||
{ IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW },
|
||||
{ IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING },
|
||||
{ IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT }
|
||||
};
|
||||
|
||||
uint32_t security_mask = 0;
|
||||
for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) {
|
||||
if (security_mappings[i].event == event) {
|
||||
security_mask = security_mappings[i].feature;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
struct ipc_client *client;
|
||||
for (i = 0; i < ipc_client_list->length; i++) {
|
||||
client = ipc_client_list->items[i];
|
||||
if (!(client->security_policy & security_mask)) {
|
||||
continue;
|
||||
}
|
||||
if ((client->subscribed_events & event_mask(event)) == 0) {
|
||||
continue;
|
||||
}
|
||||
client->current_command = event;
|
||||
if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
|
||||
wlr_log_errno(L_INFO, "Unable to send reply to IPC client");
|
||||
ipc_client_disconnect(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ipc_event_window(swayc_t *window, const char *change) {
|
||||
wlr_log(L_DEBUG, "Sending window::%s event", change);
|
||||
json_object *obj = json_object_new_object();
|
||||
json_object_object_add(obj, "change", json_object_new_string(change));
|
||||
json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
|
||||
|
||||
const char *json_string = json_object_to_json_string(obj);
|
||||
ipc_send_event(json_string, IPC_EVENT_WINDOW);
|
||||
|
||||
json_object_put(obj); // free
|
||||
}
|
||||
|
||||
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
|
||||
struct ipc_client *client = data;
|
||||
|
||||
|
|
@ -361,6 +412,45 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
case IPC_SUBSCRIBE:
|
||||
{
|
||||
// TODO: Check if they're permitted to use these events
|
||||
struct json_object *request = json_tokener_parse(buf);
|
||||
if (request == NULL) {
|
||||
ipc_send_reply(client, "{\"success\": false}", 18);
|
||||
wlr_log_errno(L_INFO, "Failed to read request");
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
// parse requested event types
|
||||
for (size_t i = 0; i < json_object_array_length(request); i++) {
|
||||
const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
|
||||
if (strcmp(event_type, "workspace") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE);
|
||||
} else if (strcmp(event_type, "barconfig_update") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
|
||||
} else if (strcmp(event_type, "mode") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_MODE);
|
||||
} else if (strcmp(event_type, "window") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
|
||||
} else if (strcmp(event_type, "modifier") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER);
|
||||
} else if (strcmp(event_type, "binding") == 0) {
|
||||
client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
|
||||
} else {
|
||||
ipc_send_reply(client, "{\"success\": false}", 18);
|
||||
json_object_put(request);
|
||||
wlr_log_errno(L_INFO, "Failed to parse request");
|
||||
goto exit_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
json_object_put(request);
|
||||
|
||||
ipc_send_reply(client, "{\"success\": true}", 17);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
case IPC_GET_INPUTS:
|
||||
{
|
||||
json_object *inputs = json_object_new_array();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "sway/server.h"
|
||||
#include "sway/view.h"
|
||||
#include "sway/workspace.h"
|
||||
#include "sway/ipc-server.h"
|
||||
#include "log.h"
|
||||
|
||||
static list_t *bfs_queue;
|
||||
|
|
@ -32,6 +33,11 @@ static list_t *get_bfs_queue() {
|
|||
return bfs_queue;
|
||||
}
|
||||
|
||||
static void notify_new_container(swayc_t *container) {
|
||||
wl_signal_emit(&root_container.sway_root->events.new_container, container);
|
||||
ipc_event_window(container, "new");
|
||||
}
|
||||
|
||||
swayc_t *swayc_by_test(swayc_t *container,
|
||||
bool (*test)(swayc_t *view, void *data), void *data) {
|
||||
if (!container->children) {
|
||||
|
|
@ -175,7 +181,7 @@ swayc_t *new_output(struct sway_output *sway_output) {
|
|||
}
|
||||
|
||||
free(ws_name);
|
||||
wl_signal_emit(&root_container.sway_root->events.new_container, output);
|
||||
notify_new_container(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +203,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
|
|||
|
||||
add_child(output, workspace);
|
||||
sort_workspaces(output);
|
||||
wl_signal_emit(&root_container.sway_root->events.new_container, workspace);
|
||||
notify_new_container(workspace);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +228,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) {
|
|||
// Regular case, create as sibling of current container
|
||||
add_sibling(sibling, swayc);
|
||||
}
|
||||
wl_signal_emit(&root_container.sway_root->events.new_container, swayc);
|
||||
notify_new_container(swayc);
|
||||
return swayc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
#include <wayland-server.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include "sway/container.h"
|
||||
#include "sway/layout.h"
|
||||
#include "sway/view.h"
|
||||
|
||||
const char *view_get_title(struct sway_view *view) {
|
||||
|
|
@ -30,13 +34,27 @@ const char *view_get_instance(struct sway_view *view) {
|
|||
|
||||
void view_set_size(struct sway_view *view, int width, int height) {
|
||||
if (view->iface.set_size) {
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
view->iface.set_size(view, width, height);
|
||||
view_update_outputs(view, &box);
|
||||
}
|
||||
}
|
||||
|
||||
void view_set_position(struct sway_view *view, double ox, double oy) {
|
||||
if (view->iface.set_position) {
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
view->iface.set_position(view, ox, oy);
|
||||
view_update_outputs(view, &box);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,3 +69,27 @@ void view_close(struct sway_view *view) {
|
|||
view->iface.close(view);
|
||||
}
|
||||
}
|
||||
|
||||
void view_update_outputs(struct sway_view *view, const struct wlr_box *before) {
|
||||
struct wlr_output_layout *output_layout =
|
||||
root_container.sway_root->output_layout;
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
struct wlr_output_layout_output *layout_output;
|
||||
wl_list_for_each(layout_output, &output_layout->outputs, link) {
|
||||
bool intersected = before != NULL && wlr_output_layout_intersects(
|
||||
output_layout, layout_output->output, before);
|
||||
bool intersects = wlr_output_layout_intersects(output_layout,
|
||||
layout_output->output, &box);
|
||||
if (intersected && !intersects) {
|
||||
wlr_surface_send_leave(view->surface, layout_output->output);
|
||||
}
|
||||
if (!intersected && intersects) {
|
||||
wlr_surface_send_enter(view->surface, layout_output->output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue