diff --git a/configure.ac b/configure.ac index 196d78b96..f4daf6d47 100644 --- a/configure.ac +++ b/configure.ac @@ -736,7 +736,7 @@ XEXTPROTO="xextproto >= 7.2.99.901" INPUTPROTO="inputproto >= 2.3" KBPROTO="kbproto >= 1.0.3" FONTSPROTO="fontsproto >= 2.1.3" -FIXESPROTO="fixesproto >= 5.0" +FIXESPROTO="fixesproto >= 6.0" DAMAGEPROTO="damageproto >= 1.1" XCMISCPROTO="xcmiscproto >= 1.2.0" BIGREQSPROTO="bigreqsproto >= 1.1.0" diff --git a/dix/dispatch.c b/dix/dispatch.c index 083553610..cc7eea874 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -128,6 +128,7 @@ int ProcInitialConnection(); #include "inputstr.h" #include "xkbsrv.h" #include "client.h" +#include "xfixesint.h" #ifdef XSERVER_DTRACE #include "registry.h" @@ -399,6 +400,22 @@ SmartScheduleClient(void) return best; } +static Bool +ShouldDisconnectRemainingClients(void) +{ + int i; + + for (i = 1; i < currentMaxClients; i++) { + if (clients[i]) { + if (!XFixesShouldDisconnectClient(clients[i])) + return FALSE; + } + } + + /* All remaining clients can be safely ignored */ + return TRUE; +} + void EnableLimitedSchedulingLatency(void) { @@ -3504,6 +3521,9 @@ CloseDownClient(ClientPtr client) while (!clients[currentMaxClients - 1]) currentMaxClients--; } + + if (ShouldDisconnectRemainingClients()) + dispatchException |= dispatchExceptionAtReset; } static void diff --git a/include/protocol-versions.h b/include/protocol-versions.h index 25abee5b7..d7bfc6dca 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h @@ -139,7 +139,7 @@ #define SERVER_XF86VIDMODE_MINOR_VERSION 2 /* Fixes */ -#define SERVER_XFIXES_MAJOR_VERSION 5 +#define SERVER_XFIXES_MAJOR_VERSION 6 #define SERVER_XFIXES_MINOR_VERSION 0 /* X Input */ diff --git a/meson.build b/meson.build index 6c27b92e8..be59e91b8 100644 --- a/meson.build +++ b/meson.build @@ -73,7 +73,7 @@ xextproto_dep = dependency('xextproto', version: '>= 7.2.99.901', fallback: ['xo inputproto_dep = dependency('inputproto', version: '>= 2.3.99.1', fallback: ['xorgproto', 'ext_xorgproto']) kbproto_dep = dependency('kbproto', version: '>= 1.0.3', fallback: ['xorgproto', 'ext_xorgproto']) fontsproto_dep = dependency('fontsproto', version: '>= 2.1.3', fallback: ['xorgproto', 'ext_xorgproto']) -fixesproto_dep = dependency('fixesproto', version: '>= 5.0', fallback: ['xorgproto', 'ext_xorgproto']) +fixesproto_dep = dependency('fixesproto', version: '>= 6.0', fallback: ['xorgproto', 'ext_xorgproto']) damageproto_dep = dependency('damageproto', version: '>= 1.1', fallback: ['xorgproto', 'ext_xorgproto']) xcmiscproto_dep = dependency('xcmiscproto', version: '>= 1.2.0', fallback: ['xorgproto', 'ext_xorgproto']) bigreqsproto_dep = dependency('bigreqsproto', version: '>= 1.1.0', fallback: ['xorgproto', 'ext_xorgproto']) diff --git a/xfixes/Makefile.am b/xfixes/Makefile.am index 2a95c065b..52a7e6c6a 100644 --- a/xfixes/Makefile.am +++ b/xfixes/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS = $(DIX_CFLAGS) libxfixes_la_SOURCES = \ cursor.c \ + disconnect.c \ region.c \ saveset.c \ select.c \ diff --git a/xfixes/disconnect.c b/xfixes/disconnect.c new file mode 100644 index 000000000..77932725e --- /dev/null +++ b/xfixes/disconnect.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright 2010 Red Hat, Inc. + * + * 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 (including the next + * paragraph) 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. + * + * Copyright © 2002 Keith Packard + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "xfixesint.h" +#include "opaque.h" + +static DevPrivateKeyRec ClientDisconnectPrivateKeyRec; + +#define ClientDisconnectPrivateKey (&ClientDisconnectPrivateKeyRec) + +typedef struct _ClientDisconnect { + int disconnect_mode; +} ClientDisconnectRec, *ClientDisconnectPtr; + +#define GetClientDisconnect(s) \ + ((ClientDisconnectPtr) dixLookupPrivate(&(s)->devPrivates, \ + ClientDisconnectPrivateKey)) + +int +ProcXFixesSetClientDisconnectMode(ClientPtr client) +{ + ClientDisconnectPtr pDisconnect = GetClientDisconnect(client); + + REQUEST(xXFixesSetClientDisconnectModeReq); + + pDisconnect->disconnect_mode = stuff->disconnect_mode; + + return Success; +} + +int _X_COLD +SProcXFixesSetClientDisconnectMode(ClientPtr client) +{ + REQUEST(xXFixesSetClientDisconnectModeReq); + + swaps(&stuff->length); + + REQUEST_AT_LEAST_SIZE(xXFixesSetClientDisconnectModeReq); + + swapl(&stuff->disconnect_mode); + + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +int +ProcXFixesGetClientDisconnectMode(ClientPtr client) +{ + ClientDisconnectPtr pDisconnect = GetClientDisconnect(client); + xXFixesGetClientDisconnectModeReply reply; + + REQUEST_SIZE_MATCH(xXFixesGetClientDisconnectModeReq); + + reply = (xXFixesGetClientDisconnectModeReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .disconnect_mode = pDisconnect->disconnect_mode, + }; + if (client->swapped) { + swaps(&reply.sequenceNumber); + swapl(&reply.disconnect_mode); + } + WriteToClient(client, sizeof(xXFixesGetClientDisconnectModeReply), &reply); + + return Success; +} + +int _X_COLD +SProcXFixesGetClientDisconnectMode(ClientPtr client) +{ + REQUEST(xXFixesGetClientDisconnectModeReq); + + swaps(&stuff->length); + + REQUEST_SIZE_MATCH(xXFixesGetClientDisconnectModeReq); + + return (*ProcXFixesVector[stuff->xfixesReqType]) (client); +} + +Bool +XFixesShouldDisconnectClient(ClientPtr client) +{ + ClientDisconnectPtr pDisconnect = GetClientDisconnect(client); + + if (!pDisconnect) + return FALSE; + + if (dispatchExceptionAtReset & DE_TERMINATE) + return (pDisconnect->disconnect_mode & XFixesClientDisconnectFlagTerminate); + + return FALSE; +} + +Bool +XFixesClientDisconnectInit(void) +{ + if (!dixRegisterPrivateKey(&ClientDisconnectPrivateKeyRec, + PRIVATE_CLIENT, sizeof(ClientDisconnectRec))) + return FALSE; + + return TRUE; +} diff --git a/xfixes/meson.build b/xfixes/meson.build index 4ca819c8d..0e97d477b 100644 --- a/xfixes/meson.build +++ b/xfixes/meson.build @@ -1,5 +1,6 @@ srcs_xfixes = [ 'cursor.c', + 'disconnect.c', 'region.c', 'saveset.c', 'select.c', diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c index 53a6bd62f..4ea9171d9 100644 --- a/xfixes/xfixes.c +++ b/xfixes/xfixes.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * Copyright 2010 Red Hat, Inc. + * Copyright 2010, 2021 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -103,6 +103,7 @@ static const int version_requests[] = { X_XFixesExpandRegion, /* Version 3 */ X_XFixesShowCursor, /* Version 4 */ X_XFixesDestroyPointerBarrier, /* Version 5 */ + X_XFixesGetClientDisconnectMode, /* Version 6 */ }; int (*ProcXFixesVector[XFixesNumberRequests]) (ClientPtr) = { @@ -139,7 +140,10 @@ int (*ProcXFixesVector[XFixesNumberRequests]) (ClientPtr) = { /*************** Version 4 ****************/ ProcXFixesHideCursor, ProcXFixesShowCursor, /*************** Version 5 ****************/ -ProcXFixesCreatePointerBarrier, ProcXFixesDestroyPointerBarrier,}; + ProcXFixesCreatePointerBarrier, ProcXFixesDestroyPointerBarrier, +/*************** Version 6 ****************/ + ProcXFixesSetClientDisconnectMode, ProcXFixesGetClientDisconnectMode, +}; static int ProcXFixesDispatch(ClientPtr client) @@ -200,7 +204,10 @@ static int (*SProcXFixesVector[XFixesNumberRequests]) (ClientPtr) = { /*************** Version 4 ****************/ SProcXFixesHideCursor, SProcXFixesShowCursor, /*************** Version 5 ****************/ -SProcXFixesCreatePointerBarrier, SProcXFixesDestroyPointerBarrier,}; + SProcXFixesCreatePointerBarrier, SProcXFixesDestroyPointerBarrier, +/*************** Version 6 ****************/ + SProcXFixesSetClientDisconnectMode, SProcXFixesGetClientDisconnectMode, +}; static _X_COLD int SProcXFixesDispatch(ClientPtr client) @@ -220,7 +227,10 @@ XFixesExtensionInit(void) (&XFixesClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(XFixesClientRec))) return; - if (XFixesSelectionInit() && XFixesCursorInit() && XFixesRegionInit() && + if (XFixesSelectionInit() && + XFixesCursorInit() && + XFixesRegionInit() && + XFixesClientDisconnectInit() && (extEntry = AddExtension(XFIXES_NAME, XFixesNumberEvents, XFixesNumberErrors, ProcXFixesDispatch, SProcXFixesDispatch, diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h index 44e889040..f597354a0 100644 --- a/xfixes/xfixesint.h +++ b/xfixes/xfixesint.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * Copyright 2010 Red Hat, Inc. + * Copyright 2010, 2021 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -290,6 +290,26 @@ int int SProcXFixesDestroyPointerBarrier(ClientPtr client); +/* Version 6 */ + +Bool + XFixesClientDisconnectInit(void); + +int + ProcXFixesSetClientDisconnectMode(ClientPtr client); + +int + ProcXFixesGetClientDisconnectMode(ClientPtr client); + +int + SProcXFixesSetClientDisconnectMode(ClientPtr client); + +int + SProcXFixesGetClientDisconnectMode(ClientPtr client); + +Bool + XFixesShouldDisconnectClient(ClientPtr client); + /* Xinerama */ #ifdef PANORAMIX extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests]) (ClientPtr);