Skip to content

Commit

Permalink
Add --background option to run kitty on the Wayland desktop (#1)
Browse files Browse the repository at this point in the history
--background-monitor can be used to specify exactly which monitor to run
kitty on.
  • Loading branch information
quantum5 committed Jan 4, 2021
1 parent 3ce04c3 commit 853a29c
Show file tree
Hide file tree
Showing 14 changed files with 447 additions and 9 deletions.
11 changes: 8 additions & 3 deletions glfw/glfw.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Env:
wayland_scanner: str = ''
wayland_scanner_code: str = ''
wayland_protocols: Tuple[str, ...] = ()
custom_wayland_protocols: Tuple[str, ...] = ()

def __init__(
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
Expand Down Expand Up @@ -95,7 +96,8 @@ def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_co
scanner_version = tuple(map(int, pkg_config('wayland-scanner', '--modversion')[0].strip().split('.')))
ans.wayland_scanner_code = 'private-code' if scanner_version >= (1, 14, 91) else 'code'
ans.wayland_protocols = tuple(sinfo[module]['protocols'])
for p in ans.wayland_protocols:
ans.custom_wayland_protocols = tuple(sinfo[module]['custom_protocols'])
for p in ans.wayland_protocols + ans.custom_wayland_protocols:
ans.sources.append(wayland_protocol_file_name(p))
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
for dep in 'wayland-client wayland-cursor xkbcommon dbus-1'.split():
Expand All @@ -115,8 +117,11 @@ def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_co

def build_wayland_protocols(env: Env, Command: Callable, parallel_run: Callable, emphasis: Callable, newer: Callable, dest_dir: str) -> None:
items = []
for protocol in env.wayland_protocols:
src = os.path.join(env.wayland_packagedir, protocol)
protocols = [(protocol, os.path.join(env.wayland_packagedir, protocol))
for protocol in env.wayland_protocols]
protocols += [(protocol, os.path.join(base, protocol))
for protocol in env.custom_wayland_protocols]
for protocol, src in protocols:
if not os.path.exists(src):
raise SystemExit('The wayland-protocols package on your system is missing the {} protocol definition file'.format(protocol))
for ext in 'hc':
Expand Down
2 changes: 2 additions & 0 deletions glfw/glfw3.h
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,8 @@ extern "C" {
#define GLFW_X11_INSTANCE_NAME 0x00024002

#define GLFW_WAYLAND_APP_ID 0x00025001
#define GLFW_WAYLAND_BACKGROUND 0x00025002
#define GLFW_WAYLAND_BACKGROUND_MONITOR 0x00025003
/*! @} */

#define GLFW_NO_API 0
Expand Down
2 changes: 2 additions & 0 deletions glfw/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ struct _GLFWwndconfig
} x11;
struct {
char appId[256];
bool background;
char backgroundMonitor[256];
} wl;
};

Expand Down
3 changes: 3 additions & 0 deletions glfw/source-info.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
"unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
"unstable/primary-selection/primary-selection-unstable-v1.xml"
],
"custom_protocols": [
"wlr-layer-shell-unstable-v1.xml"
],
"sources": [
"wl_init.c",
"wl_monitor.c",
Expand Down
7 changes: 7 additions & 0 deletions glfw/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_REFRESH_RATE:
_glfw.hints.refreshRate = value;
return;
case GLFW_WAYLAND_BACKGROUND:
_glfw.hints.window.wl.background = value;
return;
}

_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
Expand Down Expand Up @@ -491,6 +494,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
strncpy(_glfw.hints.window.wl.appId, value,
sizeof(_glfw.hints.window.wl.appId) - 1);
return;
case GLFW_WAYLAND_BACKGROUND_MONITOR:
strncpy(_glfw.hints.window.wl.backgroundMonitor, value,
sizeof(_glfw.hints.window.wl.backgroundMonitor) - 1);
return;
}

_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
Expand Down
7 changes: 7 additions & 0 deletions glfw/wl_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,13 @@ static void registryHandleGlobal(void* data UNUSED,
_glfwSetupWaylandPrimarySelectionDevice();
}
}
else if (strcmp(interface, "zwlr_layer_shell_v1") == 0)
{
_glfw.wl.layer_shell =
wl_registry_bind(registry, name,
&zwlr_layer_shell_v1_interface,
1);
}

}

Expand Down
7 changes: 7 additions & 0 deletions glfw/wl_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#include "wayland-primary-selection-unstable-v1-client-protocol.h"
#include "wayland-wlr-layer-shell-unstable-v1-client-protocol.h"

#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
Expand Down Expand Up @@ -130,6 +131,10 @@ typedef struct _GLFWwindowWayland
struct zxdg_toplevel_decoration_v1* decoration;
} xdg;

struct {
struct zwlr_layer_surface_v1* surface;
} layer;

_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;

Expand Down Expand Up @@ -216,6 +221,7 @@ typedef struct _GLFWlibraryWayland
struct zwp_primary_selection_device_manager_v1* primarySelectionDeviceManager;
struct zwp_primary_selection_device_v1* primarySelectionDevice;
struct zwp_primary_selection_source_v1* dataSourceForPrimarySelection;
struct zwlr_layer_shell_v1* layer_shell;

int compositorVersion;
int seatVersion;
Expand Down Expand Up @@ -298,6 +304,7 @@ typedef struct _GLFWcursorWayland
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
void _glfwSetupWaylandDataDevice(void);
void _glfwSetupWaylandPrimarySelectionDevice(void);
struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle);
void animateCursorImage(id_type timer_id, void *data);
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape, struct wl_cursor_theme*);
void destroy_data_offer(_GLFWWaylandDataOffer*);
93 changes: 91 additions & 2 deletions glfw/wl_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,87 @@ static bool createXdgSurface(_GLFWwindow* window)
return true;
}

static void layerSurfaceHandleConfigure(void* data,
struct zwlr_layer_surface_v1* surface,
uint32_t serial,
uint32_t width,
uint32_t height) {
_GLFWwindow* window = data;
window->wl.fullscreened = true;
dispatchChangesAfterConfigure(window, width, height);
zwlr_layer_surface_v1_ack_configure(surface, serial);
}


static void layerSurfaceHandleClosed(void* data,
struct zwlr_layer_surface_v1* surface UNUSED) {
_GLFWwindow* window = data;
_glfwInputWindowCloseRequest(window);
}

static const struct zwlr_layer_surface_v1_listener layerSurfaceListener = {
layerSurfaceHandleConfigure,
layerSurfaceHandleClosed,
};

static struct wl_output* findWlOutput(const char* name)
{
int count;
GLFWmonitor** monitors = glfwGetMonitors(&count);

for (int i = 0; i < count; ++i)
{
if (strcmp(glfwGetMonitorName(monitors[i]), name) == 0)
{
return glfwGetWaylandMonitor(monitors[i]);
}
}
return NULL;
}

static bool createLayerSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
if (!_glfw.wl.layer_shell)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: layer-shell protocol unsupported");
return false;
}

struct wl_output* output = findWlOutput(wndconfig->wl.backgroundMonitor);
window->wl.layer.surface =
zwlr_layer_shell_v1_get_layer_surface(_glfw.wl.layer_shell,
window->wl.surface, output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM,
"kitty");

if (!window->wl.layer.surface)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: layer-surface creation failed");
return false;
}

zwlr_layer_surface_v1_set_size(window->wl.layer.surface, 0, 0);
zwlr_layer_surface_v1_set_anchor(window->wl.layer.surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
zwlr_layer_surface_v1_set_exclusive_zone(window->wl.layer.surface, -1);
zwlr_layer_surface_v1_set_margin(window->wl.layer.surface, 0, 0, 0, 0);
zwlr_layer_surface_v1_set_keyboard_interactivity(window->wl.layer.surface, 0);

zwlr_layer_surface_v1_add_listener(window->wl.layer.surface,
&layerSurfaceListener,
window);

wl_surface_commit(window->wl.surface);
wl_display_roundtrip(_glfw.wl.display);

return true;
}

static void incrementCursorImage(_GLFWwindow* window)
{
if (window && window->wl.decorations.focus == mainWindow && window->cursorMode != GLFW_CURSOR_HIDDEN) {
Expand Down Expand Up @@ -913,8 +994,16 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,

if (wndconfig->visible)
{
if (!createXdgSurface(window))
return false;
if (wndconfig->wl.background)
{
if (!createLayerSurface(window, wndconfig))
return false;
}
else
{
if (!createXdgSurface(window))
return false;
}

window->wl.visible = true;
}
Expand Down
Loading

0 comments on commit 853a29c

Please sign in to comment.