Skip to content

Commit

Permalink
wl_output, wl_seat, wl_surface, text_input xdg_activation
Browse files Browse the repository at this point in the history
  • Loading branch information
Riteo committed Sep 12, 2024
1 parent e5d5c20 commit af00955
Show file tree
Hide file tree
Showing 7 changed files with 592 additions and 432 deletions.
5 changes: 5 additions & 0 deletions platform/linuxbsd/wayland/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,16 @@ source_files = [
"thread/core/keyboard.cpp",
"thread/core/pointer.cpp",
"thread/core/registry.cpp",
"thread/core/output.cpp",
"thread/core/seat.cpp",
"thread/core/surface.cpp",

"thread/libdecor.cpp",
"thread/primary-selection.cpp",
"thread/tablet.cpp",
"thread/text-input.cpp",
"thread/util.cpp",
"thread/xdg-activation.cpp",
"thread/xdg-shell.cpp",

"key_mapping_xkb.cpp",
Expand Down
98 changes: 98 additions & 0 deletions platform/linuxbsd/wayland/thread/core/output.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**************************************************************************/
/* output.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "wayland/wayland_thread.h"

void WaylandThread::_wl_output_on_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) {
ScreenState *ss = (ScreenState *)data;
ERR_FAIL_NULL(ss);

ss->pending_data.position.x = x;

ss->pending_data.position.x = x;
ss->pending_data.position.y = y;

ss->pending_data.physical_size.width = physical_width;
ss->pending_data.physical_size.height = physical_height;

ss->pending_data.make.parse_utf8(make);
ss->pending_data.model.parse_utf8(model);

// `wl_output::done` is a version 2 addition. We'll directly update the data
// for compatibility.
if (wl_output_get_version(wl_output) == 1) {
ss->data = ss->pending_data;
}
}

void WaylandThread::_wl_output_on_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
ScreenState *ss = (ScreenState *)data;
ERR_FAIL_NULL(ss);

ss->pending_data.size.width = width;
ss->pending_data.size.height = height;

ss->pending_data.refresh_rate = refresh ? refresh / 1000.0f : -1;

// `wl_output::done` is a version 2 addition. We'll directly update the data
// for compatibility.
if (wl_output_get_version(wl_output) == 1) {
ss->data = ss->pending_data;
}
}

// NOTE: The following `wl_output` events are only for version 2 onwards, so we
// can assume that they're "atomic" (i.e. rely on the `wl_output::done` event).

void WaylandThread::_wl_output_on_done(void *data, struct wl_output *wl_output) {
ScreenState *ss = (ScreenState *)data;
ERR_FAIL_NULL(ss);

ss->data = ss->pending_data;

ss->wayland_thread->_update_scale(ss->data.scale);

DEBUG_LOG_WAYLAND_THREAD(vformat("Output %x done.", (size_t)wl_output));
}

void WaylandThread::_wl_output_on_scale(void *data, struct wl_output *wl_output, int32_t factor) {
ScreenState *ss = (ScreenState *)data;
ERR_FAIL_NULL(ss);

ss->pending_data.scale = factor;

DEBUG_LOG_WAYLAND_THREAD(vformat("Output %x scale %d", (size_t)wl_output, factor));
}

void WaylandThread::_wl_output_on_name(void *data, struct wl_output *wl_output, const char *name) {
}

void WaylandThread::_wl_output_on_description(void *data, struct wl_output *wl_output, const char *description) {
}
119 changes: 119 additions & 0 deletions platform/linuxbsd/wayland/thread/core/seat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**************************************************************************/
/* seat.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "wayland/wayland_thread.h"

void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) {
SeatState *ss = (SeatState *)data;

ERR_FAIL_NULL(ss);

// TODO: Handle touch.

// Pointer handling.
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
if (!ss->wl_pointer) {
ss->cursor_surface = wl_compositor_create_surface(ss->registry->wl_compositor);
wl_surface_commit(ss->cursor_surface);

ss->wl_pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(ss->wl_pointer, &wl_pointer_listener, ss);

if (ss->registry->wp_relative_pointer_manager) {
ss->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(ss->registry->wp_relative_pointer_manager, ss->wl_pointer);
zwp_relative_pointer_v1_add_listener(ss->wp_relative_pointer, &wp_relative_pointer_listener, ss);
}

if (ss->registry->wp_pointer_gestures) {
ss->wp_pointer_gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(ss->registry->wp_pointer_gestures, ss->wl_pointer);
zwp_pointer_gesture_pinch_v1_add_listener(ss->wp_pointer_gesture_pinch, &wp_pointer_gesture_pinch_listener, ss);
}

// TODO: Constrain new pointers if the global mouse mode is constrained.
}
} else {
if (ss->cursor_frame_callback) {
// Just in case. I got bitten by weird race-like conditions already.
wl_callback_set_user_data(ss->cursor_frame_callback, nullptr);

wl_callback_destroy(ss->cursor_frame_callback);
ss->cursor_frame_callback = nullptr;
}

if (ss->cursor_surface) {
wl_surface_destroy(ss->cursor_surface);
ss->cursor_surface = nullptr;
}

if (ss->wl_pointer) {
wl_pointer_destroy(ss->wl_pointer);
ss->wl_pointer = nullptr;
}

if (ss->wp_relative_pointer) {
zwp_relative_pointer_v1_destroy(ss->wp_relative_pointer);
ss->wp_relative_pointer = nullptr;
}

if (ss->wp_confined_pointer) {
zwp_confined_pointer_v1_destroy(ss->wp_confined_pointer);
ss->wp_confined_pointer = nullptr;
}

if (ss->wp_locked_pointer) {
zwp_locked_pointer_v1_destroy(ss->wp_locked_pointer);
ss->wp_locked_pointer = nullptr;
}
}

// Keyboard handling.
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
if (!ss->wl_keyboard) {
ss->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
ERR_FAIL_NULL(ss->xkb_context);

ss->wl_keyboard = wl_seat_get_keyboard(wl_seat);
wl_keyboard_add_listener(ss->wl_keyboard, &wl_keyboard_listener, ss);
}
} else {
if (ss->xkb_context) {
xkb_context_unref(ss->xkb_context);
ss->xkb_context = nullptr;
}

if (ss->wl_keyboard) {
wl_keyboard_destroy(ss->wl_keyboard);
ss->wl_keyboard = nullptr;
}
}
}

void WaylandThread::_wl_seat_on_name(void *data, struct wl_seat *wl_seat, const char *name) {
}
77 changes: 77 additions & 0 deletions platform/linuxbsd/wayland/thread/core/surface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**************************************************************************/
/* surface.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "wayland/wayland_thread.h"

void WaylandThread::_wl_surface_on_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) {
if (!wl_output || !wl_proxy_is_godot((struct wl_proxy *)wl_output)) {
// This won't have the right data bound to it. Not worth it and would probably
// just break everything.
return;
}

WindowState *ws = (WindowState *)data;
ERR_FAIL_NULL(ws);

DEBUG_LOG_WAYLAND_THREAD(vformat("Window entered output %x.\n", (size_t)wl_output));

ws->wl_outputs.insert(wl_output);

// Workaround for buffer scaling as there's no guaranteed way of knowing the
// preferred scale.
// TODO: Skip this branch for newer `wl_surface`s once we add support for
// `wl_surface::preferred_buffer_scale`
if (ws->preferred_fractional_scale == 0) {
window_state_update_size(ws, ws->rect.size.width, ws->rect.size.height);
}
}

void WaylandThread::_wl_surface_on_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) {
if (!wl_output || !wl_proxy_is_godot((struct wl_proxy *)wl_output)) {
// This won't have the right data bound to it. Not worth it and would probably
// just break everything.
return;
}

WindowState *ws = (WindowState *)data;
ERR_FAIL_NULL(ws);

ws->wl_outputs.erase(wl_output);

DEBUG_LOG_WAYLAND_THREAD(vformat("Window left output %x.\n", (size_t)wl_output));
}

// TODO: Add support to this event.
void WaylandThread::_wl_surface_on_preferred_buffer_scale(void *data, struct wl_surface *wl_surface, int32_t factor) {
}

// TODO: Add support to this event.
void WaylandThread::_wl_surface_on_preferred_buffer_transform(void *data, struct wl_surface *wl_surface, uint32_t transform) {
}
Loading

0 comments on commit af00955

Please sign in to comment.