2019-11-21 05:16:53 +00:00
|
|
|
#define _POSIX_C_SOURCE 200112L
|
2020-01-02 07:23:39 +00:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
2019-11-21 05:16:53 +00:00
|
|
|
#include <assert.h>
|
2019-12-16 20:13:32 +00:00
|
|
|
#include <signal.h>
|
2019-11-21 05:16:53 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2019-12-31 01:50:22 +00:00
|
|
|
#include <pthread.h>
|
2020-01-02 07:23:39 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2019-12-31 06:50:49 +00:00
|
|
|
#include <sys/epoll.h>
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
#include <linux/input-event-codes.h>
|
|
|
|
|
2020-01-19 04:37:11 +00:00
|
|
|
#include <X11/extensions/XTest.h>
|
2020-01-17 09:57:39 +00:00
|
|
|
#include <xkbcommon/xkbcommon.h>
|
|
|
|
|
2019-11-21 05:16:53 +00:00
|
|
|
#include <wayland-server-core.h>
|
|
|
|
#include <wlr/backend.h>
|
|
|
|
#include <wlr/backend/headless.h>
|
|
|
|
#include <wlr/backend/multi.h>
|
|
|
|
#include <wlr/backend/libinput.h>
|
2020-01-02 07:23:39 +00:00
|
|
|
#include <wlr/interfaces/wlr_pointer.h>
|
2019-11-21 05:16:53 +00:00
|
|
|
#include <wlr/render/wlr_renderer.h>
|
|
|
|
#include <wlr/util/log.h>
|
2019-11-21 07:41:54 +00:00
|
|
|
|
|
|
|
#define C_SIDE
|
|
|
|
|
2020-01-23 05:50:01 +00:00
|
|
|
#include "steamcompmgr.hpp"
|
2019-11-21 05:16:53 +00:00
|
|
|
#include "wlserver.h"
|
2020-01-17 09:57:39 +00:00
|
|
|
#include "drm.hpp"
|
2019-11-21 07:41:54 +00:00
|
|
|
#include "main.hpp"
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-14 02:45:53 +00:00
|
|
|
#include "gpuvis_trace_utils.h"
|
|
|
|
|
2019-11-21 05:16:53 +00:00
|
|
|
struct wlserver_t wlserver;
|
|
|
|
|
2019-11-23 07:42:02 +00:00
|
|
|
Display *g_XWLDpy;
|
|
|
|
|
2020-01-23 06:15:22 +00:00
|
|
|
bool run = true;
|
2020-01-01 23:00:34 +00:00
|
|
|
|
2019-12-16 20:13:32 +00:00
|
|
|
void sig_handler(int signal)
|
|
|
|
{
|
|
|
|
wlr_log(WLR_DEBUG, "Received kill signal. Terminating!");
|
2020-01-01 23:00:34 +00:00
|
|
|
run = false;
|
2019-12-16 20:13:32 +00:00
|
|
|
}
|
|
|
|
|
2019-11-24 21:55:02 +00:00
|
|
|
void nudge_steamcompmgr(void)
|
2019-11-23 07:42:02 +00:00
|
|
|
{
|
|
|
|
static bool bHasNestedDisplay = false;
|
|
|
|
static XEvent XWLExposeEvent = {};
|
|
|
|
|
|
|
|
if ( bHasNestedDisplay == false )
|
|
|
|
{
|
|
|
|
g_XWLDpy = XOpenDisplay( wlserver.wlr.xwayland->display_name );
|
|
|
|
|
2019-11-24 21:55:02 +00:00
|
|
|
XWLExposeEvent.xclient.type = ClientMessage;
|
|
|
|
XWLExposeEvent.xclient.window = DefaultRootWindow( g_XWLDpy );
|
|
|
|
XWLExposeEvent.xclient.format = 32;
|
2019-11-23 07:42:02 +00:00
|
|
|
|
|
|
|
bHasNestedDisplay = true;
|
|
|
|
}
|
|
|
|
|
2019-11-24 21:55:02 +00:00
|
|
|
XSendEvent( g_XWLDpy , DefaultRootWindow( g_XWLDpy ), True, SubstructureRedirectMask, &XWLExposeEvent);
|
2019-11-23 07:42:02 +00:00
|
|
|
XFlush( g_XWLDpy );
|
|
|
|
}
|
|
|
|
|
2020-01-23 05:50:01 +00:00
|
|
|
const struct wlr_surface_role xwayland_surface_role;
|
|
|
|
|
2020-01-17 00:43:21 +00:00
|
|
|
void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) {
|
2019-11-23 06:58:07 +00:00
|
|
|
assert(wlr_surface->role == &xwayland_surface_role);
|
|
|
|
|
|
|
|
struct wlr_texture *tex = wlr_surface_get_texture( wlr_surface );
|
2020-01-17 00:43:21 +00:00
|
|
|
|
|
|
|
if ( tex == NULL )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2019-11-23 06:58:07 +00:00
|
|
|
|
|
|
|
struct wlr_dmabuf_attributes dmabuf_attribs = {};
|
|
|
|
bool result = False;
|
|
|
|
result = wlr_texture_to_dmabuf( tex, &dmabuf_attribs );
|
|
|
|
|
2020-01-14 06:09:55 +00:00
|
|
|
assert( result == true );
|
|
|
|
if ( result == false || dmabuf_attribs.fd[0] == -1 )
|
2019-11-23 06:58:07 +00:00
|
|
|
{
|
2020-01-14 06:09:55 +00:00
|
|
|
struct timespec now;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
|
|
|
|
wlr_surface_send_frame_done( wlr_surface, &now );
|
|
|
|
return;
|
2019-11-23 06:58:07 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 02:45:53 +00:00
|
|
|
gpuvis_trace_printf( "xwayland_surface_role_commit wlr_surface %p\n", wlr_surface );
|
|
|
|
|
2019-11-23 06:58:07 +00:00
|
|
|
wayland_PushSurface( wlr_surface, &dmabuf_attribs );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xwayland_surface_role_precommit(struct wlr_surface *wlr_surface) {
|
|
|
|
assert(wlr_surface->role == &xwayland_surface_role);
|
|
|
|
struct wlr_xwayland_surface *surface = wlr_surface->role_data;
|
|
|
|
if (surface == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct wlr_surface_role xwayland_surface_role = {
|
|
|
|
.name = "wlr_xwayland_surface",
|
|
|
|
.commit = xwayland_surface_role_commit,
|
|
|
|
.precommit = xwayland_surface_role_precommit,
|
|
|
|
};
|
|
|
|
|
2019-12-31 09:52:32 +00:00
|
|
|
static void xwayland_ready(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
startSteamCompMgr();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wl_listener xwayland_ready_listener = { .notify = xwayland_ready };
|
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
static void wlserver_handle_modifiers(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_keyboard *keyboard = wl_container_of( listener, keyboard, modifiers );
|
|
|
|
|
|
|
|
wlr_seat_set_keyboard( wlserver.wlr.seat, keyboard->device );
|
|
|
|
wlr_seat_keyboard_notify_modifiers( wlserver.wlr.seat, &keyboard->device->keyboard->modifiers );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_handle_key(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_keyboard *keyboard = wl_container_of( listener, keyboard, key );
|
|
|
|
struct wlr_event_keyboard_key *event = data;
|
|
|
|
|
|
|
|
wlr_seat_set_keyboard( wlserver.wlr.seat, keyboard->device);
|
|
|
|
wlr_seat_keyboard_notify_key( wlserver.wlr.seat, event->time_msec, event->keycode, event->state );
|
|
|
|
}
|
|
|
|
|
2020-01-19 04:37:11 +00:00
|
|
|
static void wlserver_movecursor( int x, int y )
|
|
|
|
{
|
|
|
|
wlserver.mouse_surface_cursorx += x;
|
|
|
|
|
|
|
|
if ( wlserver.mouse_surface_cursorx > wlserver.mouse_focus_surface->current.width - 1 )
|
|
|
|
{
|
|
|
|
wlserver.mouse_surface_cursorx = wlserver.mouse_focus_surface->current.width - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wlserver.mouse_surface_cursorx < 0 )
|
|
|
|
{
|
|
|
|
wlserver.mouse_surface_cursorx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
wlserver.mouse_surface_cursory += y;
|
|
|
|
|
|
|
|
if ( wlserver.mouse_surface_cursory > wlserver.mouse_focus_surface->current.height - 1 )
|
|
|
|
{
|
|
|
|
wlserver.mouse_surface_cursory = wlserver.mouse_focus_surface->current.height - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wlserver.mouse_surface_cursory < 0 )
|
|
|
|
{
|
|
|
|
wlserver.mouse_surface_cursory = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
static void wlserver_handle_pointer_motion(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_pointer *pointer = wl_container_of( listener, pointer, motion );
|
|
|
|
struct wlr_event_pointer_motion *event = data;
|
|
|
|
|
2020-01-19 04:37:11 +00:00
|
|
|
if ( wlserver.mouse_focus_surface != NULL )
|
|
|
|
{
|
|
|
|
wlserver_movecursor( event->unaccel_dx, event->unaccel_dy );
|
2020-01-17 09:57:39 +00:00
|
|
|
|
2020-01-19 04:37:11 +00:00
|
|
|
wlr_seat_pointer_notify_motion( wlserver.wlr.seat, event->time_msec, wlserver.mouse_surface_cursorx, wlserver.mouse_surface_cursory );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
2020-01-17 09:57:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_handle_pointer_button(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_pointer *pointer = wl_container_of( listener, pointer, button );
|
|
|
|
struct wlr_event_pointer_button *event = data;
|
|
|
|
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, event->time_msec, event->button, event->state );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_handle_touch_down(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_touch *touch = wl_container_of( listener, touch, down );
|
|
|
|
struct wlr_event_touch_down *event = data;
|
|
|
|
|
|
|
|
if ( wlserver.mouse_focus_surface != NULL )
|
|
|
|
{
|
|
|
|
double x = g_bRotated ? event->y : event->x;
|
|
|
|
double y = g_bRotated ? 1.0 - event->x : event->y;
|
|
|
|
|
|
|
|
wlserver.touchdown_x = x * wlserver.mouse_focus_surface->current.width;
|
|
|
|
wlserver.touchdown_y = y * wlserver.mouse_focus_surface->current.height;
|
|
|
|
|
|
|
|
wlserver.mouse_surface_cursorx = x * wlserver.mouse_focus_surface->current.width;
|
|
|
|
wlserver.mouse_surface_cursory = y * wlserver.mouse_focus_surface->current.height;
|
2020-01-17 11:27:55 +00:00
|
|
|
|
|
|
|
wlserver.dragging = false;
|
|
|
|
wlserver.candrag = true;
|
2020-01-17 09:57:39 +00:00
|
|
|
|
|
|
|
wlserver.touchdown_time_ms = get_time_in_milliseconds();
|
2020-01-17 11:27:55 +00:00
|
|
|
|
|
|
|
wlr_seat_pointer_notify_motion( wlserver.wlr.seat, event->time_msec, wlserver.mouse_surface_cursorx, wlserver.mouse_surface_cursory );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
2020-01-17 09:57:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_handle_touch_up(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_touch *touch = wl_container_of( listener, touch, down );
|
|
|
|
struct wlr_event_touch_up *event = data;
|
|
|
|
|
|
|
|
if ( wlserver.mouse_focus_surface != NULL )
|
|
|
|
{
|
|
|
|
unsigned int now = get_time_in_milliseconds();
|
|
|
|
|
|
|
|
if ( fabs( wlserver.mouse_surface_cursorx - wlserver.touchdown_x ) < 50 &&
|
|
|
|
fabs( wlserver.mouse_surface_cursory - wlserver.touchdown_y ) < 50 &&
|
2020-01-17 11:27:55 +00:00
|
|
|
now - wlserver.touchdown_time_ms < 100 )
|
2020-01-17 09:57:39 +00:00
|
|
|
{
|
|
|
|
wlr_seat_pointer_notify_motion( wlserver.wlr.seat, event->time_msec, wlserver.touchdown_x, wlserver.touchdown_y );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
2020-01-17 11:27:55 +00:00
|
|
|
|
|
|
|
if ( wlserver.dragging == true )
|
|
|
|
{
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
|
|
|
|
|
|
|
wlserver.dragging = false;
|
2020-01-17 09:57:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_handle_touch_motion(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlserver_touch *touch = wl_container_of( listener, touch, motion );
|
|
|
|
struct wlr_event_touch_motion *event = data;
|
|
|
|
|
|
|
|
if ( wlserver.mouse_focus_surface != NULL )
|
|
|
|
{
|
2020-01-17 11:27:55 +00:00
|
|
|
unsigned int now = get_time_in_milliseconds();
|
|
|
|
unsigned int sincedown = now - wlserver.touchdown_time_ms;
|
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
double x = g_bRotated ? event->y : event->x;
|
|
|
|
double y = g_bRotated ? 1.0 - event->x : event->y;
|
2020-01-17 11:27:55 +00:00
|
|
|
|
|
|
|
if ( sincedown > 200 || wlserver.candrag == false )
|
|
|
|
{
|
|
|
|
if ( wlserver.candrag == true )
|
|
|
|
{
|
|
|
|
wlserver.candrag = false;
|
|
|
|
wlserver.dragging = true;
|
|
|
|
|
|
|
|
wlr_seat_pointer_notify_motion( wlserver.wlr.seat, event->time_msec, wlserver.touchdown_x, wlserver.touchdown_y );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
|
|
|
wlserver.mouse_surface_cursorx = x * wlserver.mouse_focus_surface->current.width;
|
|
|
|
wlserver.mouse_surface_cursory = y * wlserver.mouse_focus_surface->current.height;
|
|
|
|
|
|
|
|
wlr_seat_pointer_notify_motion( wlserver.wlr.seat, event->time_msec, wlserver.mouse_surface_cursorx, wlserver.mouse_surface_cursory );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double posx = x * wlserver.mouse_focus_surface->current.width;
|
|
|
|
double posy = y * wlserver.mouse_focus_surface->current.height;
|
|
|
|
|
|
|
|
if ( fabs( posx - wlserver.touchdown_x ) > 100 || fabs( posy - wlserver.touchdown_y ) > 100 )
|
|
|
|
{
|
|
|
|
wlserver.candrag = false;
|
|
|
|
}
|
|
|
|
}
|
2020-01-17 09:57:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wlserver_new_input(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct wlr_input_device *device = data;
|
|
|
|
|
|
|
|
switch ( device->type )
|
|
|
|
{
|
|
|
|
case WLR_INPUT_DEVICE_KEYBOARD:
|
|
|
|
{
|
|
|
|
struct wlserver_keyboard *pKB = calloc( 1, sizeof( struct wlserver_keyboard ) );
|
|
|
|
|
|
|
|
pKB->device = device;
|
|
|
|
|
|
|
|
struct xkb_rule_names rules = { 0 };
|
|
|
|
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
|
|
struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
|
|
|
|
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
|
|
|
|
|
|
wlr_keyboard_set_keymap(device->keyboard, keymap);
|
|
|
|
xkb_keymap_unref(keymap);
|
|
|
|
xkb_context_unref(context);
|
|
|
|
wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
|
|
|
|
|
|
|
|
pKB->modifiers.notify = wlserver_handle_modifiers;
|
|
|
|
wl_signal_add( &device->keyboard->events.modifiers, &pKB->modifiers );
|
|
|
|
|
|
|
|
pKB->key.notify = wlserver_handle_key;
|
|
|
|
wl_signal_add( &device->keyboard->events.key, &pKB->key );
|
|
|
|
|
|
|
|
wlr_seat_set_keyboard( wlserver.wlr.seat, device );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WLR_INPUT_DEVICE_POINTER:
|
|
|
|
{
|
|
|
|
struct wlserver_pointer *pointer = calloc( 1, sizeof( struct wlserver_pointer ) );
|
|
|
|
|
|
|
|
pointer->device = device;
|
|
|
|
|
|
|
|
pointer->motion.notify = wlserver_handle_pointer_motion;
|
|
|
|
wl_signal_add( &device->pointer->events.motion, &pointer->motion );
|
|
|
|
pointer->button.notify = wlserver_handle_pointer_button;
|
|
|
|
wl_signal_add( &device->pointer->events.button, &pointer->button );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WLR_INPUT_DEVICE_TOUCH:
|
|
|
|
{
|
|
|
|
struct wlserver_touch *touch = calloc( 1, sizeof( struct wlserver_touch ) );
|
|
|
|
|
|
|
|
touch->device = device;
|
|
|
|
|
|
|
|
touch->down.notify = wlserver_handle_touch_down;
|
|
|
|
wl_signal_add( &device->touch->events.down, &touch->down );
|
|
|
|
touch->up.notify = wlserver_handle_touch_up;
|
|
|
|
wl_signal_add( &device->touch->events.up, &touch->up );
|
|
|
|
touch->motion.notify = wlserver_handle_touch_motion;
|
|
|
|
wl_signal_add( &device->touch->events.motion, &touch->motion );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wl_listener new_input_listener = { .notify = wlserver_new_input };
|
|
|
|
|
2020-01-02 07:23:39 +00:00
|
|
|
int wlserver_init(int argc, char **argv, bool bIsNested) {
|
|
|
|
bool bIsDRM = bIsNested == false;
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
wlr_log_init(WLR_DEBUG, NULL);
|
|
|
|
wlserver.wl_display = wl_display_create();
|
2019-12-16 20:13:32 +00:00
|
|
|
|
|
|
|
signal(SIGTERM, sig_handler);
|
|
|
|
signal(SIGINT, sig_handler);
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
wlserver.wlr.session = ( bIsDRM == True ) ? wlr_session_create(wlserver.wl_display) : NULL;
|
|
|
|
|
2019-12-31 06:50:49 +00:00
|
|
|
wlserver.wl_event_loop = wl_display_get_event_loop(wlserver.wl_display);
|
|
|
|
wlserver.wl_event_loop_fd = wl_event_loop_get_fd( wlserver.wl_event_loop );
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.wlr.multi_backend = wlr_multi_backend_create(wlserver.wl_display);
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
assert( wlserver.wl_display && wlserver.wl_event_loop && wlserver.wlr.multi_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
assert( !bIsDRM || wlserver.wlr.session );
|
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.wlr.headless_backend = wlr_headless_backend_create( wlserver.wl_display, NULL );
|
|
|
|
if ( wlserver.wlr.headless_backend == NULL )
|
|
|
|
{
|
2019-11-21 05:16:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-01-17 09:57:39 +00:00
|
|
|
wlr_multi_backend_add( wlserver.wlr.multi_backend, wlserver.wlr.headless_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.wlr.output = wlr_headless_add_output( wlserver.wlr.headless_backend, g_nNestedWidth, g_nNestedHeight );
|
2019-11-21 07:41:54 +00:00
|
|
|
wlr_output_set_custom_mode( wlserver.wlr.output, g_nNestedWidth, g_nNestedHeight, g_nNestedRefresh * 1000 );
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
wlr_output_create_global( wlserver.wlr.output );
|
|
|
|
|
|
|
|
if ( bIsDRM == True )
|
|
|
|
{
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.wlr.libinput_backend = wlr_libinput_backend_create( wlserver.wl_display, wlserver.wlr.session );
|
|
|
|
if ( wlserver.wlr.libinput_backend == NULL)
|
|
|
|
{
|
2019-11-21 05:16:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-01-17 09:57:39 +00:00
|
|
|
wl_signal_add( &wlserver.wlr.libinput_backend->events.new_input, &new_input_listener );
|
|
|
|
wlr_multi_backend_add( wlserver.wlr.multi_backend, wlserver.wlr.libinput_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
}
|
2020-01-18 23:10:14 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
wl_signal_add( &wlserver.wlr.headless_backend->events.new_input, &new_input_listener );
|
|
|
|
wlr_headless_add_input_device( wlserver.wlr.headless_backend, WLR_INPUT_DEVICE_KEYBOARD );
|
|
|
|
}
|
2019-11-21 05:16:53 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.wlr.renderer = wlr_backend_get_renderer( wlserver.wlr.multi_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
assert(wlserver.wlr.renderer);
|
|
|
|
|
|
|
|
wlr_renderer_init_wl_display(wlserver.wlr.renderer, wlserver.wl_display);
|
|
|
|
|
|
|
|
wlserver.wlr.compositor = wlr_compositor_create(wlserver.wl_display, wlserver.wlr.renderer);
|
|
|
|
|
|
|
|
wlserver.wlr.xwayland = wlr_xwayland_create(wlserver.wl_display, wlserver.wlr.compositor, False);
|
|
|
|
|
|
|
|
setenv("DISPLAY", wlserver.wlr.xwayland->display_name, true);
|
|
|
|
|
|
|
|
const char *socket = wl_display_add_socket_auto(wlserver.wl_display);
|
2020-01-17 09:57:39 +00:00
|
|
|
if (!socket)
|
|
|
|
{
|
2019-11-21 05:16:53 +00:00
|
|
|
wlr_log_errno(WLR_ERROR, "Unable to open wayland socket");
|
2020-01-17 09:57:39 +00:00
|
|
|
wlr_backend_destroy( wlserver.wlr.multi_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-01-17 09:57:39 +00:00
|
|
|
|
|
|
|
wlserver.wlr.seat = wlr_seat_create(wlserver.wl_display, "seat0");
|
|
|
|
wlr_seat_set_capabilities( wlserver.wlr.seat, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD );
|
|
|
|
wlr_xwayland_set_seat(wlserver.wlr.xwayland, wlserver.wlr.seat);
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
wlr_log(WLR_INFO, "Running compositor on wayland display '%s'", socket);
|
|
|
|
setenv("_WAYLAND_DISPLAY", socket, true);
|
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
if (!wlr_backend_start( wlserver.wlr.multi_backend ))
|
|
|
|
{
|
2019-11-21 05:16:53 +00:00
|
|
|
wlr_log(WLR_ERROR, "Failed to start backend");
|
2020-01-17 09:57:39 +00:00
|
|
|
wlr_backend_destroy( wlserver.wlr.multi_backend );
|
2019-11-21 05:16:53 +00:00
|
|
|
wl_display_destroy(wlserver.wl_display);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
setenv("WAYLAND_DISPLAY", socket, true);
|
2019-12-31 09:52:32 +00:00
|
|
|
|
|
|
|
wl_signal_add(&wlserver.wlr.xwayland->events.ready, &xwayland_ready_listener);
|
2019-11-21 05:16:53 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-12-31 01:50:22 +00:00
|
|
|
pthread_mutex_t waylock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
void wlserver_lock(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&waylock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wlserver_unlock(void)
|
|
|
|
{
|
2020-01-01 04:54:32 +00:00
|
|
|
wl_display_flush_clients(wlserver.wl_display);
|
2019-12-31 01:50:22 +00:00
|
|
|
pthread_mutex_unlock(&waylock);
|
|
|
|
}
|
|
|
|
|
2019-11-23 06:58:07 +00:00
|
|
|
int wlserver_run(void)
|
2019-11-21 05:16:53 +00:00
|
|
|
{
|
2019-12-31 06:50:49 +00:00
|
|
|
int epoll_fd = epoll_create( 1 );
|
|
|
|
struct epoll_event ev;
|
|
|
|
struct epoll_event events[128];
|
|
|
|
int n;
|
|
|
|
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
|
|
|
|
if ( epoll_fd == -1 ||
|
|
|
|
epoll_ctl( epoll_fd, EPOLL_CTL_ADD, wlserver.wl_event_loop_fd, &ev ) == -1 )
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-01-01 23:00:34 +00:00
|
|
|
while ( run )
|
2019-12-31 01:50:22 +00:00
|
|
|
{
|
2019-12-31 06:50:49 +00:00
|
|
|
n = epoll_wait( epoll_fd, events, 128, -1 );
|
|
|
|
if ( n == -1 )
|
|
|
|
{
|
2020-01-16 01:48:20 +00:00
|
|
|
if ( errno == EINTR )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2019-12-31 01:50:22 +00:00
|
|
|
}
|
2020-01-16 01:48:20 +00:00
|
|
|
|
2019-12-31 06:50:49 +00:00
|
|
|
// We have wayland stuff to do, do it while locked
|
|
|
|
wlserver_lock();
|
|
|
|
|
|
|
|
for ( int i = 0; i < n; i++ )
|
|
|
|
{
|
|
|
|
wl_display_flush_clients(wlserver.wl_display);
|
|
|
|
int ret = wl_event_loop_dispatch(wlserver.wl_event_loop, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
wlserver_unlock();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wlserver_unlock();
|
2019-12-31 01:50:22 +00:00
|
|
|
}
|
|
|
|
|
2019-11-21 05:16:53 +00:00
|
|
|
// We need to shutdown Xwayland before disconnecting all clients, otherwise
|
|
|
|
// wlroots will restart it automatically.
|
|
|
|
wlr_xwayland_destroy(wlserver.wlr.xwayland);
|
|
|
|
wl_display_destroy_clients(wlserver.wl_display);
|
|
|
|
wl_display_destroy(wlserver.wl_display);
|
|
|
|
return 0;
|
|
|
|
}
|
2020-01-02 07:23:39 +00:00
|
|
|
|
2020-01-17 09:57:39 +00:00
|
|
|
void wlserver_keyboardfocus( struct wlr_surface *surface )
|
|
|
|
{
|
|
|
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard( wlserver.wlr.seat );
|
|
|
|
if ( keyboard != NULL )
|
|
|
|
{
|
|
|
|
wlr_seat_keyboard_notify_enter( wlserver.wlr.seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-18 23:10:14 +00:00
|
|
|
void wlserver_key( uint32_t key, bool press, uint32_t time )
|
|
|
|
{
|
|
|
|
wlr_seat_keyboard_notify_key( wlserver.wlr.seat, time, key, press );
|
|
|
|
}
|
|
|
|
|
2020-01-02 07:23:39 +00:00
|
|
|
void wlserver_mousefocus( struct wlr_surface *wlrsurface )
|
|
|
|
{
|
2020-01-17 09:57:39 +00:00
|
|
|
wlserver.mouse_focus_surface = wlrsurface;
|
|
|
|
wlserver.mouse_surface_cursorx = wlrsurface->current.width / 2.0;
|
|
|
|
wlserver.mouse_surface_cursory = wlrsurface->current.height / 2.0;
|
|
|
|
wlr_seat_pointer_notify_enter( wlserver.wlr.seat, wlrsurface, wlserver.mouse_surface_cursorx, wlserver.mouse_surface_cursory );
|
2020-01-02 07:23:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void wlserver_mousemotion( int x, int y, uint32_t time )
|
|
|
|
{
|
2020-01-19 04:37:11 +00:00
|
|
|
if ( g_XWLDpy != NULL )
|
|
|
|
{
|
|
|
|
XTestFakeRelativeMotionEvent( g_XWLDpy, x, y, CurrentTime );
|
|
|
|
XFlush( g_XWLDpy );
|
|
|
|
}
|
2020-01-02 07:23:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void wlserver_mousebutton( int button, bool press, uint32_t time )
|
|
|
|
{
|
|
|
|
wlr_seat_pointer_notify_button( wlserver.wlr.seat, time, button, press ? WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED );
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
|
|
|
|
|
|
|
void wlserver_mousewheel( int x, int y, uint32_t time )
|
|
|
|
{
|
|
|
|
if ( x != 0 )
|
|
|
|
{
|
|
|
|
wlr_seat_pointer_notify_axis( wlserver.wlr.seat, time, WLR_AXIS_ORIENTATION_HORIZONTAL, x, x, WLR_AXIS_SOURCE_WHEEL );
|
|
|
|
}
|
|
|
|
if ( y != 0 )
|
|
|
|
{
|
|
|
|
wlr_seat_pointer_notify_axis( wlserver.wlr.seat, time, WLR_AXIS_ORIENTATION_VERTICAL, y, y, WLR_AXIS_SOURCE_WHEEL );
|
|
|
|
}
|
|
|
|
wlr_seat_pointer_notify_frame( wlserver.wlr.seat );
|
|
|
|
}
|
2020-01-23 05:50:01 +00:00
|
|
|
|
|
|
|
void wlserver_send_frame_done( struct wlr_surface *surf, const struct timespec *when )
|
|
|
|
{
|
|
|
|
wlr_surface_send_frame_done( surf, when );
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wlr_surface *wlserver_get_surface( long surfaceID )
|
|
|
|
{
|
|
|
|
struct wlr_surface *ret = NULL;
|
|
|
|
|
|
|
|
struct wl_resource *resource = wl_client_get_object(wlserver.wlr.xwayland->client, surfaceID);
|
|
|
|
if (resource) {
|
|
|
|
ret = wlr_surface_from_resource(resource);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !wlr_surface_set_role(ret, &xwayland_surface_role, NULL, NULL, 0 ) )
|
|
|
|
{
|
|
|
|
fprintf (stderr, "Failed to set xwayland surface role");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *wlserver_get_nested_display( void )
|
|
|
|
{
|
|
|
|
return wlserver.wlr.xwayland->display_name;
|
|
|
|
}
|