improve xdg + layer shell support
This commit is contained in:
144
xdg.c
144
xdg.c
@@ -5,7 +5,7 @@
|
||||
#include "xdg.h"
|
||||
#include "cursor.h"
|
||||
#include "node.h"
|
||||
#include "desktop.h"
|
||||
#include "view.h"
|
||||
#include "output.h"
|
||||
|
||||
static void xdg_popup_create(struct diyac_view *view, struct wlr_xdg_popup *wlr_popup);
|
||||
@@ -14,7 +14,7 @@ static void begin_interactive(struct diyac_view *toplevel,
|
||||
enum diyac_cursor_mode mode, uint32_t edges)
|
||||
{
|
||||
/* This function sets up an interactive move or resize operation, where the
|
||||
* compositor stops propegating pointer events to clients and instead
|
||||
* compositor stops propagating pointer events to clients and instead
|
||||
* consumes them itself, to move or resize windows. */
|
||||
struct diyac_server *server = toplevel->server;
|
||||
struct wlr_surface *focused_surface =
|
||||
@@ -57,24 +57,52 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
struct diyac_view *toplevel = wl_container_of(listener, toplevel, map);
|
||||
wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &toplevel->current);
|
||||
wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &toplevel->original);
|
||||
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true);
|
||||
toplevel->mapped = true;
|
||||
wl_list_insert(&toplevel->server->views, &toplevel->link);
|
||||
|
||||
diyac_focus_view(toplevel);
|
||||
toplevel->original.x = (toplevel->output->usable_area.width - toplevel->original.width) / 2;
|
||||
toplevel->original.y = (toplevel->output->usable_area.height - toplevel->original.height) / 2;
|
||||
if(toplevel->original.width > toplevel->output->usable_area.width)
|
||||
{
|
||||
toplevel->original.width = toplevel->output->usable_area.width;
|
||||
}
|
||||
if(toplevel->original.height > toplevel->output->usable_area.height)
|
||||
{
|
||||
toplevel->original.height = toplevel->output->usable_area.height;
|
||||
}
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
if (toplevel->state != DIYAC_VIEW_MINIMIZE)
|
||||
{
|
||||
diyac_focus_view(toplevel, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||
struct diyac_view *toplevel = wl_container_of(listener, toplevel, unmap);
|
||||
|
||||
toplevel->mapped = false;
|
||||
/* Reset the cursor mode if the grabbed toplevel was unmapped. */
|
||||
if (toplevel == toplevel->server->grabbed_view)
|
||||
{
|
||||
diyac_reset_cursor_mode(toplevel->server);
|
||||
}
|
||||
|
||||
if(toplevel->server->grabbed_view == toplevel)
|
||||
{
|
||||
toplevel->server->grabbed_view = NULL;
|
||||
}
|
||||
struct diyac_view * root = diyac_get_root_view(toplevel);
|
||||
wl_list_remove(&toplevel->link);
|
||||
if(root)
|
||||
{
|
||||
diyac_focus_view(root, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
diyac_cursor_focus(toplevel->server);
|
||||
}
|
||||
}
|
||||
|
||||
static void xdg_toplevel_request_move(
|
||||
@@ -128,35 +156,60 @@ static void xdg_toplevel_request_maximize(
|
||||
}
|
||||
struct diyac_output * target_output = output->data;
|
||||
*/
|
||||
if(toplevel->state == DIYAC_VIEW_MAXIMIZE)
|
||||
wlr_log(WLR_INFO, "Request maximize");
|
||||
diyac_reset_cursor_mode(toplevel->server);
|
||||
if (toplevel->state == DIYAC_VIEW_MAXIMIZE)
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_NORMAL;
|
||||
wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, false);
|
||||
// restore its default geometry
|
||||
}
|
||||
else
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_MAXIMIZE;
|
||||
}
|
||||
diyac_view_update_geometry(toplevel, true);
|
||||
// wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
//wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_request_fullscreen(
|
||||
struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Just as with request_maximize, we must send a configure here. */
|
||||
struct diyac_view *toplevel =
|
||||
wl_container_of(listener, toplevel, request_fullscreen);
|
||||
if(toplevel->state == DIYAC_VIEW_FULL_SCREEN)
|
||||
wlr_log(WLR_INFO, "Request fullscreen");
|
||||
/*
|
||||
diyac_reset_cursor_mode(toplevel->server);
|
||||
if (toplevel->state == DIYAC_VIEW_FULL_SCREEN)
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_NORMAL;
|
||||
wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false);
|
||||
// restore its default geometry
|
||||
}
|
||||
else
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_FULL_SCREEN;
|
||||
}
|
||||
diyac_view_update_geometry(toplevel, true);
|
||||
|
||||
*/
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct diyac_view *toplevel =
|
||||
wl_container_of(listener, toplevel, request_minimize);
|
||||
if (toplevel->state == DIYAC_VIEW_MINIMIZE)
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_NORMAL;
|
||||
// restore its default geometry
|
||||
}
|
||||
else
|
||||
{
|
||||
toplevel->state = DIYAC_VIEW_MINIMIZE;
|
||||
}
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
|
||||
@@ -171,7 +224,6 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&toplevel->request_resize.link);
|
||||
wl_list_remove(&toplevel->request_maximize.link);
|
||||
wl_list_remove(&toplevel->request_fullscreen.link);
|
||||
|
||||
free(toplevel);
|
||||
}
|
||||
|
||||
@@ -189,40 +241,51 @@ static void handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
|
||||
free(popup);
|
||||
}
|
||||
|
||||
static void
|
||||
popup_unconstrain(struct diyac_popup *popup)
|
||||
static void popup_unconstrain(struct diyac_popup *popup)
|
||||
{
|
||||
struct diyac_view *view = popup->parent;
|
||||
struct diyac_server *server = view->server;
|
||||
struct wlr_box *popup_box = &popup->wlr_popup->current.geometry;
|
||||
struct wlr_output_layout *output_layout = server->output_layout;
|
||||
struct wlr_output *wlr_output = wlr_output_layout_output_at(
|
||||
output_layout, view->current.x + popup_box->x,
|
||||
view->current.y + popup_box->y);
|
||||
|
||||
struct wlr_output *wlr_output = view->output->wlr_output;
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(output_layout, wlr_output, &output_box);
|
||||
|
||||
struct wlr_box geo_box = diyac_view_get_geometry(view);
|
||||
struct wlr_box output_toplevel_box = {
|
||||
.x = output_box.x - view->current.x,
|
||||
.y = output_box.y - view->current.y,
|
||||
.width = output_box.width,
|
||||
.height = output_box.height,
|
||||
.x = view->output->usable_area.x - geo_box.x,
|
||||
.y = view->output->usable_area.y - geo_box.y,
|
||||
.width = view->output->usable_area.width,
|
||||
.height = view->output->usable_area.height,
|
||||
};
|
||||
wlr_log(WLR_INFO, "Un constrain popup geometry: current x %d, y %d, popup [%d, %d, %d, %d] output_box: [%d, %d, %d, %d], caculate_box: [%d, %d, %d, %d]",
|
||||
view->original.x, view->original.y,
|
||||
geo_box.x, geo_box.y, geo_box.width, geo_box.height,
|
||||
output_box.x, output_box.y, output_box.width, output_box.height,
|
||||
output_toplevel_box.x, output_toplevel_box.y, output_toplevel_box.width, output_toplevel_box.height
|
||||
);
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box);
|
||||
}
|
||||
|
||||
static void handle_xdg_popup_commit(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct diyac_popup *popup = wl_container_of(listener, popup, commit);
|
||||
|
||||
if (popup->wlr_popup->base->initial_commit)
|
||||
struct wlr_box popup_box ;
|
||||
wlr_xdg_surface_get_geometry(popup->wlr_popup->base, &popup_box);
|
||||
popup_unconstrain(popup);
|
||||
if (!wlr_box_empty(&popup_box))
|
||||
//if (popup->wlr_popup->base->initial_commit)
|
||||
{
|
||||
popup_unconstrain(popup);
|
||||
|
||||
struct diyac_view *view = popup->parent;
|
||||
//wlr_output_commit(view->output->wlr_output);
|
||||
/* Prevent getting called over and over again */
|
||||
wl_list_remove(&popup->commit.link);
|
||||
popup->commit.notify = NULL;
|
||||
// force commit output
|
||||
}
|
||||
else
|
||||
{
|
||||
wlr_log(WLR_INFO, "ignore commit 2");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +293,7 @@ static void handle_xdg_popup_new(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct diyac_popup *popup = wl_container_of(listener, popup, new_popup);
|
||||
struct wlr_xdg_popup *wlr_popup = data;
|
||||
|
||||
xdg_popup_create(popup->parent, wlr_popup);
|
||||
}
|
||||
|
||||
@@ -275,15 +339,25 @@ static void xdg_popup_create(struct diyac_view *view, struct wlr_xdg_popup *wlr_
|
||||
else
|
||||
{
|
||||
parent_tree = view->server->xdg_popup_tree;
|
||||
struct wlr_box box = diyac_view_get_geometry(view);
|
||||
wlr_scene_node_set_position(&view->server->xdg_popup_tree->node,
|
||||
view->current.x, view->current.y);
|
||||
box.x, box.y);
|
||||
}
|
||||
wlr_popup->base->surface->data =
|
||||
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
|
||||
struct wlr_scene_tree* tree= wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
|
||||
wlr_popup->base->surface->data = tree;
|
||||
|
||||
//wlr_scene_node_set_enabled(&parent_tree->node, false);
|
||||
diyac_node_descriptor_create(wlr_popup->base->surface->data,
|
||||
DIYAC_NODE_XDG_POPUP, view);
|
||||
}
|
||||
|
||||
static void xdg_set_appid_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct diyac_view *xdg_toplevel_view =
|
||||
wl_container_of(listener, xdg_toplevel_view, set_app_id);
|
||||
wlr_log(WLR_INFO, "set application id");
|
||||
}
|
||||
|
||||
static void xdg_new_popup_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
wlr_log(WLR_INFO, "xdg_new_popup_notify: Creating new dialog");
|
||||
@@ -328,12 +402,14 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data)
|
||||
toplevel->server = server;
|
||||
toplevel->xdg_toplevel = xdg_surface->toplevel;
|
||||
toplevel->xdg_surface = xdg_surface;
|
||||
toplevel->mapped = false;
|
||||
toplevel->output = diyac_output_from_cursor(server);
|
||||
toplevel->scene_tree = wlr_scene_xdg_surface_create(
|
||||
toplevel->server->view_tree, toplevel->xdg_toplevel->base);
|
||||
xdg_surface->data = toplevel;
|
||||
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false);
|
||||
diyac_node_descriptor_create(&toplevel->scene_tree->node,
|
||||
DIYAC_NODE_VIEW, toplevel);
|
||||
DIYAC_NODE_VIEW, toplevel);
|
||||
/* Listen to the various events it can emit */
|
||||
toplevel->map.notify = xdg_toplevel_map;
|
||||
wl_signal_add(&xdg_surface->surface->events.map, &toplevel->map);
|
||||
@@ -348,6 +424,8 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data)
|
||||
wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
|
||||
toplevel->request_resize.notify = xdg_toplevel_request_resize;
|
||||
wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize);
|
||||
toplevel->request_minimize.notify = xdg_toplevel_request_minimize;
|
||||
wl_signal_add(&xdg_toplevel->events.request_minimize, &toplevel->request_minimize);
|
||||
toplevel->request_maximize.notify = xdg_toplevel_request_maximize;
|
||||
wl_signal_add(&xdg_toplevel->events.request_maximize,
|
||||
&toplevel->request_maximize);
|
||||
@@ -356,4 +434,6 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data)
|
||||
&toplevel->request_fullscreen);
|
||||
toplevel->new_popup.notify = xdg_new_popup_notify;
|
||||
wl_signal_add(&xdg_surface->events.new_popup, &toplevel->new_popup);
|
||||
toplevel->set_app_id.notify = xdg_set_appid_notify;
|
||||
wl_signal_add(&xdg_toplevel->events.set_app_id, &toplevel->set_app_id);
|
||||
}
|
Reference in New Issue
Block a user