improve xdg + layer shell support
This commit is contained in:
parent
55719d6dba
commit
a54dcb682c
2
Makefile
2
Makefile
@ -11,7 +11,7 @@ OBJS=\
|
||||
output.c \
|
||||
seat.c \
|
||||
node.c \
|
||||
desktop.c \
|
||||
view.c \
|
||||
xdg.c \
|
||||
xdg-shell-protocol.c \
|
||||
layer.c \
|
||||
|
68
cursor.c
68
cursor.c
@ -2,23 +2,60 @@
|
||||
#include <wlr/util/log.h>
|
||||
#include <assert.h>
|
||||
#include "cursor.h"
|
||||
#include "desktop.h"
|
||||
#include "view.h"
|
||||
#include "seat.h"
|
||||
#include "node.h"
|
||||
|
||||
void diyac_cursor_focus(struct diyac_server *server)
|
||||
{
|
||||
double sx, sy;
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct diyac_node_descriptor *desc = diyac_node_at(server,
|
||||
server->seat.cursor->x, server->seat.cursor->y, &surface, &sx, &sy);
|
||||
struct diyac_layer_surface * layer;
|
||||
if(!desc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Focus that client if the button was _pressed_ */
|
||||
switch (desc->type)
|
||||
{
|
||||
case DIYAC_NODE_VIEW:
|
||||
diyac_focus_view(desc->data, true);
|
||||
break;
|
||||
case DIYAC_NODE_LAYER_SURFACE:
|
||||
layer = desc->data;
|
||||
assert(layer);
|
||||
assert(layer->scene_layer_surface);
|
||||
diyac_seat_focus_layer(&server->seat,layer->scene_layer_surface->layer_surface);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void diyac_reset_cursor_mode(struct diyac_server *server)
|
||||
{
|
||||
/* Reset the cursor mode to passthrough. */
|
||||
server->seat.cursor_mode = DIYAC_CURSOR_PASSTHROUGH;
|
||||
server->grabbed_view = NULL;
|
||||
//struct diyac_view * view = diyac_view_at()
|
||||
}
|
||||
|
||||
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;
|
||||
toplevel->current.x = server->seat.cursor->x - server->grab_x;
|
||||
toplevel->current.y = server->seat.cursor->y - server->grab_y;
|
||||
if(toplevel->state != DIYAC_VIEW_NORMAL)
|
||||
{
|
||||
// move the windows to cursor
|
||||
server->grab_x = toplevel->original.width * server->grab_x / toplevel->output->usable_area.width;
|
||||
}
|
||||
toplevel->state = DIYAC_VIEW_NORMAL;
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
toplevel->original.y = server->seat.cursor->y - server->grab_y;
|
||||
toplevel->original.x = server->seat.cursor->x - server->grab_x;
|
||||
|
||||
diyac_view_update_geometry(toplevel, true);
|
||||
/*
|
||||
wlr_scene_node_set_position(&toplevel->scene_tree->node,
|
||||
toplevel->current.x ,
|
||||
@ -81,14 +118,14 @@ static void process_cursor_resize(struct diyac_server *server, uint32_t time)
|
||||
|
||||
struct wlr_box geo_box;
|
||||
wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box);
|
||||
toplevel->current.x = new_left - geo_box.x;
|
||||
toplevel->current.y = new_top - geo_box.y;
|
||||
toplevel->original.x = new_left - geo_box.x;
|
||||
toplevel->original.y = new_top - geo_box.y;
|
||||
int new_width = new_right - new_left;
|
||||
int new_height = new_bottom - new_top;
|
||||
toplevel->current.width = new_width;
|
||||
toplevel->current.height = new_height;
|
||||
toplevel->original.width = new_width;
|
||||
toplevel->original.height = new_height;
|
||||
toplevel->state = DIYAC_VIEW_NORMAL;
|
||||
diyac_view_update_geometry(toplevel, true);
|
||||
diyac_view_update_geometry(toplevel, false);
|
||||
/*
|
||||
wlr_scene_node_set_position(&toplevel->scene_tree->node,
|
||||
toplevel->current.x, toplevel->current.y);
|
||||
@ -114,9 +151,9 @@ static void process_cursor_motion(struct diyac_server *server, uint32_t time)
|
||||
double sx, sy;
|
||||
struct wlr_seat *seat = server->seat.wlr_seat;
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct diyac_view *toplevel = diyac_view_at(server,
|
||||
struct diyac_node_descriptor *desc = diyac_node_at(server,
|
||||
server->seat.cursor->x, server->seat.cursor->y, &surface, &sx, &sy);
|
||||
if (!toplevel)
|
||||
if (!desc)
|
||||
{
|
||||
/* If there's no toplevel under the cursor, set the cursor image to a
|
||||
* default. This is what makes the cursor image appear when you move it
|
||||
@ -191,10 +228,7 @@ static void server_cursor_button(struct wl_listener *listener, void *data)
|
||||
/* Notify the client with pointer focus that a button press has occurred */
|
||||
wlr_seat_pointer_notify_button(seat->wlr_seat,
|
||||
event->time_msec, event->button, event->state);
|
||||
double sx, sy;
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct diyac_view *toplevel = diyac_view_at(seat->server,
|
||||
seat->cursor->x, seat->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
if (event->state == WLR_BUTTON_RELEASED)
|
||||
{
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
@ -202,8 +236,8 @@ static void server_cursor_button(struct wl_listener *listener, void *data)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Focus that client if the button was _pressed_ */
|
||||
diyac_focus_view(toplevel);
|
||||
diyac_cursor_focus(seat->server);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
1
cursor.h
1
cursor.h
@ -5,4 +5,5 @@
|
||||
|
||||
void diyac_init_cursor_manager(struct diyac_server * server);
|
||||
void diyac_reset_cursor_mode(struct diyac_server *server);
|
||||
void diyac_cursor_focus(struct diyac_server *server);
|
||||
#endif
|
12
desktop.h
12
desktop.h
@ -1,12 +0,0 @@
|
||||
#ifndef DIYAC_DESKTOP_H
|
||||
#define DIYAC_DESKTOP_H
|
||||
#include "diyac.h"
|
||||
void diyac_focus_view(struct diyac_view *toplevel);
|
||||
struct diyac_view *diyac_view_at(
|
||||
struct diyac_server *server, double lx, double ly,
|
||||
struct wlr_surface **surface, double *sx, double *sy);
|
||||
void diyac_focus_topmost_view(struct diyac_server *server);
|
||||
struct diyac_view * diyac_topmost_focusable_view(struct diyac_server *server);
|
||||
bool diyac_view_update_geometry(struct diyac_view *view, bool resize);
|
||||
void diyac_arrange_all_views(struct diyac_server *server);
|
||||
#endif
|
5
diyac.h
5
diyac.h
@ -167,8 +167,8 @@ struct diyac_view
|
||||
* currently displayed. Should be kept in sync with the
|
||||
* scene-graph at all times.
|
||||
*/
|
||||
struct wlr_box current;
|
||||
|
||||
struct wlr_box original;
|
||||
bool mapped;
|
||||
struct diyac_output *output;
|
||||
|
||||
struct wl_listener map;
|
||||
@ -176,6 +176,7 @@ struct diyac_view
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener request_move;
|
||||
struct wl_listener request_resize;
|
||||
struct wl_listener request_minimize;
|
||||
struct wl_listener request_maximize;
|
||||
struct wl_listener request_fullscreen;
|
||||
|
||||
|
13
layer.c
13
layer.c
@ -6,6 +6,7 @@
|
||||
#include "node.h"
|
||||
#include "output.h"
|
||||
#include "seat.h"
|
||||
#include "cursor.h"
|
||||
|
||||
static void popup_handle_new_popup(struct wl_listener *listener, void *data);
|
||||
static struct diyac_popup *create_layer_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent);
|
||||
@ -76,7 +77,6 @@ static void layer_surface_commit(struct wl_listener *listener, void *data)
|
||||
/* Process keyboard-interactivity change */
|
||||
if (committed & WLR_LAYER_SURFACE_V1_STATE_KEYBOARD_INTERACTIVITY)
|
||||
{
|
||||
wlr_log(WLR_INFO, "Process keyboard");
|
||||
process_keyboard_interactivity(layer);
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ static void layer_surface_commit(struct wl_listener *listener, void *data)
|
||||
* enter a new/moved/resized layer surface.
|
||||
*/
|
||||
// cursor_update_focus(layer->server);
|
||||
wlr_log(WLR_INFO, "update focus");
|
||||
diyac_cursor_focus(layer->server);
|
||||
}
|
||||
}
|
||||
static void
|
||||
@ -172,10 +172,13 @@ static void popup_handle_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);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &popup->output_toplevel_sx_box);
|
||||
if (!wlr_box_empty(&popup_box))
|
||||
//if (popup->wlr_popup->base->initial_commit)
|
||||
{
|
||||
|
||||
|
||||
/* Prevent getting called over and over again */
|
||||
wl_list_remove(&popup->commit.link);
|
||||
|
30
node.c
30
node.c
@ -35,3 +35,33 @@ struct diyac_view *diyac_view_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||
assert(node_descriptor->type == DIYAC_NODE_VIEW || node_descriptor->type == DIYAC_NODE_XDG_POPUP);
|
||||
return (struct diyac_view *)node_descriptor->data;
|
||||
}
|
||||
|
||||
struct diyac_node_descriptor * diyac_node_at(struct diyac_server* server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
|
||||
{
|
||||
/* This returns the topmost node in the scene at the given layout coords.
|
||||
* We only care about surface nodes as we are specifically looking for a
|
||||
* surface in the surface tree of a diyac_view. */
|
||||
struct wlr_scene_node *node = wlr_scene_node_at(
|
||||
&server->scene->tree.node, lx, ly, sx, sy);
|
||||
if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
||||
struct wlr_scene_surface *scene_surface =
|
||||
wlr_scene_surface_try_from_buffer(scene_buffer);
|
||||
if (!scene_surface)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*surface = scene_surface->surface;
|
||||
/* Find the node corresponding to the diyac_view at the root of this
|
||||
* surface tree, it is the only one for which we set the data field. */
|
||||
struct wlr_scene_tree *tree = node->parent;
|
||||
while (tree != NULL && tree->node.data == NULL)
|
||||
{
|
||||
tree = tree->node.parent;
|
||||
}
|
||||
return tree->node.data;
|
||||
}
|
1
node.h
1
node.h
@ -5,4 +5,5 @@
|
||||
void diyac_node_descriptor_create(struct wlr_scene_node *scene_node,enum diyac_node_descriptor_type type, void *data);
|
||||
struct diyac_layer_surface * diyac_layer_surface_from_node(struct wlr_scene_node *wlr_scene_node);
|
||||
struct diyac_view *diyac_view_from_node(struct wlr_scene_node *wlr_scene_node);
|
||||
struct diyac_node_descriptor * diyac_node_at(struct diyac_server* server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy);
|
||||
#endif
|
||||
|
2
output.c
2
output.c
@ -5,7 +5,7 @@
|
||||
#include "output.h"
|
||||
#include "layer.h"
|
||||
#include "node.h"
|
||||
#include "desktop.h"
|
||||
#include "view.h"
|
||||
static void output_frame(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* This function is called every time an output is ready to display a frame,
|
||||
|
6
seat.c
6
seat.c
@ -4,7 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "seat.h"
|
||||
#include "desktop.h"
|
||||
#include "view.h"
|
||||
|
||||
|
||||
static void keyboard_handle_modifiers(
|
||||
@ -48,7 +48,7 @@ static bool handle_keybinding(struct diyac_server *server, xkb_keysym_t sym)
|
||||
}
|
||||
struct diyac_view *next_toplevel =
|
||||
wl_container_of(server->views.prev, next_toplevel, link);
|
||||
diyac_focus_view(next_toplevel);
|
||||
diyac_focus_view(next_toplevel, true);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
@ -291,7 +291,7 @@ void diyac_seat_focus_surface(struct diyac_seat *seat, struct wlr_surface *surfa
|
||||
}
|
||||
|
||||
void diyac_seat_focus_layer(struct diyac_seat *seat, struct wlr_layer_surface_v1 *layer)
|
||||
{
|
||||
{ wlr_log(WLR_INFO, "diyac_seat_focus_layer");
|
||||
if (!layer)
|
||||
{
|
||||
seat->focused_layer = NULL;
|
||||
|
@ -1,23 +1,35 @@
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <wlr/util/log.h>
|
||||
#include <assert.h>
|
||||
#include "desktop.h"
|
||||
#include "view.h"
|
||||
#include "node.h"
|
||||
#include "seat.h"
|
||||
#include "output.h"
|
||||
|
||||
void diyac_focus_view(struct diyac_view *toplevel)
|
||||
static void raise_to_front(struct diyac_view *view)
|
||||
{
|
||||
/* Move the toplevel to the front */
|
||||
wlr_scene_node_raise_to_top(&view->scene_tree->node);
|
||||
wl_list_remove(&view->link);
|
||||
wl_list_insert(&view->server->views, &view->link);
|
||||
/* Activate the new surface */
|
||||
wlr_xdg_toplevel_set_activated(view->xdg_toplevel, true);
|
||||
}
|
||||
void diyac_focus_view(struct diyac_view *toplevel, bool raise)
|
||||
{
|
||||
/* Note: this function only deals with keyboard focus. */
|
||||
if (toplevel == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!toplevel->mapped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct diyac_server *server = toplevel->server;
|
||||
struct wlr_surface *prev_surface = server->seat.wlr_seat->keyboard_state.focused_surface;
|
||||
if (prev_surface == toplevel->xdg_toplevel->base->surface)
|
||||
{
|
||||
/* Don't re-focus an already focused surface. */
|
||||
// Don't re-focus an already focused surface.
|
||||
return;
|
||||
}
|
||||
if (prev_surface)
|
||||
@ -34,12 +46,20 @@ void diyac_focus_view(struct diyac_view *toplevel)
|
||||
wlr_xdg_toplevel_set_activated(prev_toplevel, false);
|
||||
}
|
||||
}
|
||||
/* Move the toplevel to the front */
|
||||
wlr_scene_node_raise_to_top(&toplevel->scene_tree->node);
|
||||
wl_list_remove(&toplevel->link);
|
||||
wl_list_insert(&server->views, &toplevel->link);
|
||||
/* Activate the new surface */
|
||||
wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true);
|
||||
raise_to_front(toplevel);
|
||||
if (raise)
|
||||
{
|
||||
struct diyac_view **subview = NULL;
|
||||
struct wl_array subviews;
|
||||
wl_array_init(&subviews);
|
||||
diyac_get_children_views(toplevel, &subviews);
|
||||
wl_array_for_each(subview, &subviews)
|
||||
{
|
||||
raise_to_front(*subview);
|
||||
}
|
||||
wl_array_release(&subviews);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell the seat to have the keyboard enter this surface. wlroots will keep
|
||||
* track of this and automatically send key events to the appropriate
|
||||
@ -52,46 +72,21 @@ struct diyac_view *diyac_view_at(
|
||||
struct diyac_server *server, double lx, double ly,
|
||||
struct wlr_surface **surface, double *sx, double *sy)
|
||||
{
|
||||
/* This returns the topmost node in the scene at the given layout coords.
|
||||
* We only care about surface nodes as we are specifically looking for a
|
||||
* surface in the surface tree of a diyac_view. */
|
||||
struct wlr_scene_node *node = wlr_scene_node_at(
|
||||
&server->scene->tree.node, lx, ly, sx, sy);
|
||||
if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
||||
struct wlr_scene_surface *scene_surface =
|
||||
wlr_scene_surface_try_from_buffer(scene_buffer);
|
||||
if (!scene_surface)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*surface = scene_surface->surface;
|
||||
/* Find the node corresponding to the diyac_view at the root of this
|
||||
* surface tree, it is the only one for which we set the data field. */
|
||||
struct wlr_scene_tree *tree = node->parent;
|
||||
while (tree != NULL && tree->node.data == NULL)
|
||||
{
|
||||
tree = tree->node.parent;
|
||||
}
|
||||
struct diyac_node_descriptor *node_descriptor = tree->node.data;
|
||||
struct diyac_node_descriptor *node_descriptor = diyac_node_at(server,lx,ly,surface,sx,sy);
|
||||
if (!node_descriptor || node_descriptor->type != DIYAC_NODE_VIEW)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node_descriptor->data;
|
||||
}
|
||||
|
||||
void diyac_focus_topmost_view(struct diyac_server *server)
|
||||
{
|
||||
wlr_log(WLR_INFO, "diyac_focus_topmost_view");
|
||||
struct diyac_view *view = diyac_topmost_focusable_view(server);
|
||||
if (view)
|
||||
{
|
||||
diyac_focus_view(view);
|
||||
diyac_focus_view(view, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -120,11 +115,11 @@ struct diyac_view *diyac_topmost_focusable_view(struct diyac_server *server)
|
||||
}
|
||||
view = diyac_view_from_node(node);
|
||||
return view;
|
||||
/*
|
||||
if (view->mapped && view_is_focusable_from(view, prev))
|
||||
|
||||
if (view->mapped /*&& view_is_focusable_from(view, prev)*/)
|
||||
{
|
||||
return view;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -144,15 +139,15 @@ void diyac_arrange_all_views(struct diyac_server *server)
|
||||
struct diyac_view *view;
|
||||
wl_list_for_each(view, &server->views, link)
|
||||
{
|
||||
diyac_view_update_geometry(view, true);
|
||||
diyac_view_update_geometry(view, false);
|
||||
}
|
||||
}
|
||||
bool diyac_view_update_geometry(struct diyac_view *view, bool resize)
|
||||
bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed)
|
||||
{
|
||||
assert(view);
|
||||
bool adjusted = false;
|
||||
struct wlr_box geo_box;
|
||||
struct wlr_box* geometry = &view->current;
|
||||
struct wlr_box *geometry = &view->original;
|
||||
// if (wlr_output_layout_intersects(view->server->output_layout,
|
||||
// view->output->wlr_output, &view->current))
|
||||
//{
|
||||
@ -160,7 +155,16 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool resize)
|
||||
wlr_log(WLR_INFO, "diyac_view_update_geometry: current: [%d,%d,%d,%d], usable: [%d,%d,%d,%d] ",
|
||||
geometry->x, geometry->y, geometry->width, geometry->height,
|
||||
usable.x, usable.y, usable.width, usable.height);
|
||||
|
||||
struct diyac_server *server = view->server;
|
||||
if (!view->mapped)
|
||||
{
|
||||
wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, false);
|
||||
wlr_xdg_toplevel_set_fullscreen(view->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 request");
|
||||
view->state = DIYAC_VIEW_NORMAL;
|
||||
return false;
|
||||
}
|
||||
switch (view->state)
|
||||
{
|
||||
case DIYAC_VIEW_MAXIMIZE:
|
||||
@ -168,14 +172,19 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool resize)
|
||||
* We dont change the current_view geometry in maximize state
|
||||
*
|
||||
*/
|
||||
wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, true);
|
||||
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);
|
||||
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");
|
||||
wlr_xdg_toplevel_set_fullscreen(view->xdg_toplevel, false);
|
||||
return false;
|
||||
|
||||
default:
|
||||
@ -184,43 +193,95 @@ bool diyac_view_update_geometry(struct diyac_view *view, bool resize)
|
||||
{
|
||||
adjusted = true;
|
||||
}
|
||||
// if (wlr_output_layout_intersects(view->server->output_layout,
|
||||
// view->output->wlr_output, &view->current))
|
||||
//{
|
||||
/**Normal state, recalculate current geometry*/
|
||||
if (geometry->x < usable.x)
|
||||
|
||||
if (!grabbed && geometry->x < usable.x)
|
||||
{
|
||||
geometry->x = usable.x;
|
||||
adjusted = true;
|
||||
}
|
||||
if((! resize) && (geometry->x + geometry->width > usable.width))
|
||||
{
|
||||
geometry->x = usable.width - geometry->width;
|
||||
adjusted = true;
|
||||
}
|
||||
if (geometry->y < usable.y)
|
||||
if (!grabbed && geometry->y < usable.y)
|
||||
{
|
||||
geometry->y = usable.y;
|
||||
adjusted = true;
|
||||
}
|
||||
if((! resize) && (geometry->y + geometry->height > usable.height))
|
||||
if (grabbed && server->seat.cursor->x <= usable.x)
|
||||
{
|
||||
geometry->y = usable.height - geometry->height;
|
||||
geometry->x = usable.x - server->grab_x;
|
||||
adjusted = true;
|
||||
}
|
||||
if (resize && geometry->width > usable.width)
|
||||
if (grabbed && server->seat.cursor->y <= usable.y)
|
||||
{
|
||||
geometry->width = usable.width;
|
||||
geometry->y = usable.y;
|
||||
adjusted = true;
|
||||
}
|
||||
if (resize && geometry->height > usable.height)
|
||||
if (grabbed && server->seat.cursor->x >= usable.x + usable.width)
|
||||
{
|
||||
geometry->height = usable.height;
|
||||
geometry->x = usable.x + usable.width - server->grab_x;
|
||||
adjusted = true;
|
||||
}
|
||||
if (grabbed && server->seat.cursor->y >= usable.y + usable.height)
|
||||
{
|
||||
geometry->y = usable.y + usable.height - server->grab_y;
|
||||
adjusted = true;
|
||||
}
|
||||
|
||||
if (adjusted)
|
||||
{
|
||||
wlr_log(WLR_INFO, "diyac_view_update_geometry: updating geometry");
|
||||
wlr_log(WLR_INFO, "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_xdg_toplevel_set_size(view->xdg_toplevel, geometry->width, geometry->height);
|
||||
}
|
||||
return adjusted;
|
||||
}
|
||||
}
|
||||
|
||||
void diyac_get_children_views(struct diyac_view *view, struct wl_array *children)
|
||||
{
|
||||
struct diyac_view *child;
|
||||
wl_list_for_each_reverse(child, &view->server->views, link)
|
||||
{
|
||||
if (child == view)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!child->mapped /*&& !view->minimized*/)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (diyac_get_root_view(child) != view)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
struct diyac_view **item = wl_array_add(children, sizeof(*item));
|
||||
*item = child;
|
||||
}
|
||||
}
|
||||
|
||||
struct diyac_view *diyac_get_root_view(struct diyac_view *view)
|
||||
{
|
||||
struct wlr_xdg_toplevel *toplevel = view->xdg_toplevel;
|
||||
while (toplevel->parent)
|
||||
{
|
||||
toplevel = toplevel->parent;
|
||||
}
|
||||
return toplevel->base->data;
|
||||
}
|
||||
|
||||
struct wlr_box diyac_view_get_geometry(struct diyac_view *view)
|
||||
{
|
||||
struct wlr_box box;
|
||||
switch(view->state)
|
||||
{
|
||||
case DIYAC_VIEW_FULL_SCREEN:
|
||||
wlr_output_layout_get_box(view->server->output_layout, view->output->wlr_output, &box);
|
||||
return box;
|
||||
case DIYAC_VIEW_MAXIMIZE:
|
||||
return view->output->usable_area;
|
||||
default:
|
||||
return view->original;
|
||||
}
|
||||
}
|
15
view.h
Normal file
15
view.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef DIYAC_VIEW_H
|
||||
#define DIYAC_VIEW_H
|
||||
#include "diyac.h"
|
||||
void diyac_focus_view(struct diyac_view *toplevel, bool raise);
|
||||
struct diyac_view *diyac_view_at(
|
||||
struct diyac_server *server, double lx, double ly,
|
||||
struct wlr_surface **surface, double *sx, double *sy);
|
||||
void diyac_focus_topmost_view(struct diyac_server *server);
|
||||
struct diyac_view * diyac_topmost_focusable_view(struct diyac_server *server);
|
||||
bool diyac_view_update_geometry(struct diyac_view *view, bool grabbed);
|
||||
void diyac_arrange_all_views(struct diyac_server *server);
|
||||
struct diyac_view *diyac_get_root_view(struct diyac_view *view);
|
||||
void diyac_get_children_views(struct diyac_view *view, struct wl_array *children);
|
||||
struct wlr_box diyac_view_get_geometry(struct diyac_view *view);
|
||||
#endif
|
136
xdg.c
136
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;
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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,10 +402,12 @@ 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);
|
||||
/* Listen to the various events it can emit */
|
||||
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user