Compare commits

...

2 Commits

Author SHA1 Message Date
DanyLE
bca498f387 better handling different window state, support fullscreen mode 2024-04-03 00:48:59 +02:00
DanyLE
1ae9cd000a feat: allows fullscreen support 2024-04-02 23:00:11 +02:00
5 changed files with 148 additions and 148 deletions

View File

@ -52,17 +52,18 @@ void diyac_reset_cursor_mode(struct diyac_server *server)
static void process_cursor_move(struct diyac_server *server, uint32_t time) static void process_cursor_move(struct diyac_server *server, uint32_t time)
{ {
/* Move the grabbed toplevel to the new position. */
struct diyac_view *toplevel = server->grabbed_view; struct diyac_view *toplevel = server->grabbed_view;
if (toplevel->state != DIYAC_VIEW_NORMAL) /* Move the grabbed toplevel to the new position. */
if (toplevel->state.fullscreen)
{ {
// cancel maximize or fullscreen state return;
wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, false); }
wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); if (toplevel->state.maximized)
{
toplevel->requested.maximized = false;
// move the windows to cursor // move the windows to cursor
server->grab_x = toplevel->original.width * server->grab_x / toplevel->output->usable_area.width; server->grab_x = toplevel->original.width * server->grab_x / toplevel->output->usable_area.width;
} }
toplevel->state = DIYAC_VIEW_NORMAL;
toplevel->original.y = server->seat.cursor->y - server->grab_y; toplevel->original.y = server->seat.cursor->y - server->grab_y;
toplevel->original.x = server->seat.cursor->x - server->grab_x; toplevel->original.x = server->seat.cursor->x - server->grab_x;
@ -87,6 +88,10 @@ static void process_cursor_resize(struct diyac_server *server, uint32_t time)
* size, then commit any movement that was prepared. * size, then commit any movement that was prepared.
*/ */
struct diyac_view *toplevel = server->grabbed_view; struct diyac_view *toplevel = server->grabbed_view;
if(toplevel->state.fullscreen)
{
return;
}
double border_x = server->seat.cursor->x - server->grab_x; double border_x = server->seat.cursor->x - server->grab_x;
double border_y = server->seat.cursor->y - server->grab_y; double border_y = server->seat.cursor->y - server->grab_y;
int new_left = server->grab_geobox.x; int new_left = server->grab_geobox.x;
@ -135,7 +140,7 @@ static void process_cursor_resize(struct diyac_server *server, uint32_t time)
int new_height = new_bottom - new_top; int new_height = new_bottom - new_top;
toplevel->original.width = new_width; toplevel->original.width = new_width;
toplevel->original.height = new_height; toplevel->original.height = new_height;
toplevel->state = DIYAC_VIEW_NORMAL; toplevel->requested.maximized = false;
diyac_view_update_geometry(toplevel, false); diyac_view_update_geometry(toplevel, false);
/* /*
wlr_scene_node_set_position(&toplevel->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,

16
diyac.h
View File

@ -37,12 +37,15 @@ enum diyac_node_descriptor_type
// LAB_NODE_TREE, // LAB_NODE_TREE,
// LAB_NODE_SSD_BUTTON, // LAB_NODE_SSD_BUTTON,
}; };
enum diyac_view_state struct diyac_view_state
{ {
DIYAC_VIEW_NORMAL = 0, bool maximized;
DIYAC_VIEW_MAXIMIZE, bool fullscreen;
DIYAC_VIEW_MINIMIZE, bool minimized;
DIYAC_VIEW_FULL_SCREEN, /**
* if neither state is on, it means that
* the current state is normal
*/
}; };
struct diyac_seat struct diyac_seat
@ -166,7 +169,8 @@ struct diyac_view
struct wlr_xdg_surface *xdg_surface; struct wlr_xdg_surface *xdg_surface;
struct wlr_xdg_toplevel *xdg_toplevel; struct wlr_xdg_toplevel *xdg_toplevel;
struct wlr_scene_tree *scene_tree; struct wlr_scene_tree *scene_tree;
enum diyac_view_state state; struct diyac_view_state state;
struct diyac_view_state requested;
/* /*
* Geometry of the wlr_surface contained within the view, as * Geometry of the wlr_surface contained within the view, as
* currently displayed. Should be kept in sync with the * currently displayed. Should be kept in sync with the

98
view.c
View File

@ -155,91 +155,107 @@ void diyac_arrange_all_views(struct diyac_server *server)
bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed) bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed)
{ {
assert(view); assert(view);
bool adjusted = false; struct wlr_box geo_box, intersect_box;
struct wlr_box geo_box;
struct wlr_box *geometry = &view->original; struct wlr_box *geometry = &view->original;
// if (wlr_output_layout_intersects(view->server->output_layout, // if (wlr_output_layout_intersects(view->server->output_layout,
// view->output->wlr_output, &view->current)) // view->output->wlr_output, &view->current))
//{ //{
if (!view->mapped)
{
wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base);
return false;
}
struct wlr_box usable = diyac_output_usable_area(view->output); struct wlr_box usable = diyac_output_usable_area(view->output);
wlr_log(WLR_DEBUG, "diyac_view_update_geometry: current: [%d,%d,%d,%d], usable: [%d,%d,%d,%d] ", wlr_log(WLR_DEBUG, "diyac_view_update_geometry: current: [%d,%d,%d,%d], usable: [%d,%d,%d,%d] ",
geometry->x, geometry->y, geometry->width, geometry->height, geometry->x, geometry->y, geometry->width, geometry->height,
usable.x, usable.y, usable.width, usable.height); usable.x, usable.y, usable.width, usable.height);
struct diyac_server *server = view->server; struct diyac_server *server = view->server;
if (!view->mapped) wlr_box_intersection(&intersect_box,geometry, &usable);
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box);
if ( wlr_box_equal(geometry, &geo_box) && diyac_view_state_equal(view->state,view->requested) && wlr_box_empty(&intersect_box))
{ {
view->state = DIYAC_VIEW_NORMAL; wlr_log(WLR_INFO, "No geometry update needed");
return false; return false;
} }
switch (view->state) // invalidate old state if change state
if(view->state.fullscreen && !view->requested.fullscreen)
{
wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false);
wlr_scene_node_set_enabled(&view->output->scenes.top->node, true);
view->state.fullscreen = false;
}
if(view->state.maximized && !view->requested.maximized)
{
wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, false);
view->state.maximized = false;
}
view->state = view->requested;
if(view->requested.minimized)
{
// TODO implement minimize
return false;
}
else if(view->requested.fullscreen)
{
wlr_scene_node_set_enabled(&view->output->scenes.top->node, false);
wlr_scene_node_set_position(&view->scene_tree->node, 0, 0);
wlr_xdg_toplevel_set_size(view->xdg_toplevel, view->output->wlr_output->width, view->output->wlr_output->height);
wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false);
return true;
}
else if(view->requested.maximized)
{ {
case DIYAC_VIEW_MAXIMIZE:
/**
* We dont change the current_view geometry in maximize state
*
*/
wlr_scene_node_set_position(&view->scene_tree->node, usable.x, usable.y); wlr_scene_node_set_position(&view->scene_tree->node, usable.x, usable.y);
wlr_xdg_toplevel_set_size(view->xdg_toplevel, usable.width, usable.height); wlr_xdg_toplevel_set_size(view->xdg_toplevel, usable.width, usable.height);
wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, true);
return true; return true;
case DIYAC_VIEW_MINIMIZE:
view->state = DIYAC_VIEW_NORMAL;
wlr_log(WLR_INFO, "diyac_view_update_geometry: minimize ignore");
return false;
case DIYAC_VIEW_FULL_SCREEN:
/*TODO: implement full-screen */
//view->state = DIYAC_VIEW_NORMAL;
wlr_log(WLR_INFO, "diyac_view_update_geometry: full-screen ignore");
return false;
default:
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box);
if (!wlr_box_equal(geometry, &geo_box))
{
adjusted = true;
} }
else
{
// if (wlr_output_layout_intersects(view->server->output_layout, // if (wlr_output_layout_intersects(view->server->output_layout,
// view->output->wlr_output, &view->current)) // view->output->wlr_output, &view->current))
//{ //{
/**Normal state, recalculate current geometry*/ /**Normal state, recalculate current geometry*/
struct diyac_view * root = diyac_get_root_view(view);
if(!root)
{
root = view;
}
if(!root->state.fullscreen)
{
// Only adjust position only when not in fullscreen mode
if (!grabbed && geometry->x < usable.x) if (!grabbed && geometry->x < usable.x)
{ {
geometry->x = usable.x; geometry->x = usable.x;
adjusted = true;
} }
if (!grabbed && geometry->y < usable.y) if (!grabbed && geometry->y < usable.y)
{ {
geometry->y = usable.y; geometry->y = usable.y;
adjusted = true;
} }
if (grabbed && server->seat.cursor->x <= usable.x) if (grabbed && server->seat.cursor->x <= usable.x)
{ {
geometry->x = usable.x - server->grab_x; geometry->x = usable.x - server->grab_x;
adjusted = true;
} }
if (grabbed && server->seat.cursor->y <= usable.y) if (grabbed && server->seat.cursor->y <= usable.y)
{ {
geometry->y = usable.y; geometry->y = usable.y;
adjusted = true;
} }
if (grabbed && server->seat.cursor->x >= usable.x + usable.width) if (grabbed && server->seat.cursor->x >= usable.x + usable.width)
{ {
geometry->x = usable.x + usable.width - server->grab_x; geometry->x = usable.x + usable.width - server->grab_x;
adjusted = true;
} }
if (grabbed && server->seat.cursor->y >= usable.y + usable.height) if (grabbed && server->seat.cursor->y >= usable.y + usable.height)
{ {
geometry->y = usable.y + usable.height - server->grab_y; geometry->y = usable.y + usable.height - server->grab_y;
adjusted = true; }
} }
if (adjusted)
{
wlr_log(WLR_DEBUG, "diyac_view_update_geometry: updating geometry: %d %d %d %d", geometry->x, geometry->y, geometry->width, geometry->height); wlr_log(WLR_DEBUG, "diyac_view_update_geometry: updating geometry: %d %d %d %d", geometry->x, geometry->y, geometry->width, geometry->height);
wlr_scene_node_set_position(&view->scene_tree->node, geometry->x, geometry->y); wlr_scene_node_set_position(&view->scene_tree->node, geometry->x, geometry->y);
wlr_xdg_toplevel_set_size(view->xdg_toplevel, geometry->width, geometry->height); wlr_xdg_toplevel_set_size(view->xdg_toplevel, geometry->width, geometry->height);
} return true;
return adjusted;
} }
} }
@ -278,14 +294,14 @@ struct diyac_view *diyac_get_root_view(struct diyac_view *view)
struct wlr_box diyac_view_get_geometry(struct diyac_view *view) struct wlr_box diyac_view_get_geometry(struct diyac_view *view)
{ {
struct wlr_box box; struct wlr_box box;
switch(view->state) if(view->state.fullscreen)
{ {
case DIYAC_VIEW_FULL_SCREEN:
wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box); wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box);
return box; return box;
case DIYAC_VIEW_MAXIMIZE:
return view->output->usable_area;
default:
return view->original;
} }
if(view->state.maximized)
{
return view->output->usable_area;
}
return view->original;
} }

3
view.h
View File

@ -1,6 +1,9 @@
#ifndef DIYAC_VIEW_H #ifndef DIYAC_VIEW_H
#define DIYAC_VIEW_H #define DIYAC_VIEW_H
#include "diyac.h" #include "diyac.h"
#define diyac_view_state_equal(a,b) ((a.fullscreen == b.fullscreen) \
&& (a.maximized == b.maximized) \
&& (a.minimized == b.minimized))
void diyac_focus_view(struct diyac_view *toplevel, bool raise); void diyac_focus_view(struct diyac_view *toplevel, bool raise);
struct diyac_view *diyac_view_at( struct diyac_view *diyac_view_at(
struct diyac_server *server, double lx, double ly, struct diyac_server *server, double lx, double ly,

100
xdg.c
View File

@ -79,10 +79,7 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data)
toplevel->original.height = toplevel->output->usable_area.height; toplevel->original.height = toplevel->output->usable_area.height;
} }
diyac_view_update_geometry(toplevel, false); diyac_view_update_geometry(toplevel, false);
if (toplevel->state != DIYAC_VIEW_MINIMIZE)
{
diyac_focus_view(toplevel, false); diyac_focus_view(toplevel, false);
}
} }
static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) static void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
@ -95,6 +92,14 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
{ {
diyac_reset_cursor_mode(toplevel->server); diyac_reset_cursor_mode(toplevel->server);
} }
if(toplevel->state.fullscreen)
{
/**
* When a client exit during fullscreen mode, the top layer shall
* be restored as it is currently disabled
*/
wlr_scene_node_set_enabled(&toplevel->output->scenes.top->node, true);
}
wl_list_remove(&toplevel->link); wl_list_remove(&toplevel->link);
} }
@ -106,7 +111,6 @@ static void xdg_toplevel_request_move(
* decorations. Note that a more sophisticated compositor should check the * decorations. Note that a more sophisticated compositor should check the
* provided serial against a list of button press serials sent to this * provided serial against a list of button press serials sent to this
* client, to prevent the client from requesting this whenever they want. */ * client, to prevent the client from requesting this whenever they want. */
wlr_log(WLR_INFO, "Request move");
struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_move); struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_move);
begin_interactive(toplevel, DIYAC_CURSOR_MOVE, 0); begin_interactive(toplevel, DIYAC_CURSOR_MOVE, 0);
} }
@ -119,7 +123,7 @@ static void xdg_toplevel_request_resize(
* decorations. Note that a more sophisticated compositor should check the * decorations. Note that a more sophisticated compositor should check the
* provided serial against a list of button press serials sent to this * provided serial against a list of button press serials sent to this
* client, to prevent the client from requesting this whenever they want. */ * client, to prevent the client from requesting this whenever they want. */
wlr_log(WLR_INFO, "Request resize");
struct wlr_xdg_toplevel_resize_event *event = data; struct wlr_xdg_toplevel_resize_event *event = data;
struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_resize); struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_resize);
begin_interactive(toplevel, DIYAC_CURSOR_RESIZE, event->edges); begin_interactive(toplevel, DIYAC_CURSOR_RESIZE, event->edges);
@ -136,74 +140,31 @@ static void xdg_toplevel_request_maximize(
struct diyac_view *toplevel = struct diyac_view *toplevel =
wl_container_of(listener, toplevel, request_maximize); wl_container_of(listener, toplevel, request_maximize);
if (!toplevel->mapped) toplevel->requested.maximized = toplevel->xdg_toplevel->requested.maximized;
{
wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, false);
// the view has not yet be mapped, don't maximize it
wlr_log(WLR_INFO, "The view has not yet be mapped, ignore maximize request");
return;
}
wlr_log(WLR_INFO, "Request maximize");
diyac_reset_cursor_mode(toplevel->server); 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
{
wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, true);
toplevel->state = DIYAC_VIEW_MAXIMIZE;
}
diyac_view_update_geometry(toplevel, false); 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) static void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void *data)
{ {
struct diyac_view *toplevel = struct diyac_view *toplevel =
wl_container_of(listener, toplevel, request_fullscreen); wl_container_of(listener, toplevel, request_fullscreen);
if (!toplevel->mapped) toplevel->requested.fullscreen = toplevel->xdg_toplevel->requested.fullscreen;
{ /**
wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false); * TODO: use client specific output for fullscreen
// the view has not yet be mapped, don't maximize it * toplevel->xdg_toplevel->requested.fullscreen_output
wlr_log(WLR_INFO, "The view has not yet be mapped, ignore fullscreen request");
return;
}
wlr_log(WLR_INFO, "Request fullscreen");
diyac_reset_cursor_mode(toplevel->server);
wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, false);
/*
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, false); diyac_reset_cursor_mode(toplevel->server);
diyac_view_update_geometry(toplevel, false);
} }
static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *data) static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *data)
{ {
struct diyac_view *toplevel = struct diyac_view *toplevel =
wl_container_of(listener, toplevel, request_minimize); wl_container_of(listener, toplevel, request_minimize);
if (toplevel->state == DIYAC_VIEW_MINIMIZE) toplevel->requested.minimized = toplevel->xdg_toplevel->requested.minimized;
{ //TODO implement minimize
toplevel->state = DIYAC_VIEW_NORMAL; wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
// restore its default geometry
}
else
{
toplevel->state = DIYAC_VIEW_MINIMIZE;
}
diyac_view_update_geometry(toplevel, false);
} }
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) static void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
@ -251,13 +212,23 @@ static void popup_unconstrain(struct diyac_popup *popup)
struct diyac_server *server = view->server; struct diyac_server *server = view->server;
struct wlr_output_layout *output_layout = server->output_layout; struct wlr_output_layout *output_layout = server->output_layout;
struct wlr_output *wlr_output = view->output->wlr_output; struct wlr_output *wlr_output = view->output->wlr_output;
struct wlr_box usable = {
.x = 0,
.y = 0,
.width = view->output->wlr_output->width,
.height = view->output->wlr_output->height
};
struct diyac_view *root = diyac_get_root_view(view);
if(!root || ! root->state.fullscreen)
{
usable = view->output->usable_area;
}
struct wlr_box geo_box = diyac_view_get_geometry(view); struct wlr_box geo_box = diyac_view_get_geometry(view);
struct wlr_box output_toplevel_box = { struct wlr_box output_toplevel_box = {
.x = view->output->usable_area.x - geo_box.x, .x = usable.x - geo_box.x,
.y = view->output->usable_area.y - geo_box.y, .y = usable.y - geo_box.y,
.width = view->output->usable_area.width, .width = usable.width,
.height = view->output->usable_area.height, .height = usable.height,
}; };
wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box); wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box);
} }
@ -386,7 +357,8 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data)
wlr_xdg_surface_ping(xdg_surface); wlr_xdg_surface_ping(xdg_surface);
/* Allocate a diyac_view for this surface */ /* Allocate a diyac_view for this surface */
struct diyac_view *toplevel = calloc(1, sizeof(*toplevel)); struct diyac_view *toplevel = calloc(1, sizeof(*toplevel));
toplevel->state = DIYAC_VIEW_NORMAL; memset(&toplevel->state, 0, sizeof(toplevel->state));
memset(&toplevel->requested, 0, sizeof(toplevel->requested));
toplevel->server = server; toplevel->server = server;
toplevel->xdg_toplevel = xdg_surface->toplevel; toplevel->xdg_toplevel = xdg_surface->toplevel;
toplevel->xdg_surface = xdg_surface; toplevel->xdg_surface = xdg_surface;