Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement tiling with master stack #39

Merged
merged 4 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ jobs:
run: |
sudo apt update
sudo apt install -y meson ninja-build gcc cmake pkg-config \
libxkbcommon-dev libconfig-dev libjson-c-dev python3 weston
libxkbcommon-dev libconfig-dev libjson-c-dev

- name: Install test dependencies
run: sudo apt-get install -y xvfb python3 weston

- name: Install wayland-server
run: |
Expand Down Expand Up @@ -72,7 +75,7 @@ jobs:
- name: Run functional tests
run: |
mkdir -p $XDG_RUNTIME_DIR
TURTILE_BACKEND=headless ./build/turtile -c tests/test.cfg &
TURTILE_BACKEND=headless xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' ./build/turtile -c tests/test.cfg &
sleep 5
python tests/test.py
env:
Expand Down
1 change: 1 addition & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ int main(int argc, char *argv[]) {
* https://drewdevault.com/2018/07/29/Wayland-shells.html.
*/
wl_list_init(&server.toplevels);
wl_list_init(&server.focus_toplevels);
server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 3);
server.new_xdg_toplevel.notify = server_new_xdg_toplevel;
wl_signal_add(&server.xdg_shell->events.new_toplevel, &server.new_xdg_toplevel);
Expand Down
52 changes: 50 additions & 2 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@

#include "cursor.h"
#include "keyboard.h"
#include "src/output.h"
#include "toplevel.h"
#include "popup.h"
#include "wlr/util/box.h"
#include "wlr/types/wlr_output_layout.h"
#include <assert.h>
#include <stdlib.h>
#include <wlr/types/wlr_scene.h>
Expand Down Expand Up @@ -113,14 +116,59 @@ void server_new_xdg_popup(struct wl_listener *listener, void *data) {
wl_signal_add(&xdg_popup->events.destroy, &popup->destroy);
}

void server_redraw_windows(struct turtile_server *server){
void tile(struct turtile_server *server) {
int nmaster = 1; //number of master windows
double mfact = 0.5; //master size
unsigned int i, n = 0, mw, my, ty;
struct turtile_toplevel *toplevel;

struct wlr_box m;
struct turtile_output *output;
wl_list_for_each(output, &server->outputs, link)
wlr_output_layout_get_box(server->output_layout, output->wlr_output, &m);

wl_list_for_each(toplevel, &server->toplevels, link) {
if (toplevel->workspace == server->active_workspace)
n++;
}
if (n == 0)
return;

if (n > nmaster)
mw = nmaster ? m.width * mfact : 0;
else
mw = m.width;
i = my = ty = 0;
wl_list_for_each(toplevel, &server->toplevels, link) {
if (toplevel->workspace != server->active_workspace)
continue;
if (i < 1) {
toplevel_resize(toplevel, (struct wlr_box){
.x = m.x, .y = m.y + my,
.width = mw,
.height = (m.height - my) /
(((n) < (nmaster) ? (n) : (nmaster)) - i)});
my += toplevel->geometry.height;
} else {
toplevel_resize(toplevel, (struct wlr_box){
.x = m.x + mw, .y = m.y + ty,
.width = m.width - mw,
.height = (m.height - ty) / (n - i)});
ty += toplevel->geometry.height;
}
i++;
}
}

void server_redraw_windows(struct turtile_server *server) {
struct turtile_toplevel *toplevel;
wl_list_for_each(toplevel, &server->toplevels, link) {
if (toplevel->workspace == server->active_workspace) {
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true);
} else {
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false);
}
}

}
tile(server);
}
3 changes: 2 additions & 1 deletion src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct turtile_server {
struct wl_listener new_xdg_toplevel;
struct wl_listener new_xdg_popup;
struct wl_list toplevels;
struct wl_list focus_toplevels;

struct wl_list workspaces;
struct turtile_workspace *active_workspace;
Expand Down Expand Up @@ -101,7 +102,7 @@ void server_new_xdg_popup(struct wl_listener *listener, void *data);

/**
* Redraws the windows on the server by enabling or disabling their scene nodes
* based on whether they are on the active workspace.
* based on whether they are on the active workspace, and run tiling script.
*
* @param server The server instance whose windows will be redrawn.
*/
Expand Down
34 changes: 29 additions & 5 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
*/

#include "toplevel.h"
#include "src/server.h"
#include "src/workspace.h"
#include <stdlib.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_shell.h>

void focus_toplevel(struct turtile_toplevel *toplevel, struct wlr_surface *surface) {
/* Note: this function only deals with keyboard focus. */
Expand Down Expand Up @@ -54,11 +54,11 @@ void focus_toplevel(struct turtile_toplevel *toplevel, struct wlr_surface *surfa
}
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
// switch to the right workspace
switch_workspace(toplevel->workspace);
/* switch_workspace(toplevel->workspace); */
server->active_workspace = toplevel->workspace;
/* 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->toplevels, &toplevel->link);
wl_list_remove(&toplevel->flink);
wl_list_insert(&server->focus_toplevels, &toplevel->flink);
/* Activate the new surface */
wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true);
/*
Expand All @@ -70,6 +70,15 @@ void focus_toplevel(struct turtile_toplevel *toplevel, struct wlr_surface *surfa
wlr_seat_keyboard_notify_enter(seat, toplevel->xdg_toplevel->base->surface,
keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
}
server_redraw_windows(server);
}

struct turtile_toplevel *get_first_toplevel(struct turtile_server *server) {
struct turtile_toplevel *toplevel;
wl_list_for_each(toplevel, &server->focus_toplevels, flink)
if (toplevel->workspace == server->active_workspace)
return toplevel;
return NULL;
}

struct turtile_toplevel *desktop_toplevel_at(
Expand Down Expand Up @@ -100,12 +109,23 @@ struct turtile_toplevel *desktop_toplevel_at(
return tree->node.data;
}

void toplevel_resize(
struct turtile_toplevel *toplevel, struct wlr_box geometry) {
toplevel->geometry = geometry;

wlr_scene_node_set_position(&toplevel->scene_tree->node,
toplevel->geometry.x, toplevel->geometry.y);
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, toplevel->geometry.width,
toplevel->geometry.height);
}

void xdg_toplevel_map(struct wl_listener *listener, void *data) {
/* Called when the surface is mapped, or ready to display on-screen. */
struct turtile_toplevel *toplevel = wl_container_of(listener, toplevel, map);

toplevel->workspace = toplevel->server->active_workspace;
wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
wl_list_insert(&toplevel->server->focus_toplevels, &toplevel->flink);

focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
}
Expand All @@ -117,6 +137,9 @@ void xdg_toplevel_unmap(struct wl_listener *listener, void *data) {
/* Reset the cursor mode if the grabbed toplevel was unmapped. */
if (toplevel == toplevel->server->grabbed_toplevel) {
reset_cursor_mode(toplevel->server);

struct turtile_toplevel *newfocus = get_first_toplevel(toplevel->server);
focus_toplevel(newfocus, newfocus->xdg_toplevel->base->surface);
}

wl_list_remove(&toplevel->link);
Expand Down Expand Up @@ -148,6 +171,7 @@ void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&toplevel->request_maximize.link);
wl_list_remove(&toplevel->request_fullscreen.link);

server_redraw_windows(toplevel->server);
free(toplevel);
}

Expand Down
20 changes: 20 additions & 0 deletions src/toplevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
#include "cursor.h"
#include "src/output.h"
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_xdg_shell.h>

struct turtile_toplevel {
struct wl_list link;
struct wl_list flink;
struct turtile_server *server;
struct wlr_xdg_toplevel *xdg_toplevel;
struct wlr_scene_tree *scene_tree;
struct wlr_box geometry;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener commit;
Expand All @@ -53,6 +56,15 @@ struct turtile_toplevel {
*/
void focus_toplevel(struct turtile_toplevel *toplevel,
struct wlr_surface *surface);
/**
* Retrieves the first toplevel on the active workspace of the given server.
* If no such toplevel is found, NULL is returned.

* @param server The turtile server to search for the toplevel on.
* @return A pointer to the first toplevel on the active workspace,
* or NULL if no such toplevel is found.
*/
struct turtile_toplevel *get_first_toplevel(struct turtile_server *server);

/**
* Given a server, layout coordinates, and optional surface and position
Expand All @@ -73,6 +85,14 @@ void focus_toplevel(struct turtile_toplevel *toplevel,
struct turtile_toplevel *desktop_toplevel_at(
struct turtile_server *server, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy);
/**
* Resizes the given toplevel to the specified geometry.
*
* @param toplevel The turtile toplevel to resize.
* @param geometry The new geometry for the toplevel.
*/
void toplevel_resize(
struct turtile_toplevel *toplevel, struct wlr_box geometry);

/**
* Called when the surface is mapped, or ready to display on-screen.
Expand Down
7 changes: 6 additions & 1 deletion src/workspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "workspace.h"
#include "src/config.h"
#include "src/server.h"
#include "src/toplevel.h"
#include "wlr/util/log.h"
#include <stdlib.h>
#include <string.h>
Expand All @@ -45,8 +46,12 @@ void switch_workspace(struct turtile_workspace *workspace){
return;
}
struct turtile_server *server = workspace->server;

server->active_workspace = workspace;

struct turtile_toplevel *newfocus = get_first_toplevel(server);
if(newfocus != NULL)
focus_toplevel(newfocus, newfocus->xdg_toplevel->base->surface);

server_redraw_windows(server);
}

Expand Down
Loading