mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
Support xwayland window title bar dragging
This commit is contained in:
parent
4c53bd8bf9
commit
83c3492c87
7 changed files with 109 additions and 42 deletions
4
Makefile
4
Makefile
|
|
@ -13,9 +13,11 @@ ASAN_FLAGS = -O0 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynami
|
|||
WP = `pkg-config --variable=pkgdatadir wayland-protocols`
|
||||
WS = `pkg-config --variable=wayland_scanner wayland-scanner`
|
||||
|
||||
OBJS = main.o xdg.o view.o xwl.o server.o output.o dbg.o deco.o
|
||||
|
||||
all: labwc
|
||||
|
||||
labwc: xdg-shell-protocol.o main.o xdg.o view.o xwl.o server.o output.o dbg.o
|
||||
labwc: xdg-shell-protocol.o $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
xdg-shell-protocol.h:
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
labwc is a wayland compositor based on wlroots
|
||||
|
||||
[https://imgur.com/rb2hJh3](https://imgur.com/rb2hJh3)
|
||||
|
||||
## Dependencies
|
||||
|
||||
- wlroots
|
||||
|
|
@ -15,7 +13,6 @@ labwc is a wayland compositor based on wlroots
|
|||
Alt+Escape Exit labwc
|
||||
Alt+F2 Cycle between windows
|
||||
Alt+F3 Launch dmenu
|
||||
Alt+F6 Move window
|
||||
Alt+F12 Print all views (helpful if run from X11)
|
||||
```
|
||||
|
||||
|
|
@ -47,7 +44,7 @@ In terms of size comparison of these two giants, it's worth reflecting on the si
|
|||
|
||||
[sway](https://github.com/swaywm/sway) - 37k LOC
|
||||
|
||||
[rootston](https://github.com/swaywm/wlroots/tree/master/rootston) - 7k LOC
|
||||
[rootston]() - 7k LOC
|
||||
|
||||
[openbox](https://github.com/danakj/openbox) - 53k LOC
|
||||
|
||||
|
|
|
|||
39
deco.c
Normal file
39
deco.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include "labwc.h"
|
||||
|
||||
struct wlr_box deco_max_extents(struct view *view)
|
||||
{
|
||||
struct wlr_box box = {
|
||||
.x = view->x - XWL_WINDOW_BORDER,
|
||||
.y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER,
|
||||
.width = view->surface->current.width + 2 * XWL_WINDOW_BORDER,
|
||||
.height = view->surface->current.height + XWL_TITLEBAR_HEIGHT +
|
||||
2 * XWL_WINDOW_BORDER,
|
||||
};
|
||||
return box;
|
||||
}
|
||||
|
||||
struct wlr_box deco_box(struct view *view, enum deco_part deco_part)
|
||||
{
|
||||
struct wlr_box box = { .x = 0, .y = 0, .width = 0, .height = 0 };
|
||||
if (!view)
|
||||
return;
|
||||
switch (deco_part) {
|
||||
case LAB_DECO_PART_TOP:
|
||||
box.x = view->x - XWL_WINDOW_BORDER;
|
||||
box.y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER;
|
||||
box.width = view->surface->current.width + 2 * XWL_WINDOW_BORDER;
|
||||
box.height = XWL_TITLEBAR_HEIGHT + XWL_WINDOW_BORDER;
|
||||
break;
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
enum deco_part deco_at(struct view *view, double lx, double ly)
|
||||
{
|
||||
struct wlr_box box;
|
||||
box = deco_box(view, LAB_DECO_PART_TOP);
|
||||
if (wlr_box_contains_point(&box, lx, ly))
|
||||
return LAB_DECO_PART_TOP;
|
||||
return LAB_DECO_NONE;
|
||||
}
|
||||
|
||||
13
labwc.h
13
labwc.h
|
|
@ -33,7 +33,6 @@
|
|||
#define XWL_TITLEBAR_HEIGHT (10)
|
||||
#define XWL_WINDOW_BORDER (3)
|
||||
|
||||
/* For brevity's sake, struct members are annotated where they are used. */
|
||||
enum cursor_mode {
|
||||
TINYWL_CURSOR_PASSTHROUGH,
|
||||
TINYWL_CURSOR_MOVE,
|
||||
|
|
@ -84,6 +83,11 @@ struct output {
|
|||
|
||||
enum view_type { LAB_XDG_SHELL_VIEW, LAB_XWAYLAND_VIEW };
|
||||
|
||||
enum deco_part {
|
||||
LAB_DECO_NONE,
|
||||
LAB_DECO_PART_TOP
|
||||
};
|
||||
|
||||
struct view {
|
||||
enum view_type type;
|
||||
struct wl_list link;
|
||||
|
|
@ -131,6 +135,7 @@ void xwl_surface_destroy(struct wl_listener *listener, void *data);
|
|||
void xwl_surface_configure(struct wl_listener *listener, void *data);
|
||||
void xwl_surface_new(struct wl_listener *listener, void *data);
|
||||
|
||||
bool view_want_deco(struct view *view);
|
||||
void view_focus_last_toplevel(struct server *server);
|
||||
void focus_view(struct view *view, struct wlr_surface *surface);
|
||||
void view_focus_next_toplevel(struct server *server);
|
||||
|
|
@ -139,7 +144,7 @@ void begin_interactive(struct view *view, enum cursor_mode mode,
|
|||
bool is_toplevel(struct view *view);
|
||||
struct view *desktop_view_at(struct server *server, double lx, double ly,
|
||||
struct wlr_surface **surface, double *sx,
|
||||
double *sy);
|
||||
double *sy, int *view_area);
|
||||
|
||||
/* TODO: try to refactor to remove from header file */
|
||||
struct view *first_toplevel(struct server *server);
|
||||
|
|
@ -157,4 +162,8 @@ void output_frame(struct wl_listener *listener, void *data);
|
|||
|
||||
void dbg_show_views(struct server *server);
|
||||
|
||||
struct wlr_box deco_max_extents(struct view *view);
|
||||
struct wlr_box deco_box(struct view *view, enum deco_part deco_part);
|
||||
enum deco_part deco_at(struct view *view, double lx, double ly);
|
||||
|
||||
#endif /* LABWC_H */
|
||||
|
|
|
|||
29
output.c
29
output.c
|
|
@ -1,9 +1,5 @@
|
|||
#include "labwc.h"
|
||||
|
||||
/*
|
||||
* Used to move all of the data necessary to render a surface from the
|
||||
* top-level frame handler to the per-surface render function.
|
||||
*/
|
||||
struct render_data {
|
||||
struct wlr_output *output;
|
||||
struct wlr_renderer *renderer;
|
||||
|
|
@ -13,32 +9,19 @@ struct render_data {
|
|||
|
||||
static void render_decorations(struct wlr_output *output, struct view *view)
|
||||
{
|
||||
if (!view->surface)
|
||||
return;
|
||||
if (view->type != LAB_XWAYLAND_VIEW)
|
||||
return;
|
||||
if (!is_toplevel(view))
|
||||
return;
|
||||
if (view->xwayland_surface->override_redirect)
|
||||
return;
|
||||
if (view->xwayland_surface->decorations !=
|
||||
WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
|
||||
if (!view_want_deco(view))
|
||||
return;
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = view->x - XWL_WINDOW_BORDER,
|
||||
.y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER,
|
||||
.width = view->surface->current.width + 2 * XWL_WINDOW_BORDER,
|
||||
.height = view->surface->current.height + XWL_TITLEBAR_HEIGHT +
|
||||
2 * XWL_WINDOW_BORDER,
|
||||
};
|
||||
|
||||
struct wlr_box box = deco_max_extents(view);
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
|
||||
output->transform_matrix);
|
||||
|
||||
float color[] = { 0.2, 0.2, 0.7, 0.9 };
|
||||
wlr_render_quad_with_matrix(view->server->renderer, color, matrix);
|
||||
|
||||
box = deco_box(view, LAB_DECO_PART_TOP);
|
||||
float color2[] = { 0.7, 0.2, 0.2, 0.9 };
|
||||
wlr_render_rect(view->server->renderer, &box, color2, output->transform_matrix);
|
||||
}
|
||||
|
||||
static void render_surface(struct wlr_surface *surface, int sx, int sy,
|
||||
|
|
|
|||
17
server.c
17
server.c
|
|
@ -252,9 +252,10 @@ static void process_cursor_motion(struct server *server, uint32_t time)
|
|||
double sx, sy;
|
||||
struct wlr_seat *seat = server->seat;
|
||||
struct wlr_surface *surface = NULL;
|
||||
int view_area;
|
||||
struct view *view = desktop_view_at(server, server->cursor->x,
|
||||
server->cursor->y, &surface, &sx,
|
||||
&sy);
|
||||
&sy, &view_area);
|
||||
if (!view) {
|
||||
/* If there's no view under the cursor, set the cursor image to
|
||||
* a default. This is what makes the cursor image appear when
|
||||
|
|
@ -262,6 +263,12 @@ static void process_cursor_motion(struct server *server, uint32_t time)
|
|||
wlr_xcursor_manager_set_cursor_image(
|
||||
server->cursor_mgr, "left_ptr", server->cursor);
|
||||
}
|
||||
switch (view_area) {
|
||||
case LAB_DECO_PART_TOP:
|
||||
wlr_xcursor_manager_set_cursor_image(
|
||||
server->cursor_mgr, "left_ptr", server->cursor);
|
||||
break;
|
||||
}
|
||||
if (surface) {
|
||||
bool focus_changed = seat->pointer_state.focused_surface !=
|
||||
surface;
|
||||
|
|
@ -332,9 +339,10 @@ void server_cursor_button(struct wl_listener *listener, void *data)
|
|||
event->button, event->state);
|
||||
double sx, sy;
|
||||
struct wlr_surface *surface;
|
||||
int view_area;
|
||||
struct view *view = desktop_view_at(server, server->cursor->x,
|
||||
server->cursor->y, &surface, &sx,
|
||||
&sy);
|
||||
&sy, &view_area);
|
||||
if (event->state == WLR_BUTTON_RELEASED) {
|
||||
/* If you released any buttons, we exit interactive move/resize
|
||||
* mode. */
|
||||
|
|
@ -342,6 +350,11 @@ void server_cursor_button(struct wl_listener *listener, void *data)
|
|||
} else {
|
||||
/* Focus that client if the button was _pressed_ */
|
||||
focus_view(view, surface);
|
||||
switch (view_area) {
|
||||
case LAB_DECO_PART_TOP:
|
||||
begin_interactive(view, TINYWL_CURSOR_MOVE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
44
view.c
44
view.c
|
|
@ -1,5 +1,21 @@
|
|||
#include "labwc.h"
|
||||
|
||||
bool view_want_deco(struct view *view)
|
||||
{
|
||||
if (!view->surface)
|
||||
return false;
|
||||
if (view->type != LAB_XWAYLAND_VIEW)
|
||||
return false;
|
||||
if (!is_toplevel(view))
|
||||
return false;
|
||||
if (view->xwayland_surface->override_redirect)
|
||||
return false;
|
||||
if (view->xwayland_surface->decorations !=
|
||||
WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct view *last_toplevel(struct server *server)
|
||||
{
|
||||
struct view *view;
|
||||
|
|
@ -127,10 +143,6 @@ void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges)
|
|||
struct server *server = view->server;
|
||||
struct wlr_surface *focused_surface =
|
||||
server->seat->pointer_state.focused_surface;
|
||||
if (view->surface != focused_surface) {
|
||||
/* Deny move/resize requests from unfocused clients. */
|
||||
return;
|
||||
}
|
||||
server->grabbed_view = view;
|
||||
server->cursor_mode = mode;
|
||||
|
||||
|
|
@ -216,7 +228,7 @@ static bool view_at(struct view *view, double lx, double ly,
|
|||
break;
|
||||
}
|
||||
|
||||
if (_surface != NULL) {
|
||||
if (_surface) {
|
||||
*sx = _sx;
|
||||
*sy = _sy;
|
||||
*surface = _surface;
|
||||
|
|
@ -227,16 +239,28 @@ static bool view_at(struct view *view, double lx, double ly,
|
|||
|
||||
struct view *desktop_view_at(struct server *server, double lx, double ly,
|
||||
struct wlr_surface **surface, double *sx,
|
||||
double *sy)
|
||||
double *sy, int *view_area)
|
||||
{
|
||||
/* This iterates over all of our surfaces and attempts to find one under
|
||||
* the cursor. This relies on server->views being ordered from
|
||||
* top-to-bottom. */
|
||||
/*
|
||||
* This iterates over all of our surfaces and attempts to find one under
|
||||
* the cursor. It relies on server->views being ordered from
|
||||
* top-to-bottom.
|
||||
*/
|
||||
struct wlr_box border_box = {
|
||||
.x = 0, .y = 0,
|
||||
.width = 0, .height = 0,
|
||||
};
|
||||
struct view *view;
|
||||
wl_list_for_each (view, &server->views, link) {
|
||||
if (view_at(view, lx, ly, surface, sx, sy)) {
|
||||
if (view_at(view, lx, ly, surface, sx, sy))
|
||||
return view;
|
||||
if (!view_want_deco(view))
|
||||
continue;
|
||||
if (deco_at(view, lx, ly) == LAB_DECO_PART_TOP) {
|
||||
*view_area = LAB_DECO_PART_TOP;
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue