Require wlroots 0.17.0

This commit is contained in:
Keith Bowes 2023-11-22 10:06:39 -05:00
parent 7fb889d171
commit bceafa5b6b
18 changed files with 305 additions and 400 deletions

View file

@ -17,8 +17,8 @@ jobs:
- name: packages - name: packages
run: | run: |
apk add clang gcc libevdev-dev libinput-dev libxkbcommon-dev libxml2-dev meson musl-dev wayland-dev wayland-protocols wlroots-dev xwayland apk add clang gcc libevdev-dev libinput-dev libxkbcommon-dev libxml2-dev meson musl-dev wayland-dev wayland-protocols wlroots-dev xwayland
# actions/checkout@v3 clones the repository # actions/checkout@v4 clones the repository
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: build-gcc - name: build-gcc
run: | run: |
CC=gcc meson setup build-gcc CC=gcc meson setup build-gcc

View file

@ -1,7 +1,6 @@
#ifndef _WB_OUTPUT_H #ifndef _WB_OUTPUT_H
#define _WB_OUTPUT_H #define _WB_OUTPUT_H
#include <stdlib.h>
#include <time.h> #include <time.h>
#include "waybox/server.h" #include "waybox/server.h"
@ -32,28 +31,6 @@ struct wb_output {
struct wl_list link; struct wl_list link;
}; };
struct wb_view {
struct wl_list link;
struct wb_server *server;
struct wlr_xdg_toplevel *xdg_toplevel;
struct wlr_scene_tree *scene_tree;
struct wlr_xdg_toplevel_decoration_v1 *decoration;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
struct wl_listener new_popup;
struct wl_listener request_fullscreen;
struct wl_listener request_maximize;
struct wl_listener request_minimize;
struct wl_listener request_move;
struct wl_listener request_resize;
struct wlr_box geometry;
struct wlr_box previous_geometry;
};
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data); void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data);
void output_frame_notify(struct wl_listener *listener, void *data); void output_frame_notify(struct wl_listener *listener, void *data);
void output_destroy_notify(struct wl_listener *listener, void *data); void output_destroy_notify(struct wl_listener *listener, void *data);

View file

@ -22,6 +22,8 @@
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <stdlib.h>
#ifdef USE_NLS #ifdef USE_NLS
# include <libintl.h> # include <libintl.h>
# include <locale.h> # include <locale.h>
@ -34,7 +36,7 @@
#include "waybox/cursor.h" #include "waybox/cursor.h"
#include "decoration.h" #include "decoration.h"
#include "layer_shell.h" #include "layer_shell.h"
#include "waybox/output.h" #include "waybox/xdg_shell.h"
#include "waybox/seat.h" #include "waybox/seat.h"
struct wb_server { struct wb_server {
@ -58,11 +60,11 @@ struct wb_server {
struct wb_cursor *cursor; struct wb_cursor *cursor;
struct wb_seat *seat; struct wb_seat *seat;
struct wb_view *grabbed_view; struct wb_toplevel *grabbed_toplevel;
struct wlr_box grab_geo_box; struct wlr_box grab_geo_box;
double grab_x, grab_y; double grab_x, grab_y;
uint32_t resize_edges; uint32_t resize_edges;
struct wl_list views; struct wl_list toplevels;
struct wlr_layer_shell_v1 *layer_shell; struct wlr_layer_shell_v1 *layer_shell;
struct wlr_xdg_shell *xdg_shell; struct wlr_xdg_shell *xdg_shell;

View file

@ -3,10 +3,32 @@
#include "waybox/server.h" #include "waybox/server.h"
struct wb_toplevel {
struct wl_list link;
struct wb_server *server;
struct wlr_xdg_toplevel *xdg_toplevel;
struct wlr_scene_tree *scene_tree;
struct wlr_xdg_toplevel_decoration_v1 *decoration;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
struct wl_listener new_popup;
struct wl_listener request_fullscreen;
struct wl_listener request_maximize;
struct wl_listener request_minimize;
struct wl_listener request_move;
struct wl_listener request_resize;
struct wlr_box geometry;
struct wlr_box previous_geometry;
};
void init_xdg_shell(struct wb_server *server); void init_xdg_shell(struct wb_server *server);
void focus_view(struct wb_view *view, struct wlr_surface *surface); void focus_toplevel(struct wb_toplevel *toplevel, struct wlr_surface *surface);
struct wlr_output *get_active_output(struct wb_view *view); struct wlr_output *get_active_output(struct wb_toplevel *toplevel);
struct wb_view *get_view_at( struct wb_toplevel *get_toplevel_at(
struct wb_server *server, double lx, double ly, struct wb_server *server, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy); struct wlr_surface **surface, double *sx, double *sy);
#endif #endif

View file

@ -28,7 +28,7 @@ inc_dir = include_directories('include')
libevdev = dependency('libevdev') libevdev = dependency('libevdev')
libinput = dependency('libinput', version: '>=1.21.0') libinput = dependency('libinput', version: '>=1.21.0')
libxml2 = dependency('libxml-2.0') libxml2 = dependency('libxml-2.0')
wlroots = dependency('wlroots', version: '>=0.16.0') wlroots = dependency('wlroots', version: '>=0.17.0')
wayland_server = dependency('wayland-server', version: '>=1.15') wayland_server = dependency('wayland-server', version: '>=1.15')
wayland_protos = dependency('wayland-protocols', version: '>=1.27') wayland_protos = dependency('wayland-protocols', version: '>=1.27')
xkbcommon = dependency('xkbcommon') xkbcommon = dependency('xkbcommon')

View file

@ -11,8 +11,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Waybox 0.0.1\n" "Project-Id-Version: Waybox 0.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n" "Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n"
"POT-Creation-Date: 2022-12-06 22:27-0500\n" "POT-Creation-Date: 2023-11-21 15:47-0500\n"
"PO-Revision-Date: 2022-12-06 22:30-0500\n" "PO-Revision-Date: 2023-11-21 12:49-0500\n"
"Last-Translator: Volker Ribbert <volker.nospam@netcologne.de>\n" "Last-Translator: Volker Ribbert <volker.nospam@netcologne.de>\n"
"Language-Team: <de@li.org>\n" "Language-Team: <de@li.org>\n"
"Language: de\n" "Language: de\n"
@ -39,14 +39,14 @@ msgstr "Kein nodeset"
msgid "" msgid ""
"Unable to parse the configuration file. Consult stderr for more information." "Unable to parse the configuration file. Consult stderr for more information."
msgstr "" msgstr ""
"Kann nicht die Einstullungsdatei analisieren. Für mehr Informationen die " "Kann nicht die Einstellungsdatei analisieren. Für weitere Informationen die "
"Standardfehlerausgabe lesen." "Standardfehlerausgabe lesen."
msgid "Couldn't create new context!" msgid "Couldn't create new context!"
msgstr "Konnte einen neuen Zusammenhang nicht erstellen" msgstr "Konnte keinen neuen Zusammenhang erstellen"
msgid "Couldn't register the namespace" msgid "Couldn't register the namespace"
msgstr "Konte dem Namensnraum nicht registrieren" msgstr "Konnte dem Namensraum nicht registrieren"
#, c-format #, c-format
msgid "Syntax: %s [options]\n" msgid "Syntax: %s [options]\n"
@ -118,8 +118,8 @@ msgstr "Der Server wurde nicht erfolgreich gestartet"
msgid "New output device detected" msgid "New output device detected"
msgstr "Neue Ausgabegerät entdeckt" msgstr "Neue Ausgabegerät entdeckt"
msgid "Couldn't commit pending frame to output" msgid "Could not add an output layout."
msgstr "Konnte sich nicht an den anstehenden Rahmen an die Ausgabe eintragen" msgstr "Konnte keine neue Ausgabenanordnung hinzufügen."
msgid "New keyboard detected" msgid "New keyboard detected"
msgstr "Neue Tastatur entdeckt" msgstr "Neue Tastatur entdeckt"
@ -151,8 +151,12 @@ msgstr "Display zerstört"
msgid "Keyboard focus is now on surface" msgid "Keyboard focus is now on surface"
msgstr "Tastaturfokus ist jetzt auf Oberfläche" msgstr "Tastaturfokus ist jetzt auf Oberfläche"
msgid "Focusing next view" msgid "Focusing next toplevel"
msgstr "Fokussiert nächste Ansicht" msgstr "Fokussiert nächstes Spitzenniveau"
#~ msgid "Couldn't commit pending frame to output"
#~ msgstr ""
#~ "Konnte sich nicht an den anstehenden Rahmen an die Ausgabe eintragen"
#, fuzzy #, fuzzy
#~ msgid "Failed to create wlr_backend" #~ msgid "Failed to create wlr_backend"

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Waybox 0.0.1\n" "Project-Id-Version: Waybox 0.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n" "Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n"
"POT-Creation-Date: 2022-12-06 22:27-0500\n" "POT-Creation-Date: 2023-11-21 15:47-0500\n"
"PO-Revision-Date: 2022-12-06 22:33-0500\n" "PO-Revision-Date: 2023-11-21 15:58-0500\n"
"Last-Translator: Keith <keith@localhost>\n" "Last-Translator: Keith <keith@localhost>\n"
"Language-Team: Esperanto\n" "Language-Team: Esperanto\n"
"Language: eo\n" "Language: eo\n"
@ -24,7 +24,7 @@ msgid "ERROR: No configuration file found."
msgstr "ERARO: Neniu agordo-dosiero trovita." msgstr "ERARO: Neniu agordo-dosiero trovita."
msgid "Unable to evaluate expression" msgid "Unable to evaluate expression"
msgstr "Ne povas taksi esprimon" msgstr "Ne eblis taksi esprimon"
msgid "No nodesetval" msgid "No nodesetval"
msgstr "Neniu nodara valoro" msgstr "Neniu nodara valoro"
@ -41,7 +41,7 @@ msgid "Couldn't create new context!"
msgstr "Ne povis krei novan kuntekston!" msgstr "Ne povis krei novan kuntekston!"
msgid "Couldn't register the namespace" msgid "Couldn't register the namespace"
msgstr "Ne povas registri lo nomspacon" msgstr "Ne eblis registri la nomspacon"
#, c-format #, c-format
msgid "Syntax: %s [options]\n" msgid "Syntax: %s [options]\n"
@ -98,13 +98,13 @@ msgstr "%s postulas argumenton\n"
#, c-format #, c-format
msgid "%s hasn't been implemented yet.\n" msgid "%s hasn't been implemented yet.\n"
msgstr "%s ankoraŭ ne estas efektigita.\n" msgstr "%s ankoraŭ ne estas efektivigita.\n"
msgid "Successfully created backend" msgid "Successfully created backend"
msgstr "Sukcese kreis servilan dorson" msgstr "Sukcese kreis servilan dorson"
msgid "Failed to create backend" msgid "Failed to create backend"
msgstr "Malsukesis krei servilan dorson" msgstr "Malsukcesis krei servilan dorson"
msgid "Successfully started server" msgid "Successfully started server"
msgstr "Sukcese startigis servilon" msgstr "Sukcese startigis servilon"
@ -115,8 +115,8 @@ msgstr "Malsukcesis startigi servilon"
msgid "New output device detected" msgid "New output device detected"
msgstr "Nova enigilo malkovrita" msgstr "Nova enigilo malkovrita"
msgid "Couldn't commit pending frame to output" msgid "Could not add an output layout."
msgstr "Ne povis surmeti atendantan framon sur eligon" msgstr "Ne eblis aldoni eligan aranĝon."
msgid "New keyboard detected" msgid "New keyboard detected"
msgstr "Nova klavaro malkovrita" msgstr "Nova klavaro malkovrita"
@ -131,13 +131,13 @@ msgid "Failed to connect to a Wayland display"
msgstr "Malsukcesis konektiĝi al Wayland-ekrano" msgstr "Malsukcesis konektiĝi al Wayland-ekrano"
msgid "Failed to create renderer" msgid "Failed to create renderer"
msgstr "Malsukesis krei servilan bildigilon" msgstr "Malsukcesis krei servilan bildigilon"
msgid "Failed to create allocator" msgid "Failed to create allocator"
msgstr "Malsukesis krei servilan asignilon" msgstr "Malsukcesis krei servilan asignilon"
msgid "Failed to start backend" msgid "Failed to start backend"
msgstr "Malsukesis startigi servilan dorson" msgstr "Malsukcesis startigi servilan dorson"
msgid "Running Wayland compositor on Wayland display" msgid "Running Wayland compositor on Wayland display"
msgstr "Plenumas Wayland-komponilon sur Wayland-ekrano" msgstr "Plenumas Wayland-komponilon sur Wayland-ekrano"
@ -148,8 +148,11 @@ msgstr "Ekrano finigita"
msgid "Keyboard focus is now on surface" msgid "Keyboard focus is now on surface"
msgstr "Klavara fokuso nun estas sur surfaco" msgstr "Klavara fokuso nun estas sur surfaco"
msgid "Focusing next view" msgid "Focusing next toplevel"
msgstr "Fokusas la sekvan vidon" msgstr "Fokusas la sekvan supran nivelon"
#~ msgid "Couldn't commit pending frame to output"
#~ msgstr "Ne eblis surmeti atendantan framon sur eligon"
#, fuzzy #, fuzzy
#~ msgid "Failed to create wlr_backend" #~ msgid "Failed to create wlr_backend"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: waybox\n" "Project-Id-Version: waybox\n"
"Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n" "Report-Msgid-Bugs-To: https://github.com/wizbright/waybox/issues\n"
"POT-Creation-Date: 2022-12-06 22:27-0500\n" "POT-Creation-Date: 2023-11-21 15:47-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -107,7 +107,7 @@ msgstr ""
msgid "New output device detected" msgid "New output device detected"
msgstr "" msgstr ""
msgid "Couldn't commit pending frame to output" msgid "Could not add an output layout."
msgstr "" msgstr ""
msgid "New keyboard detected" msgid "New keyboard detected"
@ -140,5 +140,5 @@ msgstr ""
msgid "Keyboard focus is now on surface" msgid "Keyboard focus is now on surface"
msgstr "" msgstr ""
msgid "Focusing next view" msgid "Focusing next toplevel"
msgstr "" msgstr ""

View file

@ -29,14 +29,14 @@ protocols = [
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
'wlr-gamma-control-unstable-v1.xml', 'wlr-gamma-control-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
] ]
client_protocols = [ client_protocols = [
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
'wlr-screencopy-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
] ]
wl_protos_src = [] wl_protos_src = []

View file

@ -4,22 +4,22 @@
void reset_cursor_mode(struct wb_server *server) { void reset_cursor_mode(struct wb_server *server) {
/* Reset the cursor mode to passthrough */ /* Reset the cursor mode to passthrough */
server->cursor->cursor_mode = WB_CURSOR_PASSTHROUGH; server->cursor->cursor_mode = WB_CURSOR_PASSTHROUGH;
server->grabbed_view = NULL; server->grabbed_toplevel = NULL;
} }
static void process_cursor_move(struct wb_server *server) { static void process_cursor_move(struct wb_server *server) {
/* Move the grabbed view to the new position. */ /* Move the grabbed toplevel to the new position. */
struct wb_view *view = server->grabbed_view; struct wb_toplevel *toplevel = server->grabbed_toplevel;
if (view->scene_tree->node.type == WLR_SCENE_NODE_TREE) { if (toplevel->scene_tree->node.type == WLR_SCENE_NODE_TREE) {
view->geometry.x = server->cursor->cursor->x - server->grab_x; toplevel->geometry.x = server->cursor->cursor->x - server->grab_x;
view->geometry.y = server->cursor->cursor->y - server->grab_y; toplevel->geometry.y = server->cursor->cursor->y - server->grab_y;
wlr_scene_node_set_position(&view->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,
view->geometry.x, view->geometry.y); toplevel->geometry.x, toplevel->geometry.y);
} }
} }
static void process_cursor_resize(struct wb_server *server) { static void process_cursor_resize(struct wb_server *server) {
struct wb_view *view = server->grabbed_view; struct wb_toplevel *toplevel = server->grabbed_toplevel;
double border_x = server->cursor->cursor->x - server->grab_x; double border_x = server->cursor->cursor->x - server->grab_x;
double border_y = server->cursor->cursor->y - server->grab_y; double border_y = server->cursor->cursor->y - server->grab_y;
int new_left = server->grab_geo_box.x; int new_left = server->grab_geo_box.x;
@ -51,15 +51,15 @@ static void process_cursor_resize(struct wb_server *server) {
} }
struct wlr_box geo_box; struct wlr_box geo_box;
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box);
view->geometry.x = new_left - geo_box.x; toplevel->geometry.x = new_left - geo_box.x;
view->geometry.y = new_top - geo_box.y; toplevel->geometry.y = new_top - geo_box.y;
wlr_scene_node_set_position(&view->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,
view->geometry.x, view->geometry.y); toplevel->geometry.x, toplevel->geometry.y);
int new_width = new_right - new_left; int new_width = new_right - new_left;
int new_height = new_bottom - new_top; int new_height = new_bottom - new_top;
wlr_xdg_toplevel_set_size(view->xdg_toplevel, new_width, new_height); wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, new_width, new_height);
} }
static void process_cursor_motion(struct wb_server *server, uint32_t time) { static void process_cursor_motion(struct wb_server *server, uint32_t time) {
@ -72,23 +72,18 @@ static void process_cursor_motion(struct wb_server *server, uint32_t time) {
return; return;
} }
/* Otherwise, find the view under the pointer and send the event along. */ /* Otherwise, find the toplevel under the pointer and send the event along. */
double sx, sy; double sx, sy;
struct wlr_seat *seat = server->seat->seat; struct wlr_seat *seat = server->seat->seat;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct wb_view *view = get_view_at(server, struct wb_toplevel *toplevel = get_toplevel_at(server,
server->cursor->cursor->x, server->cursor->cursor->y, &surface, &sx, &sy); server->cursor->cursor->x, server->cursor->cursor->y, &surface, &sx, &sy);
if (!view) { if (!toplevel) {
/* If there's no view under the cursor, set the cursor image to a /* 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 * default. This is what makes the cursor image appear when you move it
* around the screen, not over any views. */ * around the screen, not over any toplevels. */
#if WLR_CHECK_VERSION(0, 17, 0)
wlr_cursor_set_xcursor( wlr_cursor_set_xcursor(
server->cursor->cursor, server->cursor->xcursor_manager, "default"); server->cursor->cursor, server->cursor->xcursor_manager, "default");
#else
wlr_xcursor_manager_set_cursor_image(
server->cursor->xcursor_manager, "left_ptr", server->cursor->cursor);
#endif
} }
if (surface) { if (surface) {
/* /*
@ -139,14 +134,14 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
event->time_msec, event->button, event->state); event->time_msec, event->button, event->state);
double sx, sy; double sx, sy;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct wb_view *view = get_view_at(cursor->server, struct wb_toplevel *toplevel = get_toplevel_at(cursor->server,
cursor->server->cursor->cursor->x, cursor->server->cursor->cursor->y, &surface, &sx, &sy); cursor->server->cursor->cursor->x, cursor->server->cursor->cursor->y, &surface, &sx, &sy);
if (event->state == WLR_BUTTON_RELEASED) { if (event->state == WLR_BUTTON_RELEASED) {
/* If you released any buttons, we exit interactive move/resize mode. */ /* If you released any buttons, we exit interactive move/resize mode. */
reset_cursor_mode(cursor->server); reset_cursor_mode(cursor->server);
} else { } else {
/* Focus that client if the button was _pressed_ */ /* Focus that client if the button was _pressed_ */
focus_view(view, surface); focus_toplevel(toplevel, surface);
} }
wlr_idle_notifier_v1_notify_activity(cursor->server->idle_notifier, cursor->server->seat->seat); wlr_idle_notifier_v1_notify_activity(cursor->server->idle_notifier, cursor->server->seat->seat);
@ -203,9 +198,6 @@ struct wb_cursor *wb_cursor_create(struct wb_server *server) {
const char *xcursor_size = getenv("XCURSOR_SIZE"); const char *xcursor_size = getenv("XCURSOR_SIZE");
cursor->xcursor_manager = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"), cursor->xcursor_manager = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"),
xcursor_size ? strtoul(xcursor_size, (char **) NULL, 10) : 24); xcursor_size ? strtoul(xcursor_size, (char **) NULL, 10) : 24);
#if !WLR_CHECK_VERSION(0, 17, 0)
wlr_xcursor_manager_load(cursor->xcursor_manager, 1);
#endif
cursor->cursor_motion.notify = handle_cursor_motion; cursor->cursor_motion.notify = handle_cursor_motion;
wl_signal_add(&cursor->cursor->events.motion, &cursor->cursor_motion); wl_signal_add(&cursor->cursor->events.motion, &cursor->cursor_motion);

View file

@ -15,9 +15,9 @@ static void free_xdg_decoration_mode(struct wl_listener *listener, void *data) {
static void handle_xdg_decoration_mode(struct wl_listener *listener, void *data) { static void handle_xdg_decoration_mode(struct wl_listener *listener, void *data) {
struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration = data; struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration = data;
struct wb_decoration *decoration = wl_container_of(listener, decoration, request_mode); struct wb_decoration *decoration = wl_container_of(listener, decoration, request_mode);
struct wb_view *view = wl_container_of(decoration->server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(decoration->server->toplevels.next, toplevel, link);
wlr_xdg_toplevel_decoration_v1_set_mode(toplevel_decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); wlr_xdg_toplevel_decoration_v1_set_mode(toplevel_decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
view->decoration = toplevel_decoration; toplevel->decoration = toplevel_decoration;
} }
static void handle_new_xdg_toplevel_decoration(struct wl_listener *listener, void *data) { static void handle_new_xdg_toplevel_decoration(struct wl_listener *listener, void *data) {

View file

@ -121,13 +121,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wlr_scene_node_reparent(&surface->scene->tree->node, output_layer); wlr_scene_node_reparent(&surface->scene->tree->node, output_layer);
} }
#if WLR_CHECK_VERSION(0, 17, 0)
if (committed || layer_surface->surface->mapped != surface->mapped) { if (committed || layer_surface->surface->mapped != surface->mapped) {
surface->mapped = layer_surface->surface->mapped; surface->mapped = layer_surface->surface->mapped;
#else
if (committed || layer_surface->mapped != surface->mapped) {
surface->mapped = layer_surface->mapped;
#endif
arrange_layers(surface->output); arrange_layers(surface->output);
struct timespec now; struct timespec now;
@ -175,9 +170,9 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
seat_set_focus_layer(seat, NULL); seat_set_focus_layer(seat, NULL);
} }
struct wb_view *view = wl_container_of(surface->server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(surface->server->toplevels.next, toplevel, link);
if (view && view->scene_tree && view->scene_tree->node.enabled) { if (toplevel && toplevel->scene_tree && toplevel->scene_tree->node.enabled) {
focus_view(view, view->xdg_toplevel->base->surface); focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
} }
} }
@ -310,9 +305,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
if (layer_surface->output == NULL) { if (layer_surface->output == NULL) {
struct wb_server *server = struct wb_server *server =
wl_container_of(listener, server, new_layer_surface); wl_container_of(listener, server, new_layer_surface);
struct wb_view *view = struct wb_toplevel *toplevel =
wl_container_of(server->views.next, view, link); wl_container_of(server->toplevels.next, toplevel, link);
layer_surface->output = get_active_output(view); layer_surface->output = get_active_output(toplevel);
} }
struct wb_output *output = layer_surface->output->data; struct wb_output *output = layer_surface->output->data;
@ -348,17 +343,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
wl_signal_add(&layer_surface->surface->events.commit, wl_signal_add(&layer_surface->surface->events.commit,
&surface->surface_commit); &surface->surface_commit);
surface->map.notify = handle_map; surface->map.notify = handle_map;
#if WLR_CHECK_VERSION(0, 17, 0)
wl_signal_add(&layer_surface->surface->events.map, &surface->map); wl_signal_add(&layer_surface->surface->events.map, &surface->map);
#else
wl_signal_add(&layer_surface->events.map, &surface->map);
#endif
surface->unmap.notify = handle_unmap; surface->unmap.notify = handle_unmap;
#if WLR_CHECK_VERSION(0, 17, 0)
wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap); wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap);
#else
wl_signal_add(&layer_surface->events.unmap, &surface->unmap);
#endif
surface->destroy.notify = handle_destroy; surface->destroy.notify = handle_destroy;
wl_signal_add(&layer_surface->events.destroy, &surface->destroy); wl_signal_add(&layer_surface->events.destroy, &surface->destroy);
surface->new_popup.notify = handle_new_popup; surface->new_popup.notify = handle_new_popup;
@ -373,11 +360,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
} }
void init_layer_shell(struct wb_server *server) { void init_layer_shell(struct wb_server *server) {
#if WLR_CHECK_VERSION(0, 17, 0)
server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, 4); server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, 4);
#else
server->layer_shell = wlr_layer_shell_v1_create(server->wl_display);
#endif
server->new_layer_surface.notify = handle_layer_shell_surface; server->new_layer_surface.notify = handle_layer_shell_surface;
wl_signal_add(&server->layer_shell->events.new_surface, wl_signal_add(&server->layer_shell->events.new_surface,
&server->new_layer_surface); &server->new_layer_surface);

View file

@ -2,7 +2,7 @@
#define _WB_LAYERS_H #define _WB_LAYERS_H
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
struct wb_server; #include "waybox/output.h"
struct wb_layer_surface { struct wb_layer_surface {
struct wb_output *output; struct wb_output *output;

View file

@ -28,8 +28,8 @@ void signal_handler(int sig) {
wl_display_terminate(server.wl_display); wl_display_terminate(server.wl_display);
break; break;
case SIGUSR1: case SIGUSR1:
/* Openbox uses SIGUSR1 to restart. I'm not sure of the /* Openbox uses SIGUSR1 to restart and SIGUSR2 to reconfigure.
* difference between restarting and reconfiguring. * What's the difference?
*/ */
case SIGUSR2: case SIGUSR2:
deinit_config(server.config); deinit_config(server.config);

View file

@ -18,28 +18,21 @@ void output_frame_notify(struct wl_listener *listener, void *data) {
if (output->gamma_lut_changed) { if (output->gamma_lut_changed) {
output->gamma_lut_changed = false; output->gamma_lut_changed = false;
#if WLR_CHECK_VERSION(0, 17, 0)
struct wlr_gamma_control_v1 *gamma_control = struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control(output->server->gamma_control_manager, wlr_gamma_control_manager_v1_get_control(output->server->gamma_control_manager,
output->wlr_output); output->wlr_output);
if (!wlr_gamma_control_v1_apply(gamma_control, &output->wlr_output->pending)) { if (!wlr_gamma_control_v1_apply(gamma_control, &output->wlr_output->pending)) {
return; return;
} }
#endif
if (!wlr_output_test(output->wlr_output)) { if (!wlr_output_test(output->wlr_output)) {
wlr_output_rollback(output->wlr_output); wlr_output_rollback(output->wlr_output);
#if WLR_CHECK_VERSION(0, 17, 0)
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
#endif
} }
} }
/* Render the scene if needed and commit the output */ /* Render the scene if needed and commit the output */
#if WLR_CHECK_VERSION(0, 17, 0)
wlr_scene_output_commit(scene_output, NULL); wlr_scene_output_commit(scene_output, NULL);
#else
wlr_scene_output_commit(scene_output);
#endif
/* This lets the client know that we've displayed that frame and it can /* This lets the client know that we've displayed that frame and it can
* prepare another one now if it likes. */ * prepare another one now if it likes. */
@ -48,7 +41,6 @@ void output_frame_notify(struct wl_listener *listener, void *data) {
wlr_scene_output_send_frame_done(scene_output, &now); wlr_scene_output_send_frame_done(scene_output, &now);
} }
#if WLR_CHECK_VERSION(0, 17, 0)
void output_request_state_notify(struct wl_listener *listener, void *data) { void output_request_state_notify(struct wl_listener *listener, void *data) {
struct wb_output *output = wl_container_of(listener, output, request_state); struct wb_output *output = wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data; const struct wlr_output_event_request_state *event = data;
@ -61,16 +53,13 @@ void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
output->gamma_lut_changed = true; output->gamma_lut_changed = true;
wlr_output_schedule_frame(output->wlr_output); wlr_output_schedule_frame(output->wlr_output);
} }
#endif
void output_destroy_notify(struct wl_listener *listener, void *data) { void output_destroy_notify(struct wl_listener *listener, void *data) {
struct wb_output *output = wl_container_of(listener, output, destroy); struct wb_output *output = wl_container_of(listener, output, destroy);
wl_list_remove(&output->destroy.link); wl_list_remove(&output->destroy.link);
wl_list_remove(&output->frame.link); wl_list_remove(&output->frame.link);
#if WLR_CHECK_VERSION(0, 17, 0)
wl_list_remove(&output->request_state.link); wl_list_remove(&output->request_state.link);
#endif
/* Frees the layers */ /* Frees the layers */
size_t num_layers = sizeof(output->layers) / sizeof(struct wlr_scene_node *); size_t num_layers = sizeof(output->layers) / sizeof(struct wlr_scene_node *);
@ -95,7 +84,6 @@ void new_output_notify(struct wl_listener *listener, void *data) {
* and our renderer */ * and our renderer */
wlr_output_init_render(wlr_output, server->allocator, server->renderer); wlr_output_init_render(wlr_output, server->allocator, server->renderer);
#if WLR_CHECK_VERSION(0, 17, 0)
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
struct wlr_output_state state; struct wlr_output_state state;
wlr_output_state_init(&state); wlr_output_state_init(&state);
@ -107,18 +95,6 @@ void new_output_notify(struct wl_listener *listener, void *data) {
wlr_output_commit_state(wlr_output, &state); wlr_output_commit_state(wlr_output, &state);
wlr_output_state_finish(&state); wlr_output_state_finish(&state);
#else
if (!wl_list_empty(&wlr_output->modes)) {
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
wlr_output_set_mode(wlr_output, mode);
wlr_output_enable(wlr_output, true);
if (!wlr_output_commit(wlr_output)) {
wlr_log_errno(WLR_ERROR, "%s", _("Couldn't commit pending frame to output"));
return;
}
}
#endif
struct wb_output *output = calloc(1, sizeof(struct wb_output)); struct wb_output *output = calloc(1, sizeof(struct wb_output));
output->server = server; output->server = server;
@ -145,10 +121,8 @@ void new_output_notify(struct wl_listener *listener, void *data) {
wl_signal_add(&wlr_output->events.destroy, &output->destroy); wl_signal_add(&wlr_output->events.destroy, &output->destroy);
output->frame.notify = output_frame_notify; output->frame.notify = output_frame_notify;
wl_signal_add(&wlr_output->events.frame, &output->frame); wl_signal_add(&wlr_output->events.frame, &output->frame);
#if WLR_CHECK_VERSION(0, 17, 0)
output->request_state.notify = output_request_state_notify; output->request_state.notify = output_request_state_notify;
wl_signal_add(&wlr_output->events.request_state, &output->request_state); wl_signal_add(&wlr_output->events.request_state, &output->request_state);
#endif
/* Adds this to the output layout. The add_auto function arranges outputs /* Adds this to the output layout. The add_auto function arranges outputs
* from left-to-right in the order they appear. A more sophisticated * from left-to-right in the order they appear. A more sophisticated
@ -159,7 +133,6 @@ void new_output_notify(struct wl_listener *listener, void *data) {
* display, which Wayland clients can see to find out information about the * display, which Wayland clients can see to find out information about the
* output (such as DPI, scale factor, manufacturer, etc). * output (such as DPI, scale factor, manufacturer, etc).
*/ */
#if WLR_CHECK_VERSION(0, 17, 0)
struct wlr_output_layout_output *l_output = struct wlr_output_layout_output *l_output =
wlr_output_layout_add_auto(server->output_layout, wlr_output); wlr_output_layout_add_auto(server->output_layout, wlr_output);
if (!l_output) { if (!l_output) {
@ -169,7 +142,4 @@ void new_output_notify(struct wl_listener *listener, void *data) {
struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output); struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output);
wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output); wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output);
#else
wlr_output_layout_add_auto(server->output_layout, wlr_output);
#endif
} }

View file

@ -8,45 +8,45 @@
#include "waybox/seat.h" #include "waybox/seat.h"
#include "waybox/xdg_shell.h" #include "waybox/xdg_shell.h"
static void deiconify_view(struct wb_view *view) { static void deiconify_toplevel(struct wb_toplevel *toplevel) {
if (view->xdg_toplevel->requested.minimized) { if (toplevel->xdg_toplevel->requested.minimized) {
view->xdg_toplevel->requested.minimized = false; toplevel->xdg_toplevel->requested.minimized = false;
wl_signal_emit(&view->xdg_toplevel->events.request_minimize, NULL); wl_signal_emit(&toplevel->xdg_toplevel->events.request_minimize, NULL);
} }
} }
static void cycle_views(struct wb_server *server) { static void cycle_toplevels(struct wb_server *server) {
/* Cycle to the next view */ /* Cycle to the next toplevel */
if (wl_list_length(&server->views) < 1) { if (wl_list_length(&server->toplevels) < 1) {
return; return;
} }
struct wb_view *current_view = wl_container_of( struct wb_toplevel *current_toplevel = wl_container_of(
server->views.prev, current_view, link); server->toplevels.prev, current_toplevel, link);
deiconify_view(current_view); deiconify_toplevel(current_toplevel);
focus_view(current_view, current_view->xdg_toplevel->base->surface); focus_toplevel(current_toplevel, current_toplevel->xdg_toplevel->base->surface);
/* Move the current view to the beginning of the list */ /* Move the current toplevel to the beginning of the list */
wl_list_remove(&current_view->link); wl_list_remove(&current_toplevel->link);
wl_list_insert(&server->views, &current_view->link); wl_list_insert(&server->toplevels, &current_toplevel->link);
} }
static void cycle_views_reverse(struct wb_server *server) { static void cycle_toplevels_reverse(struct wb_server *server) {
/* Cycle to the previous view */ /* Cycle to the previous toplevel */
if (wl_list_length(&server->views) < 1) { if (wl_list_length(&server->toplevels) < 1) {
return; return;
} }
struct wb_view *current_view = wl_container_of( struct wb_toplevel *current_toplevel = wl_container_of(
server->views.next, current_view, link); server->toplevels.next, current_toplevel, link);
struct wb_view *next_view = wl_container_of( struct wb_toplevel *next_toplevel = wl_container_of(
current_view->link.next, next_view, link); current_toplevel->link.next, next_toplevel, link);
deiconify_view(next_view); deiconify_toplevel(next_toplevel);
focus_view(next_view, next_view->xdg_toplevel->base->surface); focus_toplevel(next_toplevel, next_toplevel->xdg_toplevel->base->surface);
/* Move the current view to after the previous view in the list */ /* Move the current toplevel to after the previous toplevel in the list */
wl_list_remove(&current_view->link); wl_list_remove(&current_toplevel->link);
wl_list_insert(server->views.prev, &current_view->link); wl_list_insert(server->toplevels.prev, &current_toplevel->link);
} }
static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32_t modifiers) { static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32_t modifiers) {
@ -62,10 +62,10 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32
/* Some default key bindings, when the rc.xml file can't be /* Some default key bindings, when the rc.xml file can't be
* parsed. */ * parsed. */
if (modifiers & WLR_MODIFIER_ALT && sym == XKB_KEY_Tab) if (modifiers & WLR_MODIFIER_ALT && sym == XKB_KEY_Tab)
cycle_views(server); cycle_toplevels(server);
else if (modifiers & (WLR_MODIFIER_ALT|WLR_MODIFIER_SHIFT) && else if (modifiers & (WLR_MODIFIER_ALT|WLR_MODIFIER_SHIFT) &&
sym == XKB_KEY_Tab) sym == XKB_KEY_Tab)
cycle_views_reverse(server); cycle_toplevels_reverse(server);
else if (sym == XKB_KEY_Escape && modifiers & WLR_MODIFIER_CTRL) else if (sym == XKB_KEY_Escape && modifiers & WLR_MODIFIER_CTRL)
wl_display_terminate(server->wl_display); wl_display_terminate(server->wl_display);
else else
@ -77,14 +77,14 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32
wl_list_for_each(key_binding, &server->config->key_bindings, link) { wl_list_for_each(key_binding, &server->config->key_bindings, link) {
if (sym == key_binding->sym && modifiers == key_binding->modifiers) { if (sym == key_binding->sym && modifiers == key_binding->modifiers) {
if (key_binding->action & ACTION_NEXT_WINDOW) if (key_binding->action & ACTION_NEXT_WINDOW)
cycle_views(server); cycle_toplevels(server);
if (key_binding->action & ACTION_PREVIOUS_WINDOW) if (key_binding->action & ACTION_PREVIOUS_WINDOW)
cycle_views_reverse(server); cycle_toplevels_reverse(server);
if (key_binding->action & ACTION_CLOSE) { if (key_binding->action & ACTION_CLOSE) {
struct wb_view *current_view = wl_container_of( struct wb_toplevel *current_toplevel = wl_container_of(
server->views.next, current_view, link); server->toplevels.next, current_toplevel, link);
if (current_view->scene_tree->node.enabled) if (current_toplevel->scene_tree->node.enabled)
wlr_xdg_toplevel_send_close(current_view->xdg_toplevel); wlr_xdg_toplevel_send_close(current_toplevel->xdg_toplevel);
} }
if (key_binding->action & ACTION_EXECUTE) { if (key_binding->action & ACTION_EXECUTE) {
if (fork() == 0) { if (fork() == 0) {
@ -92,34 +92,34 @@ static bool handle_keybinding(struct wb_server *server, xkb_keysym_t sym, uint32
} }
} }
if (key_binding->action & ACTION_TOGGLE_MAXIMIZE) { if (key_binding->action & ACTION_TOGGLE_MAXIMIZE) {
struct wb_view *view = wl_container_of(server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(server->toplevels.next, toplevel, link);
if (view->scene_tree->node.enabled) if (toplevel->scene_tree->node.enabled)
wl_signal_emit(&view->xdg_toplevel->events.request_maximize, NULL); wl_signal_emit(&toplevel->xdg_toplevel->events.request_maximize, NULL);
} }
if (key_binding->action & ACTION_ICONIFY) { if (key_binding->action & ACTION_ICONIFY) {
struct wb_view *view = wl_container_of(server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(server->toplevels.next, toplevel, link);
if (view->scene_tree->node.enabled) { if (toplevel->scene_tree->node.enabled) {
view->xdg_toplevel->requested.minimized = true; toplevel->xdg_toplevel->requested.minimized = true;
wl_signal_emit(&view->xdg_toplevel->events.request_minimize, NULL); wl_signal_emit(&toplevel->xdg_toplevel->events.request_minimize, NULL);
} }
} }
if (key_binding->action & ACTION_SHADE) { if (key_binding->action & ACTION_SHADE) {
struct wb_view *view = wl_container_of(server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(server->toplevels.next, toplevel, link);
if (view->scene_tree->node.enabled) { if (toplevel->scene_tree->node.enabled) {
struct wlr_box geo_box; struct wlr_box geo_box;
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box);
int decoration_height = MAX(geo_box.y - view->geometry.y, TITLEBAR_HEIGHT); int decoration_height = MAX(geo_box.y - toplevel->geometry.y, TITLEBAR_HEIGHT);
view->previous_geometry = view->geometry; toplevel->previous_geometry = toplevel->geometry;
wlr_xdg_toplevel_set_size(view->xdg_toplevel, wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel,
view->geometry.width, decoration_height); toplevel->geometry.width, decoration_height);
} }
} }
if (key_binding->action & ACTION_UNSHADE) { if (key_binding->action & ACTION_UNSHADE) {
struct wb_view *view = wl_container_of(server->views.next, view, link); struct wb_toplevel *toplevel = wl_container_of(server->toplevels.next, toplevel, link);
if (view->scene_tree->node.enabled) { if (toplevel->scene_tree->node.enabled) {
wlr_xdg_toplevel_set_size(view->xdg_toplevel, wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel,
view->previous_geometry.width, view->previous_geometry.height); toplevel->previous_geometry.width, toplevel->previous_geometry.height);
} }
} }
if (key_binding->action & ACTION_RECONFIGURE) { if (key_binding->action & ACTION_RECONFIGURE) {

View file

@ -14,11 +14,7 @@ bool wb_create_backend(struct wb_server* server) {
* output hardware. The autocreate option will choose the most suitable * output hardware. The autocreate option will choose the most suitable
* backend based on the current environment, such as opening an X11 window * backend based on the current environment, such as opening an X11 window
* if an X11 server is running. */ * if an X11 server is running. */
#if ! WLR_CHECK_VERSION(0, 13, 0) || WLR_CHECK_VERSION(0, 17, 0)
server->backend = wlr_backend_autocreate(server->wl_display, NULL); server->backend = wlr_backend_autocreate(server->wl_display, NULL);
#else
server->backend = wlr_backend_autocreate(server->wl_display);
#endif
if (server->backend == NULL) { if (server->backend == NULL) {
wlr_log(WLR_ERROR, "%s", _("Failed to create backend")); wlr_log(WLR_ERROR, "%s", _("Failed to create backend"));
return false; return false;
@ -46,13 +42,8 @@ bool wb_create_backend(struct wb_server* server) {
return false; return false;
} }
#if WLR_CHECK_VERSION(0, 17, 0)
server->compositor = server->compositor =
wlr_compositor_create(server->wl_display, 5, server->renderer); wlr_compositor_create(server->wl_display, 5, server->renderer);
#else
server->compositor = wlr_compositor_create(server->wl_display,
server->renderer);
#endif
server->subcompositor = wlr_subcompositor_create(server->wl_display); server->subcompositor = wlr_subcompositor_create(server->wl_display);
server->output_layout = wlr_output_layout_create(); server->output_layout = wlr_output_layout_create();
server->seat = wb_seat_create(server); server->seat = wb_seat_create(server);
@ -78,9 +69,7 @@ bool wb_start_server(struct wb_server* server) {
* necessary. * necessary.
*/ */
server->scene = wlr_scene_create(); server->scene = wlr_scene_create();
#if WLR_CHECK_VERSION(0, 17, 0)
server->scene_layout = server->scene_layout =
#endif
wlr_scene_attach_output_layout(server->scene, server->output_layout); wlr_scene_attach_output_layout(server->scene, server->output_layout);
const char *socket = wl_display_add_socket_auto(server->wl_display); const char *socket = wl_display_add_socket_auto(server->wl_display);
@ -103,22 +92,18 @@ bool wb_start_server(struct wb_server* server) {
server->gamma_control_manager = server->gamma_control_manager =
wlr_gamma_control_manager_v1_create(server->wl_display); wlr_gamma_control_manager_v1_create(server->wl_display);
#if WLR_CHECK_VERSION(0, 17, 0)
server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma; server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
wl_signal_add(&server->gamma_control_manager->events.set_gamma, &server->gamma_control_set_gamma); wl_signal_add(&server->gamma_control_manager->events.set_gamma, &server->gamma_control_set_gamma);
#endif
wlr_screencopy_manager_v1_create(server->wl_display); wlr_screencopy_manager_v1_create(server->wl_display);
server->idle_notifier = wlr_idle_notifier_v1_create(server->wl_display); server->idle_notifier = wlr_idle_notifier_v1_create(server->wl_display);
wl_list_init(&server->views); wl_list_init(&server->toplevels);
init_xdg_decoration(server); init_xdg_decoration(server);
init_layer_shell(server); init_layer_shell(server);
/* Set up the xdg-shell. The xdg-shell is a Wayland protocol which is used /* Set up the xdg-shell. The xdg-shell is a Wayland protocol which is used
* for application windows. For more detail on shells, refer to Drew * for application windows. For more detail on shells, refer to
* DeVault's article:
*
* https://drewdevault.com/2018/07/29/Wayland-shells.html * https://drewdevault.com/2018/07/29/Wayland-shells.html
*/ */
init_xdg_shell(server); init_xdg_shell(server);

View file

@ -1,11 +1,11 @@
#include "waybox/xdg_shell.h" #include "waybox/xdg_shell.h"
struct wb_view *get_view_at( struct wb_toplevel *get_toplevel_at(
struct wb_server *server, double lx, double ly, struct wb_server *server, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) { struct wlr_surface **surface, double *sx, double *sy) {
/* This returns the topmost node in the scene at the given layout coords. /* 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 * we only care about surface nodes as we are specifically looking for a
* surface in the surface tree of a wb_view. */ * surface in the surface tree of a wb_toplevel. */
struct wlr_scene_node *node = struct wlr_scene_node *node =
wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy); wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy);
if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) { if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) {
@ -13,17 +13,13 @@ struct wb_view *get_view_at(
} }
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
struct wlr_scene_surface *scene_surface = struct wlr_scene_surface *scene_surface =
#if WLR_CHECK_VERSION(0, 17, 0)
wlr_scene_surface_try_from_buffer(scene_buffer); wlr_scene_surface_try_from_buffer(scene_buffer);
#else
wlr_scene_surface_from_buffer(scene_buffer);
#endif
if (!scene_surface) { if (!scene_surface) {
return NULL; return NULL;
} }
*surface = scene_surface->surface; *surface = scene_surface->surface;
/* Find the node corresponding to the wb_view at the root of this /* Find the node corresponding to the wb_toplevel at the root of this
* surface tree, it is the only one for which we set the data field. */ * surface tree, it is the only one for which we set the data field. */
struct wlr_scene_tree *tree = node->parent; struct wlr_scene_tree *tree = node->parent;
while (tree != NULL && tree->node.data == NULL) { while (tree != NULL && tree->node.data == NULL) {
@ -32,25 +28,18 @@ struct wb_view *get_view_at(
return tree->node.data; return tree->node.data;
} }
void focus_view(struct wb_view *view, struct wlr_surface *surface) { void focus_toplevel(struct wb_toplevel *toplevel, struct wlr_surface *surface) {
/* Note: this function only deals with keyboard focus. */ /* Note: this function only deals with keyboard focus. */
if (view == NULL) { if (toplevel == NULL) {
return; return;
} }
#if WLR_CHECK_VERSION(0, 17, 0)
struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface); struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface);
#else
if (surface == NULL || !wlr_surface_is_xdg_surface(surface))
return;
struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(surface);
#endif
if (xdg_surface) if (xdg_surface)
wlr_log(WLR_INFO, "%s: %s", _("Keyboard focus is now on surface"), wlr_log(WLR_INFO, "%s: %s", _("Keyboard focus is now on surface"),
xdg_surface->toplevel->app_id); xdg_surface->toplevel->app_id);
struct wb_server *server = view->server; struct wb_server *server = toplevel->server;
struct wlr_seat *seat = server->seat->seat; struct wlr_seat *seat = server->seat->seat;
struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface; struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
if (prev_surface == surface) { if (prev_surface == surface) {
@ -63,48 +52,40 @@ void focus_view(struct wb_view *view, struct wlr_surface *surface) {
* it no longer has focus and the client will repaint accordingly, e.g. * it no longer has focus and the client will repaint accordingly, e.g.
* stop displaying a caret. * stop displaying a caret.
*/ */
#if WLR_CHECK_VERSION(0, 17, 0) struct wlr_xdg_toplevel *prev_toplevel =
struct wlr_xdg_surface *previous = wlr_xdg_toplevel_try_from_wlr_surface(prev_surface);
wlr_xdg_surface_try_from_wlr_surface(prev_surface); if (prev_toplevel != NULL) {
#else wlr_xdg_toplevel_set_activated(prev_toplevel, false);
struct wlr_xdg_surface *previous = NULL;
if (wlr_surface_is_xdg_surface(prev_surface)) {
previous = wlr_xdg_surface_from_wlr_surface(prev_surface);
}
#endif
if (previous != NULL && previous->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL &&
previous->toplevel != NULL) {
wlr_xdg_toplevel_set_activated(previous->toplevel, false);
} }
} }
/* Move the view to the front */ /* Move the toplevel to the front */
if (!server->seat->focused_layer) { if (!server->seat->focused_layer) {
wlr_scene_node_raise_to_top(&view->scene_tree->node); wlr_scene_node_raise_to_top(&toplevel->scene_tree->node);
} }
wl_list_remove(&view->link); wl_list_remove(&toplevel->link);
wl_list_insert(&server->views, &view->link); wl_list_insert(&server->toplevels, &toplevel->link);
/* Activate the new surface */ /* Activate the new surface */
wlr_xdg_toplevel_set_activated(view->xdg_toplevel, true); wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true);
/* /*
* Tell the seat to have the keyboard enter this surface. wlroots will keep * Tell the seat to have the keyboard enter this surface. wlroots will keep
* track of this and automatically send key events to the appropriate * track of this and automatically send key events to the appropriate
* clients without additional work on your part. * clients without additional work on your part.
*/ */
seat_focus_surface(server->seat, view->xdg_toplevel->base->surface); seat_focus_surface(server->seat, toplevel->xdg_toplevel->base->surface);
} }
struct wlr_output *get_active_output(struct wb_view *view) { struct wlr_output *get_active_output(struct wb_toplevel *toplevel) {
double closest_x, closest_y; double closest_x, closest_y;
struct wlr_output *output = NULL; struct wlr_output *output = NULL;
wlr_output_layout_closest_point(view->server->output_layout, output, wlr_output_layout_closest_point(toplevel->server->output_layout, output,
view->geometry.x + view->geometry.width / 2, toplevel->geometry.x + toplevel->geometry.width / 2,
view->geometry.y + view->geometry.height / 2, toplevel->geometry.y + toplevel->geometry.height / 2,
&closest_x, &closest_y); &closest_x, &closest_y);
return wlr_output_layout_output_at(view->server->output_layout, closest_x, closest_y); return wlr_output_layout_output_at(toplevel->server->output_layout, closest_x, closest_y);
} }
static struct wlr_box get_usable_area(struct wb_view *view) { static struct wlr_box get_usable_area(struct wb_toplevel *toplevel) {
struct wlr_output *output = get_active_output(view); struct wlr_output *output = get_active_output(toplevel);
struct wlr_box usable_area = {0}; struct wlr_box usable_area = {0};
wlr_output_effective_resolution(output, &usable_area.width, &usable_area.height); wlr_output_effective_resolution(output, &usable_area.width, &usable_area.height);
return usable_area; return usable_area;
@ -112,79 +93,79 @@ static struct wlr_box get_usable_area(struct wb_view *view) {
static void xdg_toplevel_map(struct wl_listener *listener, void *data) { static void xdg_toplevel_map(struct wl_listener *listener, void *data) {
/* Called when the surface is mapped, or ready to display on-screen. */ /* Called when the surface is mapped, or ready to display on-screen. */
struct wb_view *view = wl_container_of(listener, view, map); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, map);
if (view->xdg_toplevel->base->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) if (toplevel->xdg_toplevel->base->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; return;
struct wb_config *config = view->server->config; struct wb_config *config = toplevel->server->config;
struct wlr_box geo_box = {0}; struct wlr_box geo_box = {0};
struct wlr_box usable_area = get_usable_area(view); struct wlr_box usable_area = get_usable_area(toplevel);
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box);
if (config) { if (config) {
view->geometry.height = MIN(geo_box.height, toplevel->geometry.height = MIN(geo_box.height,
usable_area.height - config->margins.top - config->margins.bottom); usable_area.height - config->margins.top - config->margins.bottom);
view->geometry.width = MIN(geo_box.width, toplevel->geometry.width = MIN(geo_box.width,
usable_area.width - config->margins.left - config->margins.right); usable_area.width - config->margins.left - config->margins.right);
view->geometry.x = config->margins.left; toplevel->geometry.x = config->margins.left;
view->geometry.y = config->margins.top; toplevel->geometry.y = config->margins.top;
} else { } else {
view->geometry.height = MIN(geo_box.height, usable_area.height); toplevel->geometry.height = MIN(geo_box.height, usable_area.height);
view->geometry.width = MIN(geo_box.width, usable_area.width); toplevel->geometry.width = MIN(geo_box.width, usable_area.width);
view->geometry.x = 0; toplevel->geometry.x = 0;
view->geometry.y = 0; toplevel->geometry.y = 0;
} }
/* A view no larger than a title bar shouldn't be sized or focused */ /* A toplevel no larger than a title bar shouldn't be sized or focused */
if (view->geometry.height > TITLEBAR_HEIGHT && if (toplevel->geometry.height > TITLEBAR_HEIGHT &&
view->geometry.height > TITLEBAR_HEIGHT * toplevel->geometry.height > TITLEBAR_HEIGHT *
(usable_area.width / usable_area.height)) { (usable_area.width / usable_area.height)) {
wlr_xdg_toplevel_set_size(view->xdg_toplevel, wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel,
view->geometry.width, view->geometry.height); toplevel->geometry.width, toplevel->geometry.height);
focus_view(view, view->xdg_toplevel->base->surface); focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
} }
wlr_scene_node_set_position(&view->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,
view->geometry.x, view->geometry.y); toplevel->geometry.x, toplevel->geometry.y);
} }
static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) {
/* Called when the surface is unmapped, and should no longer be shown. */ /* Called when the surface is unmapped, and should no longer be shown. */
struct wb_view *view = wl_container_of(listener, view, unmap); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, unmap);
if (view->xdg_toplevel->base->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) if (toplevel->xdg_toplevel->base->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; return;
reset_cursor_mode(view->server); reset_cursor_mode(toplevel->server);
/* Focus the next view, if any. */ /* Focus the next toplevel, if any. */
if (wl_list_length(&view->link) > 1) { if (wl_list_length(&toplevel->link) > 1) {
struct wb_view *next_view = wl_container_of(view->link.next, next_view, link); struct wb_toplevel *next_toplevel = wl_container_of(toplevel->link.next, next_toplevel, link);
if (next_view && next_view->xdg_toplevel && next_view->scene_tree && next_view->scene_tree->node.enabled) { if (next_toplevel && next_toplevel->xdg_toplevel && next_toplevel->scene_tree && next_toplevel->scene_tree->node.enabled) {
wlr_log(WLR_INFO, "%s: %s", _("Focusing next view"), wlr_log(WLR_INFO, "%s: %s", _("Focusing next toplevel"),
next_view->xdg_toplevel->app_id); next_toplevel->xdg_toplevel->app_id);
focus_view(next_view, next_view->xdg_toplevel->base->surface); focus_toplevel(next_toplevel, next_toplevel->xdg_toplevel->base->surface);
} }
} }
} }
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
/* Called when the surface is destroyed and should never be shown again. */ /* Called when the xdg_toplevel is destroyed and should never be shown again. */
struct wb_view *view = wl_container_of(listener, view, destroy); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
wl_list_remove(&view->map.link); wl_list_remove(&toplevel->map.link);
wl_list_remove(&view->unmap.link); wl_list_remove(&toplevel->unmap.link);
wl_list_remove(&view->destroy.link); wl_list_remove(&toplevel->destroy.link);
wl_list_remove(&view->new_popup.link); wl_list_remove(&toplevel->new_popup.link);
if (view->xdg_toplevel->base->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { if (toplevel->xdg_toplevel->base->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wl_list_remove(&view->request_fullscreen.link); wl_list_remove(&toplevel->request_fullscreen.link);
wl_list_remove(&view->request_minimize.link); wl_list_remove(&toplevel->request_minimize.link);
wl_list_remove(&view->request_maximize.link); wl_list_remove(&toplevel->request_maximize.link);
wl_list_remove(&view->request_move.link); wl_list_remove(&toplevel->request_move.link);
wl_list_remove(&view->request_resize.link); wl_list_remove(&toplevel->request_resize.link);
wl_list_remove(&view->link); wl_list_remove(&toplevel->link);
} }
free(view); free(toplevel);
} }
static void xdg_toplevel_request_fullscreen( static void xdg_toplevel_request_fullscreen(
@ -194,9 +175,9 @@ static void xdg_toplevel_request_fullscreen(
* conform to xdg-shell protocol we still must send a configure. * conform to xdg-shell protocol we still must send a configure.
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. * wlr_xdg_surface_schedule_configure() is used to send an empty reply.
*/ */
struct wb_view *view = struct wb_toplevel *toplevel =
wl_container_of(listener, view, request_fullscreen); wl_container_of(listener, toplevel, request_fullscreen);
wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
} }
static void xdg_toplevel_request_maximize(struct wl_listener *listener, void *data) { static void xdg_toplevel_request_maximize(struct wl_listener *listener, void *data) {
@ -204,85 +185,85 @@ static void xdg_toplevel_request_maximize(struct wl_listener *listener, void *da
* typically because the user clicked on the maximize button on * typically because the user clicked on the maximize button on
* client-side decorations. * client-side decorations.
*/ */
struct wb_view *view = wl_container_of(listener, view, request_maximize); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize);
struct wlr_box usable_area = get_usable_area(view); struct wlr_box usable_area = get_usable_area(toplevel);
bool is_maximized = view->xdg_toplevel->current.maximized; bool is_maximized = toplevel->xdg_toplevel->current.maximized;
if (!is_maximized) { if (!is_maximized) {
struct wb_config *config = view->server->config; struct wb_config *config = toplevel->server->config;
view->previous_geometry = view->geometry; toplevel->previous_geometry = toplevel->geometry;
if (config) { if (config) {
view->geometry.x = config->margins.left; toplevel->geometry.x = config->margins.left;
view->geometry.y = config->margins.top; toplevel->geometry.y = config->margins.top;
usable_area.height -= config->margins.top + config->margins.bottom; usable_area.height -= config->margins.top + config->margins.bottom;
usable_area.width -= config->margins.left + config->margins.right; usable_area.width -= config->margins.left + config->margins.right;
} else { } else {
view->geometry.x = 0; toplevel->geometry.x = 0;
view->geometry.y = 0; toplevel->geometry.y = 0;
} }
} else { } else {
usable_area = view->previous_geometry; usable_area = toplevel->previous_geometry;
view->geometry.x = view->previous_geometry.x; toplevel->geometry.x = toplevel->previous_geometry.x;
view->geometry.y = view->previous_geometry.y; toplevel->geometry.y = toplevel->previous_geometry.y;
} }
wlr_xdg_toplevel_set_size(view->xdg_toplevel, usable_area.width, usable_area.height); wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, usable_area.width, usable_area.height);
wlr_xdg_toplevel_set_maximized(view->xdg_toplevel, !is_maximized); wlr_xdg_toplevel_set_maximized(toplevel->xdg_toplevel, !is_maximized);
wlr_scene_node_set_position(&view->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,
view->geometry.x, view->geometry.y); toplevel->geometry.x, toplevel->geometry.y);
} }
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 wb_view *view = wl_container_of(listener, view, request_minimize); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, request_minimize);
bool minimize_requested = view->xdg_toplevel->requested.minimized; bool minimize_requested = toplevel->xdg_toplevel->requested.minimized;
if (minimize_requested) { if (minimize_requested) {
view->previous_geometry = view->geometry; toplevel->previous_geometry = toplevel->geometry;
view->geometry.y = -view->geometry.height; toplevel->geometry.y = -toplevel->geometry.height;
struct wb_view *next_view = wl_container_of(view->link.next, next_view, link); struct wb_toplevel *next_toplevel = wl_container_of(toplevel->link.next, next_toplevel, link);
if (wl_list_length(&view->link) > 1) if (wl_list_length(&toplevel->link) > 1)
focus_view(next_view, next_view->xdg_toplevel->base->surface); focus_toplevel(next_toplevel, next_toplevel->xdg_toplevel->base->surface);
else else
focus_view(view, view->xdg_toplevel->base->surface); focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
} else { } else {
view->geometry = view->previous_geometry; toplevel->geometry = toplevel->previous_geometry;
} }
wlr_scene_node_set_position(&view->scene_tree->node, wlr_scene_node_set_position(&toplevel->scene_tree->node,
view->geometry.x, view->geometry.y); toplevel->geometry.x, toplevel->geometry.y);
} }
static void begin_interactive(struct wb_view *view, static void begin_interactive(struct wb_toplevel *toplevel,
enum wb_cursor_mode mode, uint32_t edges) { enum wb_cursor_mode mode, uint32_t edges) {
/* This function sets up an interactive move or resize operation, where the /* This function sets up an interactive move or resize operation, where the
* compositor stops propagating pointer events to clients and instead * compositor stops propagating pointer events to clients and instead
* consumes them itself, to move or resize windows. */ * consumes them itself, to move or resize windows. */
struct wb_server *server = view->server; struct wb_server *server = toplevel->server;
struct wlr_surface *focused_surface = struct wlr_surface *focused_surface =
server->seat->seat->pointer_state.focused_surface; server->seat->seat->pointer_state.focused_surface;
if (view->xdg_toplevel->base->surface != wlr_surface_get_root_surface(focused_surface)) { if (toplevel->xdg_toplevel->base->surface != wlr_surface_get_root_surface(focused_surface)) {
/* Deny move/resize requests from unfocused clients. */ /* Deny move/resize requests from unfocused clients. */
return; return;
} }
server->grabbed_view = view; server->grabbed_toplevel = toplevel;
server->cursor->cursor_mode = mode; server->cursor->cursor_mode = mode;
if (mode == WB_CURSOR_MOVE) { if (mode == WB_CURSOR_MOVE) {
server->grab_x = server->cursor->cursor->x - view->geometry.x; server->grab_x = server->cursor->cursor->x - toplevel->geometry.x;
server->grab_y = server->cursor->cursor->y - view->geometry.y; server->grab_y = server->cursor->cursor->y - toplevel->geometry.y;
} else if (mode == WB_CURSOR_RESIZE) { } else if (mode == WB_CURSOR_RESIZE) {
struct wlr_box geo_box; struct wlr_box geo_box;
wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box);
double border_x = (view->geometry.x + geo_box.x) + double border_x = (toplevel->geometry.x + geo_box.x) +
((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0); ((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0);
double border_y = (view->geometry.y + geo_box.y) + double border_y = (toplevel->geometry.y + geo_box.y) +
((edges & WLR_EDGE_BOTTOM) ? geo_box.height : 0); ((edges & WLR_EDGE_BOTTOM) ? geo_box.height : 0);
server->grab_x = server->cursor->cursor->x - border_x; server->grab_x = server->cursor->cursor->x - border_x;
server->grab_y = server->cursor->cursor->y - border_y; server->grab_y = server->cursor->cursor->y - border_y;
server->grab_geo_box = geo_box; server->grab_geo_box = geo_box;
server->grab_geo_box.x += view->geometry.x; server->grab_geo_box.x += toplevel->geometry.x;
server->grab_geo_box.y += view->geometry.y; server->grab_geo_box.y += toplevel->geometry.y;
server->resize_edges = edges; server->resize_edges = edges;
} }
@ -293,8 +274,8 @@ static void xdg_toplevel_request_move(
/* This event is raised when a client would like to begin an interactive /* This event is raised when a client would like to begin an interactive
* move, typically because the user clicked on their client-side * move, typically because the user clicked on their client-side
* decorations. */ * decorations. */
struct wb_view *view = wl_container_of(listener, view, request_move); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, request_move);
begin_interactive(view, WB_CURSOR_MOVE, 0); begin_interactive(toplevel, WB_CURSOR_MOVE, 0);
} }
static void xdg_toplevel_request_resize( static void xdg_toplevel_request_resize(
@ -303,29 +284,29 @@ static void xdg_toplevel_request_resize(
* resize, typically because the user clicked on their client-side * resize, typically because the user clicked on their client-side
* decorations. */ * decorations. */
struct wlr_xdg_toplevel_resize_event *event = data; struct wlr_xdg_toplevel_resize_event *event = data;
struct wb_view *view = wl_container_of(listener, view, request_resize); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, request_resize);
begin_interactive(view, WB_CURSOR_RESIZE, event->edges); begin_interactive(toplevel, WB_CURSOR_RESIZE, event->edges);
} }
static void handle_new_popup(struct wl_listener *listener, void *data) { static void handle_new_popup(struct wl_listener *listener, void *data) {
struct wlr_xdg_popup *popup = data; struct wlr_xdg_popup *popup = data;
struct wb_view *view = wl_container_of(listener, view, new_popup); struct wb_toplevel *toplevel = wl_container_of(listener, toplevel, new_popup);
struct wlr_output *wlr_output = wlr_output_layout_output_at( struct wlr_output *wlr_output = wlr_output_layout_output_at(
view->server->output_layout, toplevel->server->output_layout,
view->geometry.x + popup->current.geometry.x, toplevel->geometry.x + popup->current.geometry.x,
view->geometry.y + popup->current.geometry.y); toplevel->geometry.y + popup->current.geometry.y);
if (!wlr_output) { if (!wlr_output) {
return; return;
} }
struct wb_output *output = wlr_output->data; struct wb_output *output = wlr_output->data;
int top_margin = (view->server->config) ? int top_margin = (toplevel->server->config) ?
view->server->config->margins.top : 0; toplevel->server->config->margins.top : 0;
struct wlr_box output_toplevel_box = { struct wlr_box output_toplevel_box = {
.x = output->geometry.x - view->geometry.x, .x = output->geometry.x - toplevel->geometry.x,
.y = output->geometry.y - view->geometry.y, .y = output->geometry.y - toplevel->geometry.y,
.width = output->geometry.width, .width = output->geometry.width,
.height = output->geometry.height - top_margin, .height = output->geometry.height - top_margin,
}; };
@ -345,15 +326,9 @@ static void handle_new_xdg_surface(struct wl_listener *listener, void *data) {
* we always set the user data field of xdg_surfaces to the corresponding * we always set the user data field of xdg_surfaces to the corresponding
* scene node. */ * scene node. */
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
#if WLR_CHECK_VERSION(0, 17, 0)
struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface( struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface(
xdg_surface->popup->parent); xdg_surface->popup->parent);
if (parent != NULL) { if (parent != NULL) {
#else
if (wlr_surface_is_xdg_surface(xdg_surface->popup->parent)) {
struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface(
xdg_surface->popup->parent);
#endif
struct wlr_scene_tree *parent_tree = parent->data; struct wlr_scene_tree *parent_tree = parent->data;
xdg_surface->data = wlr_scene_xdg_surface_create( xdg_surface->data = wlr_scene_xdg_surface_create(
@ -365,49 +340,41 @@ static void handle_new_xdg_surface(struct wl_listener *listener, void *data) {
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE)
return; return;
/* Allocate a wb_view for this surface */ /* Allocate a wb_toplevel for this surface */
struct wb_view *view = struct wb_toplevel *toplevel =
calloc(1, sizeof(struct wb_view)); calloc(1, sizeof(struct wb_toplevel));
view->server = server; toplevel->server = server;
view->xdg_toplevel = xdg_surface->toplevel; toplevel->xdg_toplevel = xdg_surface->toplevel;
/* Listen to the various events it can emit */ /* Listen to the various events it can emit */
view->map.notify = xdg_toplevel_map; toplevel->map.notify = xdg_toplevel_map;
#if WLR_CHECK_VERSION(0, 17, 0) wl_signal_add(&xdg_surface->surface->events.map, &toplevel->map);
wl_signal_add(&xdg_surface->surface->events.map, &view->map); toplevel->unmap.notify = xdg_toplevel_unmap;
#else wl_signal_add(&xdg_surface->surface->events.unmap, &toplevel->unmap);
wl_signal_add(&xdg_surface->events.map, &view->map); toplevel->destroy.notify = xdg_toplevel_destroy;
#endif wl_signal_add(&xdg_surface->events.destroy, &toplevel->destroy);
view->unmap.notify = xdg_toplevel_unmap; toplevel->new_popup.notify = handle_new_popup;
#if WLR_CHECK_VERSION(0, 17, 0) wl_signal_add(&xdg_surface->events.new_popup, &toplevel->new_popup);
wl_signal_add(&xdg_surface->surface->events.unmap, &view->unmap);
#else
wl_signal_add(&xdg_surface->events.unmap, &view->unmap);
#endif
view->destroy.notify = xdg_toplevel_destroy;
wl_signal_add(&xdg_surface->events.destroy, &view->destroy);
view->new_popup.notify = handle_new_popup;
wl_signal_add(&xdg_surface->events.new_popup, &view->new_popup);
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
view->scene_tree = wlr_scene_xdg_surface_create( toplevel->scene_tree = wlr_scene_xdg_surface_create(
&view->server->scene->tree, view->xdg_toplevel->base); &toplevel->server->scene->tree, toplevel->xdg_toplevel->base);
view->scene_tree->node.data = view; toplevel->scene_tree->node.data = toplevel;
xdg_surface->data = view->scene_tree; xdg_surface->data = toplevel->scene_tree;
struct wlr_xdg_toplevel *toplevel = view->xdg_toplevel; struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel;
view->request_fullscreen.notify = xdg_toplevel_request_fullscreen; toplevel->request_fullscreen.notify = xdg_toplevel_request_fullscreen;
wl_signal_add(&toplevel->events.request_fullscreen, &view->request_fullscreen); wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
view->request_maximize.notify = xdg_toplevel_request_maximize; toplevel->request_maximize.notify = xdg_toplevel_request_maximize;
wl_signal_add(&toplevel->events.request_maximize, &view->request_maximize); wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize);
view->request_minimize.notify = xdg_toplevel_request_minimize; toplevel->request_minimize.notify = xdg_toplevel_request_minimize;
wl_signal_add(&toplevel->events.request_minimize, &view->request_minimize); wl_signal_add(&xdg_toplevel->events.request_minimize, &toplevel->request_minimize);
view->request_move.notify = xdg_toplevel_request_move; toplevel->request_move.notify = xdg_toplevel_request_move;
wl_signal_add(&toplevel->events.request_move, &view->request_move); wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
view->request_resize.notify = xdg_toplevel_request_resize; toplevel->request_resize.notify = xdg_toplevel_request_resize;
wl_signal_add(&toplevel->events.request_resize, &view->request_resize); wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize);
wl_list_insert(&view->server->views, &view->link); wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
} }
} }