478 lines
13 KiB
C
478 lines
13 KiB
C
/*
|
|
* Copyright © 2011-2014 Intel Corporation
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
* and its documentation for any purpose is hereby granted without
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
* and that both that copyright notice and this permission notice
|
|
* appear in supporting documentation, and that the name of the
|
|
* copyright holders not be used in advertising or publicity
|
|
* pertaining to distribution of the software without specific,
|
|
* written prior permission. The copyright holders make no
|
|
* representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied
|
|
* warranty.
|
|
*
|
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include <xwayland-config.h>
|
|
|
|
#if !defined(WIN32)
|
|
#include <sys/resource.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xfuncproto.h>
|
|
|
|
#include "dix/dix_priv.h"
|
|
#include "dix/screenint_priv.h"
|
|
#include "dix/selection_priv.h"
|
|
#include "os/auth.h"
|
|
#include "os/cmdline.h"
|
|
#include "os/ddx_priv.h"
|
|
#include "os/osdep.h"
|
|
#include "os/xserver_poll.h"
|
|
|
|
#include <micmap.h>
|
|
#include <misyncshm.h>
|
|
#include <compositeext.h>
|
|
#include <compint.h>
|
|
#include <glx_extinit.h>
|
|
#include <opaque.h>
|
|
#include <os.h>
|
|
#include "ddx.h"
|
|
#include <propertyst.h>
|
|
#include <version-config.h>
|
|
|
|
#include "xwayland-screen.h"
|
|
#include "xwayland-vidmode.h"
|
|
|
|
#ifdef XF86VIDMODE
|
|
#include <X11/extensions/xf86vmproto.h>
|
|
Bool noXFree86VidModeExtension = FALSE;
|
|
#endif
|
|
|
|
void
|
|
ddxGiveUp(enum ExitCode error)
|
|
{
|
|
}
|
|
|
|
void
|
|
OsVendorInit(void)
|
|
{
|
|
if (serverGeneration == 1)
|
|
ForceClockId(CLOCK_MONOTONIC);
|
|
}
|
|
|
|
void
|
|
OsVendorFatalError(const char *f, va_list args)
|
|
{
|
|
}
|
|
|
|
#if defined(DDXBEFORERESET)
|
|
void
|
|
ddxBeforeReset(void)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if INPUTTHREAD
|
|
/** This function is called in Xserver/os/inputthread.c when starting
|
|
the input thread. */
|
|
void
|
|
ddxInputThreadInit(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
ddxUseMsg(void)
|
|
{
|
|
ErrorF("-rootless run rootless, requires wm support\n");
|
|
ErrorF("-fullscreen run fullscreen when rootful\n");
|
|
ErrorF("-geometry WxH set Xwayland window size when rootful\n");
|
|
ErrorF("-hidpi adjust to output scale when rootful\n");
|
|
ErrorF("-host-grab disable host keyboard shortcuts when rootful\n");
|
|
ErrorF("-nokeymap ignore keymap from the Wayland compositor\n");
|
|
ErrorF("-output specify which output to use for fullscreen when rootful\n");
|
|
ErrorF("-wm fd create X client for wm on given fd\n");
|
|
ErrorF("-initfd fd add given fd as a listen socket for initialization clients\n");
|
|
ErrorF("-listenfd fd add given fd as a listen socket\n");
|
|
ErrorF("-listen fd deprecated, use \"-listenfd\" instead\n");
|
|
ErrorF("-shm use shared memory for passing buffers\n");
|
|
#ifdef XWL_HAS_GLAMOR
|
|
ErrorF("-glamor [gl|es|off] use given API for Glamor acceleration. Incompatible with -shm option\n");
|
|
#endif
|
|
ErrorF("-verbose [n] verbose startup messages\n");
|
|
ErrorF("-version show the server version and exit\n");
|
|
ErrorF("-noTouchPointerEmulation disable touch pointer emulation\n");
|
|
ErrorF("-force-xrandr-emulation force non-native modes to be exposed when viewporter is not exposed by the compositor\n");
|
|
#ifdef XWL_HAS_LIBDECOR
|
|
ErrorF("-decorate add decorations to Xwayland when rootful\n");
|
|
#endif
|
|
#ifdef XWL_HAS_EI_PORTAL
|
|
ErrorF("-enable-ei-portal use the XDG portal for input emulation\n");
|
|
#endif
|
|
}
|
|
|
|
static int init_fd = -1;
|
|
static int wm_fd = -1;
|
|
static int listen_fds[5] = { -1, -1, -1, -1, -1 };
|
|
static int listen_fd_count = 0;
|
|
static int verbosity = 0;
|
|
|
|
static void
|
|
xwl_show_version(void)
|
|
{
|
|
ErrorF("%s Xwayland %s (%d)\n", VENDOR_NAME, VENDOR_MAN_VERSION, VENDOR_RELEASE);
|
|
ErrorF("X Protocol Version %d, Revision %d\n", X_PROTOCOL, X_PROTOCOL_REVISION);
|
|
#if defined(BUILDERSTRING)
|
|
if (strlen(BUILDERSTRING))
|
|
ErrorF("%s\n", BUILDERSTRING);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
try_raising_nofile_limit(void)
|
|
{
|
|
#ifdef RLIMIT_NOFILE
|
|
struct rlimit rlim;
|
|
|
|
/* Only fiddle with the limit if not set explicitly from the command line */
|
|
if (limitNoFile >= 0)
|
|
return;
|
|
|
|
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
|
ErrorF("Failed to get the current nofile limit: %s\n", strerror(errno));
|
|
return;
|
|
}
|
|
|
|
rlim.rlim_cur = rlim.rlim_max;
|
|
|
|
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
|
ErrorF("Failed to set the current nofile limit: %s\n", strerror(errno));
|
|
return;
|
|
}
|
|
|
|
LogMessageVerb(X_INFO, 3, "Raising the file descriptors limit to %llu\n",
|
|
(long long unsigned int) rlim.rlim_max);
|
|
#endif /* RLIMIT_NOFILE */
|
|
}
|
|
|
|
static void
|
|
xwl_add_listen_fd(int argc, char *argv[], int i)
|
|
{
|
|
NoListenAll = TRUE;
|
|
if (listen_fd_count == ARRAY_SIZE(listen_fds))
|
|
FatalError("Too many -listen arguments given, max is %zu\n",
|
|
ARRAY_SIZE(listen_fds));
|
|
|
|
listen_fds[listen_fd_count++] = atoi(argv[i + 1]);
|
|
}
|
|
|
|
int
|
|
ddxProcessArgument(int argc, char *argv[], int i)
|
|
{
|
|
if (strcmp(argv[i], "-rootless") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-listen") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
|
|
/* Not an FD */
|
|
if (!isdigit(*argv[i + 1]))
|
|
return 0;
|
|
|
|
LogMessageVerb(X_WARNING, 0, "Option \"-listen\" for file descriptors is deprecated\n"
|
|
"Please use \"-listenfd\" instead.\n");
|
|
|
|
xwl_add_listen_fd (argc, argv, i);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-listenfd") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
|
|
xwl_add_listen_fd (argc, argv, i);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-wm") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
wm_fd = atoi(argv[i + 1]);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-initfd") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
init_fd = atoi(argv[i + 1]);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-shm") == 0) {
|
|
return 1;
|
|
}
|
|
#ifdef XWL_HAS_GLAMOR
|
|
else if (strcmp(argv[i], "-glamor") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
/* Only check here, actual work inside xwayland-screen.c */
|
|
return 2;
|
|
}
|
|
#endif
|
|
else if (strcmp(argv[i], "-verbose") == 0) {
|
|
if (++i < argc && argv[i]) {
|
|
char *end;
|
|
long val;
|
|
|
|
val = strtol(argv[i], &end, 0);
|
|
if (*end == '\0') {
|
|
verbosity = val;
|
|
LogSetParameter(XLOG_VERBOSITY, verbosity);
|
|
return 2;
|
|
}
|
|
}
|
|
LogSetParameter(XLOG_VERBOSITY, ++verbosity);
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-version") == 0) {
|
|
xwl_show_version();
|
|
exit(0);
|
|
}
|
|
else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) {
|
|
touchEmulatePointer = FALSE;
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-force-xrandr-emulation") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-geometry") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-fullscreen") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-host-grab") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-decorate") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-enable-ei-portal") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-output") == 0) {
|
|
CHECK_FOR_REQUIRED_ARGUMENTS(1);
|
|
return 2;
|
|
}
|
|
else if (strcmp(argv[i], "-nokeymap") == 0) {
|
|
return 1;
|
|
}
|
|
else if (strcmp(argv[i], "-hidpi") == 0) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static CARD32
|
|
add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
|
|
{
|
|
if (!AddClientOnOpenFD(wm_fd))
|
|
FatalError("Failed to add wm client\n");
|
|
|
|
TimerFree(timer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
listen_on_fds(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < listen_fd_count; i++)
|
|
ListenOnOpenFD(listen_fds[i], FALSE);
|
|
}
|
|
|
|
static void
|
|
wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
|
|
{
|
|
SelectionInfoRec *info = arg;
|
|
struct xwl_screen *xwl_screen = data;
|
|
static const char atom_name[] = "WM_S0";
|
|
static Atom atom_wm_s0;
|
|
|
|
if (atom_wm_s0 == None)
|
|
atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
|
|
if (info->selection->selection != atom_wm_s0 ||
|
|
info->kind != SelectionSetOwner)
|
|
return;
|
|
|
|
listen_on_fds();
|
|
|
|
DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
|
|
}
|
|
|
|
static void _X_ATTRIBUTE_PRINTF(1, 0)
|
|
xwl_log_handler(const char *format, va_list args)
|
|
{
|
|
char msg[256];
|
|
|
|
vsnprintf(msg, sizeof msg, format, args);
|
|
ErrorF("XWAYLAND: %s", msg);
|
|
}
|
|
|
|
#ifdef XWL_HAS_XWAYLAND_EXTENSION
|
|
#include <X11/extensions/xwaylandproto.h>
|
|
|
|
Bool noXwaylandExtension = FALSE;
|
|
|
|
static int
|
|
ProcXwlQueryVersion(ClientPtr client)
|
|
{
|
|
xXwlQueryVersionReply reply;
|
|
int major, minor;
|
|
|
|
REQUEST(xXwlQueryVersionReq);
|
|
REQUEST_SIZE_MATCH(xXwlQueryVersionReq);
|
|
|
|
if (version_compare(stuff->majorVersion, stuff->minorVersion,
|
|
XWAYLAND_EXTENSION_MAJOR,
|
|
XWAYLAND_EXTENSION_MINOR) < 0) {
|
|
major = stuff->majorVersion;
|
|
minor = stuff->minorVersion;
|
|
} else {
|
|
major = XWAYLAND_EXTENSION_MAJOR;
|
|
minor = XWAYLAND_EXTENSION_MINOR;
|
|
}
|
|
|
|
reply = (xXwlQueryVersionReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = 0,
|
|
.majorVersion = major,
|
|
.minorVersion = minor,
|
|
};
|
|
|
|
if (client->swapped) {
|
|
swaps(&reply.sequenceNumber);
|
|
swapl(&reply.length);
|
|
swaps(&reply.majorVersion);
|
|
swaps(&reply.minorVersion);
|
|
}
|
|
|
|
WriteReplyToClient(client, sizeof(reply), &reply);
|
|
return Success;
|
|
}
|
|
|
|
static int _X_COLD
|
|
SProcXwlQueryVersion(ClientPtr client)
|
|
{
|
|
REQUEST(xXwlQueryVersionReq);
|
|
REQUEST_AT_LEAST_SIZE(xXwlQueryVersionReq);
|
|
swaps(&stuff->majorVersion);
|
|
swaps(&stuff->minorVersion);
|
|
|
|
return ProcXwlQueryVersion(client);
|
|
}
|
|
|
|
static int
|
|
ProcXwaylandDispatch(ClientPtr client)
|
|
{
|
|
REQUEST(xReq);
|
|
|
|
switch (stuff->data) {
|
|
case X_XwlQueryVersion:
|
|
return ProcXwlQueryVersion(client);
|
|
}
|
|
return BadRequest;
|
|
}
|
|
|
|
static int
|
|
SProcXwaylandDispatch(ClientPtr client)
|
|
{
|
|
REQUEST(xReq);
|
|
|
|
switch (stuff->data) {
|
|
case X_XwlQueryVersion:
|
|
return SProcXwlQueryVersion(client);
|
|
}
|
|
return BadRequest;
|
|
}
|
|
|
|
static void
|
|
xwlExtensionInit(void)
|
|
{
|
|
AddExtension(XWAYLAND_EXTENSION_NAME,
|
|
XwlNumberEvents, XwlNumberErrors,
|
|
ProcXwaylandDispatch, SProcXwaylandDispatch,
|
|
NULL, StandardMinorOpcode);
|
|
}
|
|
|
|
#endif
|
|
|
|
static const ExtensionModule xwayland_extensions[] = {
|
|
#ifdef XF86VIDMODE
|
|
{ xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
|
|
#endif
|
|
#ifdef XWL_HAS_XWAYLAND_EXTENSION
|
|
{ xwlExtensionInit, XWAYLAND_EXTENSION_NAME, &noXwaylandExtension },
|
|
#endif
|
|
};
|
|
|
|
void
|
|
InitOutput(ScreenInfo * screen_info, int argc, char **argv)
|
|
{
|
|
int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
|
|
int bpp[] = { 1, 8, 8, 16, 16, 32, 32 };
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(depths); i++) {
|
|
screen_info->formats[i].depth = depths[i];
|
|
screen_info->formats[i].bitsPerPixel = bpp[i];
|
|
screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
|
|
}
|
|
|
|
screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
|
|
screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
|
|
screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
|
|
screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
|
|
screen_info->numPixmapFormats = ARRAY_SIZE(depths);
|
|
|
|
if (serverGeneration == 1) {
|
|
try_raising_nofile_limit();
|
|
LoadExtensionList(xwayland_extensions,
|
|
ARRAY_SIZE(xwayland_extensions), FALSE);
|
|
}
|
|
|
|
wl_log_set_handler_client(xwl_log_handler);
|
|
|
|
if (AddScreen(xwl_screen_init, argc, argv) == -1) {
|
|
FatalError("Couldn't add screen\n");
|
|
}
|
|
|
|
xorgGlxCreateVendor();
|
|
|
|
LocalAccessScopeUser();
|
|
|
|
if (wm_fd >= 0 || init_fd >= 0) {
|
|
if (wm_fd >= 0)
|
|
TimerSet(NULL, 0, 1, add_client_fd, NULL);
|
|
if (init_fd >= 0)
|
|
ListenOnOpenFD(init_fd, FALSE);
|
|
AddCallback(&SelectionCallback, wm_selection_callback, NULL);
|
|
}
|
|
else if (listen_fd_count > 0) {
|
|
listen_on_fds();
|
|
}
|
|
}
|