Skip to content

Commit 258b268

Browse files
committed
Add --background option to run kitty on the Wayland desktop
--background-monitor can be used to specify exactly which monitor to run kitty on.
1 parent 71c8d82 commit 258b268

File tree

14 files changed

+455
-9
lines changed

14 files changed

+455
-9
lines changed

glfw/glfw.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Env:
3131
wayland_scanner: str = ''
3232
wayland_scanner_code: str = ''
3333
wayland_protocols: Tuple[str, ...] = ()
34+
custom_wayland_protocols: Tuple[str, ...] = ()
3435

3536
def __init__(
3637
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
@@ -99,7 +100,8 @@ def init_env(env: Env, pkg_config: Callable, pkg_version: Callable, at_least_ver
99100
scanner_version = tuple(map(int, pkg_config('wayland-scanner', '--modversion')[0].strip().split('.')))
100101
ans.wayland_scanner_code = 'private-code' if scanner_version >= (1, 14, 91) else 'code'
101102
ans.wayland_protocols = tuple(sinfo[module]['protocols'])
102-
for p in ans.wayland_protocols:
103+
ans.custom_wayland_protocols = tuple(sinfo[module]['custom_protocols'])
104+
for p in ans.wayland_protocols + ans.custom_wayland_protocols:
103105
ans.sources.append(wayland_protocol_file_name(p))
104106
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
105107
for dep in 'wayland-client wayland-cursor xkbcommon dbus-1'.split():
@@ -119,8 +121,11 @@ def init_env(env: Env, pkg_config: Callable, pkg_version: Callable, at_least_ver
119121

120122
def build_wayland_protocols(env: Env, Command: Callable, parallel_run: Callable, emphasis: Callable, newer: Callable, dest_dir: str) -> None:
121123
items = []
122-
for protocol in env.wayland_protocols:
123-
src = os.path.join(env.wayland_packagedir, protocol)
124+
protocols = [(protocol, os.path.join(env.wayland_packagedir, protocol))
125+
for protocol in env.wayland_protocols]
126+
protocols += [(protocol, os.path.join(base, protocol))
127+
for protocol in env.custom_wayland_protocols]
128+
for protocol, src in protocols:
124129
if not os.path.exists(src):
125130
raise SystemExit('The wayland-protocols package on your system is missing the {} protocol definition file'.format(protocol))
126131
for ext in 'hc':

glfw/glfw3.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,8 @@ typedef enum GLFWMouseButton {
10341034
#define GLFW_X11_INSTANCE_NAME 0x00024002
10351035

10361036
#define GLFW_WAYLAND_APP_ID 0x00025001
1037+
#define GLFW_WAYLAND_BACKGROUND 0x00025002
1038+
#define GLFW_WAYLAND_BACKGROUND_MONITOR 0x00025003
10371039
/*! @} */
10381040

10391041
#define GLFW_NO_API 0

glfw/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ struct _GLFWwndconfig
315315
} x11;
316316
struct {
317317
char appId[256];
318+
bool background;
319+
char backgroundMonitor[256];
318320
} wl;
319321
};
320322

glfw/source-info.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
"unstable/primary-selection/primary-selection-unstable-v1.xml",
8080
"unstable/text-input/text-input-unstable-v3.xml"
8181
],
82+
"custom_protocols": [
83+
"wlr-layer-shell-unstable-v1.xml"
84+
],
8285
"sources": [
8386
"wl_init.c",
8487
"wl_monitor.c",

glfw/window.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
460460
case GLFW_REFRESH_RATE:
461461
_glfw.hints.refreshRate = value;
462462
return;
463+
case GLFW_WAYLAND_BACKGROUND:
464+
_glfw.hints.window.wl.background = value;
465+
return;
463466
}
464467

465468
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
@@ -489,6 +492,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
489492
strncpy(_glfw.hints.window.wl.appId, value,
490493
sizeof(_glfw.hints.window.wl.appId) - 1);
491494
return;
495+
case GLFW_WAYLAND_BACKGROUND_MONITOR:
496+
strncpy(_glfw.hints.window.wl.backgroundMonitor, value,
497+
sizeof(_glfw.hints.window.wl.backgroundMonitor) - 1);
498+
return;
492499
}
493500

494501
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);

glfw/wl_init.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,13 @@ static void registryHandleGlobal(void* data UNUSED,
644644
_glfwSetupWaylandPrimarySelectionDevice();
645645
}
646646
}
647+
else if (strcmp(interface, "zwlr_layer_shell_v1") == 0)
648+
{
649+
_glfw.wl.layer_shell =
650+
wl_registry_bind(registry, name,
651+
&zwlr_layer_shell_v1_interface,
652+
1);
653+
}
647654

648655
}
649656

glfw/wl_platform.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
5959
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
6060
#include "wayland-primary-selection-unstable-v1-client-protocol.h"
6161
#include "wl_text_input.h"
62+
#include "wayland-wlr-layer-shell-unstable-v1-client-protocol.h"
6263

6364
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
6465
#define _glfw_dlclose(handle) dlclose(handle)
@@ -146,6 +147,10 @@ typedef struct _GLFWwindowWayland
146147
struct zxdg_toplevel_decoration_v1* decoration;
147148
} xdg;
148149

150+
struct {
151+
struct zwlr_layer_surface_v1* surface;
152+
} layer;
153+
149154
_GLFWcursor* currentCursor;
150155
double cursorPosX, cursorPosY, allCursorPosX, allCursorPosY;
151156

@@ -261,6 +266,7 @@ typedef struct _GLFWlibraryWayland
261266
struct zwp_primary_selection_device_manager_v1* primarySelectionDeviceManager;
262267
struct zwp_primary_selection_device_v1* primarySelectionDevice;
263268
struct zwp_primary_selection_source_v1* dataSourceForPrimarySelection;
269+
struct zwlr_layer_shell_v1* layer_shell;
264270

265271
int compositorVersion;
266272
int seatVersion;
@@ -342,6 +348,7 @@ typedef struct _GLFWcursorWayland
342348
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
343349
void _glfwSetupWaylandDataDevice(void);
344350
void _glfwSetupWaylandPrimarySelectionDevice(void);
351+
struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle);
345352
void animateCursorImage(id_type timer_id, void *data);
346353
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape, struct wl_cursor_theme*);
347354
void destroy_data_offer(_GLFWWaylandDataOffer*);

glfw/wl_window.c

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,86 @@ static bool createXdgSurface(_GLFWwindow* window)
568568
return true;
569569
}
570570

571+
static void layerSurfaceHandleConfigure(void* data,
572+
struct zwlr_layer_surface_v1* surface,
573+
uint32_t serial,
574+
uint32_t width,
575+
uint32_t height) {
576+
_GLFWwindow* window = data;
577+
dispatchChangesAfterConfigure(window, width, height);
578+
zwlr_layer_surface_v1_ack_configure(surface, serial);
579+
}
580+
581+
582+
static void layerSurfaceHandleClosed(void* data,
583+
struct zwlr_layer_surface_v1* surface UNUSED) {
584+
_GLFWwindow* window = data;
585+
_glfwInputWindowCloseRequest(window);
586+
}
587+
588+
static const struct zwlr_layer_surface_v1_listener layerSurfaceListener = {
589+
layerSurfaceHandleConfigure,
590+
layerSurfaceHandleClosed,
591+
};
592+
593+
static struct wl_output* findWlOutput(const char* name)
594+
{
595+
int count;
596+
GLFWmonitor** monitors = glfwGetMonitors(&count);
597+
598+
for (int i = 0; i < count; ++i)
599+
{
600+
if (strcmp(glfwGetMonitorName(monitors[i]), name) == 0)
601+
{
602+
return glfwGetWaylandMonitor(monitors[i]);
603+
}
604+
}
605+
return NULL;
606+
}
607+
608+
static bool createLayerSurface(_GLFWwindow* window,
609+
const _GLFWwndconfig* wndconfig)
610+
{
611+
if (!_glfw.wl.layer_shell)
612+
{
613+
_glfwInputError(GLFW_PLATFORM_ERROR,
614+
"Wayland: layer-shell protocol unsupported");
615+
return false;
616+
}
617+
618+
struct wl_output* output = findWlOutput(wndconfig->wl.backgroundMonitor);
619+
window->wl.layer.surface =
620+
zwlr_layer_shell_v1_get_layer_surface(_glfw.wl.layer_shell,
621+
window->wl.surface, output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM,
622+
"kitty");
623+
624+
if (!window->wl.layer.surface)
625+
{
626+
_glfwInputError(GLFW_PLATFORM_ERROR,
627+
"Wayland: layer-surface creation failed");
628+
return false;
629+
}
630+
631+
zwlr_layer_surface_v1_set_size(window->wl.layer.surface, 0, 0);
632+
zwlr_layer_surface_v1_set_anchor(window->wl.layer.surface,
633+
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
634+
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
635+
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
636+
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
637+
zwlr_layer_surface_v1_set_exclusive_zone(window->wl.layer.surface, -1);
638+
zwlr_layer_surface_v1_set_margin(window->wl.layer.surface, 0, 0, 0, 0);
639+
zwlr_layer_surface_v1_set_keyboard_interactivity(window->wl.layer.surface, 0);
640+
641+
zwlr_layer_surface_v1_add_listener(window->wl.layer.surface,
642+
&layerSurfaceListener,
643+
window);
644+
645+
wl_surface_commit(window->wl.surface);
646+
wl_display_roundtrip(_glfw.wl.display);
647+
648+
return true;
649+
}
650+
571651
static void incrementCursorImage(_GLFWwindow* window)
572652
{
573653
if (window && window->wl.decorations.focus == CENTRAL_WINDOW && window->cursorMode != GLFW_CURSOR_HIDDEN) {
@@ -746,8 +826,16 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
746826

747827
if (wndconfig->visible)
748828
{
749-
if (!createXdgSurface(window))
750-
return false;
829+
if (wndconfig->wl.background)
830+
{
831+
if (!createLayerSurface(window, wndconfig))
832+
return false;
833+
}
834+
else
835+
{
836+
if (!createXdgSurface(window))
837+
return false;
838+
}
751839

752840
window->wl.visible = true;
753841
}

0 commit comments

Comments
 (0)