Skip to content

Commit

Permalink
Merge pull request #39 from migueldeoleiros/feature/tiling
Browse files Browse the repository at this point in the history
Implement tiling with master stack
  • Loading branch information
migueldeoleiros authored Oct 30, 2024
2 parents 1e694fa + 0568fd0 commit 038cb87
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 11 deletions.
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

0 comments on commit 038cb87

Please sign in to comment.