diff --git a/Makefile.am b/Makefile.am index c425cc6bb..799815ee2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,6 +59,7 @@ SUBDIRS = \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ exa \ + config \ hw aclocaldir = $(datadir)/aclocal diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 000000000..1cc9109db --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,10 @@ +AM_CFLAGS = @DIX_CFLAGS@ + +dbusconfigdir = $(sysconfdir)/dbus-1/system.d +dbusconfig_DATA = xorg-server.conf + +lib_LIBRARIES = libconfig.a + +libconfig_a_SOURCES = config.c + +EXTRA_DIST = xorg-server.conf diff --git a/config/config.c b/config/config.c new file mode 100644 index 000000000..b85b12028 --- /dev/null +++ b/config/config.c @@ -0,0 +1,289 @@ +/* + * Copyright © 2006 Daniel Stone + * + * 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 and/or authors + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The copyright holders + * and/or authors 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 AND/OR AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR AUTHORS 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 + +#ifdef HAVE_DBUS +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include +#include "opaque.h" /* for 'display': there has to be a better way */ + /* the above comment lies. there is no better way. */ +#include "input.h" +#include "config.h" + +#define MATCH_RULE "type='method_call',interface='org.x.config.input'" + +static DBusConnection *configConnection = NULL; +static int configfd = -1; +static char busobject[32] = { 0 }; +static char busname[64] = { 0 }; + +void +configDispatch() +{ + if (!configConnection) + return; + + dbus_connection_read_write_dispatch(configConnection, 0); +} + +static DBusHandlerResult +configMessage(DBusConnection *connection, DBusMessage *message, void *closure) +{ + InputOption *option = NULL, *ret = NULL; + DBusMessageIter iter, subiter; + DBusError error; + char *tmp = NULL; + int deviceid = -1; + DeviceIntPtr pDev = NULL; + + ErrorF("[dbus] new message!\n"); + ErrorF(" source: %s\n", dbus_message_get_sender(message)); + ErrorF(" destination: %s\n", dbus_message_get_destination(message)); + ErrorF(" signature: %s\n", dbus_message_get_signature(message)); + ErrorF(" path: %s\n", dbus_message_get_path(message)); + ErrorF(" interface: %s\n", dbus_message_get_interface(message)); + ErrorF(" member: %s\n", dbus_message_get_member(message)); + ErrorF(" method call? %s\n", (dbus_message_get_type(message) == + DBUS_MESSAGE_TYPE_METHOD_CALL) ? + "yes" : "no"); + + dbus_error_init(&error); + + if (strcmp(dbus_message_get_interface(message), + "org.x.config.input") == 0) { + if (!dbus_message_iter_init(message, &iter)) { + ErrorF("failed to init iterator! this is probably bad.\n"); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_NEED_MEMORY; /* ?? */ + } + if (strcmp(dbus_message_get_member(message), "add") == 0) { + ErrorF(" we want to add a device!\n"); + /* signature should be [ss][ss]... */ + while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) { + option = (InputOption *)xcalloc(sizeof(InputOption), 1); + if (!option) { + while (ret) { + option = ret; + ret = ret->next; + xfree(option); + } + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + + dbus_message_iter_recurse(&iter, &subiter); + + if (dbus_message_iter_get_arg_type(&subiter) != + DBUS_TYPE_STRING) { + ErrorF("couldn't get the arg type\n"); + xfree(option); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + dbus_message_iter_get_basic(&subiter, &tmp); + if (!tmp) { + ErrorF("couldn't get the key!\n"); + xfree(option); + break; + } + option->key = xstrdup(tmp); + if (!option->key) { + ErrorF("couldn't duplicate the key!\n"); + xfree(option); + break; + } + + if (!dbus_message_iter_has_next(&subiter)) { + ErrorF("broken message: no next\n"); + xfree(option->key); + xfree(option); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + dbus_message_iter_next(&subiter); + + if (dbus_message_iter_get_arg_type(&subiter) != + DBUS_TYPE_STRING) { + ErrorF("couldn't get the arg type\n"); + xfree(option); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + dbus_message_iter_get_basic(&subiter, &tmp); + if (!tmp) { + ErrorF("couldn't get the value!\n"); + xfree(option->key); + xfree(option); + break; + } + option->value = xstrdup(tmp); + if (!option->value) { + ErrorF("couldn't duplicate the option!\n"); + xfree(option->value); + xfree(option); + break; + } + + option->next = ret; + ret = option; + dbus_message_iter_next(&iter); + } + + if (NewInputDeviceRequest(ret) != Success) { + ErrorF("[config] NIDR failed\n"); + } + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + else if (strcmp(dbus_message_get_member(message), "remove") == 0) { + ErrorF(" we want to remove a device!\n"); + if (!dbus_message_get_args(message, &error, DBUS_TYPE_INT32, + &deviceid, DBUS_TYPE_INVALID)) { + ErrorF("couldn't get args: %s %s\n", error.name, error.message); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + if (deviceid < 0 || !(pDev = LookupDeviceIntRec(deviceid))) { + ErrorF("bogus device id %d\n", deviceid); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + ErrorF("pDev is %p\n", pDev); + RemoveDevice(pDev); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_HANDLED; + } + } + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +void +configInitialise() +{ + DBusConnection *bus = NULL; + DBusError error; + DBusObjectPathVTable vtable; + + configConnection = NULL; + + dbus_error_init(&error); + bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (!bus || dbus_error_is_set(&error)) { + ErrorF("[dbus] some kind of error occurred: %s (%s)\n", error.name, + error.message); + dbus_error_free(&error); + return; + } + + if (!dbus_connection_get_unix_fd(bus, &configfd)) { + ErrorF("[dbus] couldn't get fd for bus\n"); + dbus_connection_close(bus); + configfd = -1; + return; + } + + snprintf(busname, sizeof(busname), "org.x.config.display%d", atoi(display)); + if (!dbus_bus_request_name(bus, busname, 0, &error) || + dbus_error_is_set(&error)) { + ErrorF("[dbus] couldn't take over org.x.config: %s (%s)\n", + error.name, error.message); + dbus_error_free(&error); + dbus_connection_close(bus); + configfd = -1; + return; + } + + /* blocks until we get a reply. */ + dbus_bus_add_match(bus, MATCH_RULE, &error); + if (dbus_error_is_set(&error)) { + ErrorF("[dbus] couldn't match X.Org rule: %s (%s)\n", error.name, + error.message); + dbus_error_free(&error); + dbus_bus_release_name(bus, busname, &error); + dbus_connection_close(bus); + configfd = -1; + return; + } + + vtable.message_function = configMessage; + snprintf(busobject, sizeof(busobject), "/org/x/config/%d", atoi(display)); + if (!dbus_connection_register_object_path(bus, busobject, &vtable, NULL)) { + ErrorF("[dbus] couldn't register object path\n"); + configfd = -1; + dbus_bus_release_name(bus, busname, &error); + dbus_bus_remove_match(bus, MATCH_RULE, &error); + dbus_connection_close(bus); + configfd = -1; + return; + } + ErrorF("[dbus] registered object path %s\n", busobject); + + ErrorF("[dbus] registered and listening\n"); + + dbus_error_free(&error); + + configConnection = bus; + + AddGeneralSocket(configfd); +} + +void +configFini() +{ + DBusError error; + + if (configConnection) { + dbus_error_init(&error); + ErrorF("configFini being called\n"); + dbus_bus_remove_match(configConnection, MATCH_RULE, &error); + dbus_bus_release_name(configConnection, busname, &error); + dbus_connection_close(configConnection); + RemoveGeneralSocket(configfd); + configConnection = NULL; + configfd = -1; + dbus_error_free(&error); + } +} +#else +void +configDispatch() +{ +} + +void +configInitialise() +{ +} + +void +configFini() +{ +} +#endif diff --git a/config/xorg-server.conf b/config/xorg-server.conf new file mode 100644 index 000000000..47a9a7824 --- /dev/null +++ b/config/xorg-server.conf @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/configure.ac b/configure.ac index a2af59990..41536f74e 100644 --- a/configure.ac +++ b/configure.ac @@ -423,6 +423,7 @@ AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extensi AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--disable-xf86bigfont], [Build XF86 Big Font extension (default: enabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=yes]) AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) AC_ARG_ENABLE(xinput, AS_HELP_STRING([--disable-xinput], [Build XInput Extension (default: enabled)]), [XINPUT=$enableval], [XINPUT=yes]) +AC_ARG_ENABLE(dbus, AS_HELP_STRING([--disable-dbus], [Build D-BUS support (default: auto)]), [DBUS=$enableval], [DBUS=auto]) dnl DDXes. AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) @@ -512,6 +513,18 @@ dnl Core modules for most extensions, et al. REQUIRED_MODULES="randrproto renderproto [fixesproto >= 4.0] damageproto xcmiscproto xextproto xproto xtrans xf86miscproto xf86vidmodeproto xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto xf86dgaproto" REQUIRED_LIBS="xfont xau fontenc" +if test "x$DBUS" = xauto; then + PKG_CHECK_MODULES(DBUS, dbus-1, [DBUS=yes], [DBUS=no]) +fi +if test "x$DBUS" = xyes; then + PKG_CHECK_MODULES(DBUS, dbus-1) + AC_DEFINE(HAVE_DBUS, 1, [Have D-BUS support]) + REQUIRED_MODULES="$REQUIRED_MODULES dbus-1" + REQUIRED_LIBS="$REQUIRED_LIBS dbus-1" +fi +CONFIG_LIB='$(top_builddir)/config/libconfig.a' +AM_CONDITIONAL(DBUS, [test "x$DBUS" = xyes]) + AM_CONDITIONAL(XV, [test "x$XV" = xyes]) if test "x$XV" = xyes; then AC_DEFINE(XV, 1, [Support Xv extension]) @@ -1007,7 +1020,7 @@ if test "x$XGLX" = xyes; then fi # XORG_CORE_LIBS is needed even if you're not building the Xorg DDX -XORG_CORE_LIBS="$DIX_LIB" +XORG_CORE_LIBS="$DIX_LIB $CONFIG_LIB" AC_SUBST([XORG_CORE_LIBS]) xorg_bus_linuxpci=no @@ -1295,7 +1308,7 @@ AC_MSG_RESULT([$XPRINT]) if test "x$XPRINT" = xyes; then PKG_CHECK_MODULES([XPRINT], [printproto x11 xfont $XDMCP_MODULES xau]) XPRINT_EXTENSIONS="$XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $RENDER_LIB $COMPOSITE_LIB $RANDR_LIB $XI_LIB $FIXES_LIB $DAMAGE_LIB $XI_LIB $GLX_LIBS" - XPRINT_LIBS="$XPRINT_LIBS $DIX_LIB $XKB_LIB $XKB_STUB_LIB $XPRINT_EXTENSIONS $MI_LIB $MIEXT_DAMAGE_LIB $CWRAP_LIB $OS_LIB" + XPRINT_LIBS="$XPRINT_LIBS $DIX_LIB $CONFIG_LIB $XKB_LIB $XKB_STUB_LIB $XPRINT_EXTENSIONS $MI_LIB $MIEXT_DAMAGE_LIB $CWRAP_LIB $OS_LIB" AC_SUBST([XPRINT_CFLAGS]) AC_SUBST([XPRINT_LIBS]) @@ -1451,7 +1464,7 @@ if test "$KDRIVE" = yes; then KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a' KDRIVE_OS_LIB='$(top_builddir)/hw/kdrive/linux/liblinux.a' KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.a' - KDRIVE_LIBS="$DIX_LIB $KDRIVE_LIB $KDRIVE_OS_LIB $KDRIVE_PURE_LIBS $KDRIVE_STUB_LIB" + KDRIVE_LIBS="$DIX_LIB $CONFIG_LIB $KDRIVE_LIB $KDRIVE_OS_LIB $KDRIVE_PURE_LIBS $KDRIVE_STUB_LIB" # check if we can build Xephyr PKG_CHECK_MODULES(XEPHYR, x11 xext xfont xau xdmcp, [xephyr="yes"], [xephyr="no"]) @@ -1630,6 +1643,7 @@ XTrap/Makefile mfb/Makefile cfb/Makefile cfb32/Makefile +config/Makefile mi/Makefile miext/Makefile miext/damage/Makefile diff --git a/dix/dispatch.c b/dix/dispatch.c index 72d49950b..066b608f2 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -103,6 +103,7 @@ int ProcInitialConnection(); #include "dispatch.h" #include "swaprep.h" #include "swapreq.h" +#include "config.h" #ifdef PANORAMIX #include "panoramiX.h" #include "panoramiXsrv.h" @@ -385,6 +386,9 @@ Dispatch(void) nready = WaitForSomething(clientReady); + /* this is an enormous hack and NEEDS TO GO AWAY. */ + configDispatch(); + #ifdef SMART_SCHEDULE if (nready && !SmartScheduleDisable) { diff --git a/dix/main.c b/dix/main.c index 9d66a4fa8..5f539895e 100644 --- a/dix/main.c +++ b/dix/main.c @@ -101,6 +101,7 @@ Equipment Corporation. #include #include "opaque.h" #include "servermd.h" +#include "config.h" #include "site.h" #include "dixfont.h" #include "extnsionst.h" @@ -311,6 +312,7 @@ main(int argc, char *argv[], char *envp[]) DPMSPowerLevel = 0; #endif InitBlockAndWakeupHandlers(); + configInitialise(); /* Perform any operating system dependent initializations you'd like */ OsInit(); if(serverGeneration == 1) @@ -463,6 +465,7 @@ main(int argc, char *argv[], char *envp[]) FreeAllResources(); #endif + configFini(); CloseDownDevices(); for (i = screenInfo.numScreens - 1; i >= 0; i--) { diff --git a/include/config.h b/include/config.h new file mode 100644 index 000000000..0c304b15e --- /dev/null +++ b/include/config.h @@ -0,0 +1,31 @@ +/* + * Copyright © 2006 Daniel Stone + * + * 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 and/or authors + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The copyright holders + * and/or authors 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 AND/OR AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR AUTHORS 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. + */ + +#ifndef CONFIG_H +#define CONFIG_H + +void configInitialise(void); +void configFini(void); +void configDispatch(void); + +#endif /* CONFIG_H */ diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 2b9f273d7..72a329c03 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -436,4 +436,7 @@ /* Define to 1 if modules should avoid the libcwrapper */ #undef NO_LIBCWRAPPER +/* Support D-BUS */ +#undef HAVE_DBUS + #endif /* _DIX_CONFIG_H_ */ diff --git a/include/input.h b/include/input.h index e32182d4c..3e00be671 100644 --- a/include/input.h +++ b/include/input.h @@ -163,6 +163,12 @@ extern void ResetDevicePrivateIndex(void); extern KeybdCtrl defaultKeyboardControl; extern PtrCtrl defaultPointerControl; +typedef struct _InputOption { + char *key; + char *value; + struct _InputOption *next; +} InputOption; + extern DeviceIntPtr AddInputDevice( DeviceProc /*deviceProc*/, Bool /*autoStart*/); @@ -366,4 +372,11 @@ extern void InitInput( int /*argc*/, char ** /*argv*/); +/* Implemented by the DDX. */ +extern int NewInputDeviceRequest( + InputOption *options); + +extern DeviceIntPtr LookupDeviceIntRec( + CARD8 deviceid); + #endif /* INPUT_H */ diff --git a/include/os.h b/include/os.h index e16839c74..d459e9e2f 100644 --- a/include/os.h +++ b/include/os.h @@ -149,6 +149,10 @@ extern void CheckConnections(void); extern void CloseDownConnection(ClientPtr /*client*/); +extern void AddGeneralSocket(int /*fd*/); + +extern void RemoveGeneralSocket(int /*fd*/); + extern void AddEnabledDevice(int /*fd*/); extern void RemoveEnabledDevice(int /*fd*/); diff --git a/os/connection.c b/os/connection.c index ce765665f..7648a52ca 100644 --- a/os/connection.c +++ b/os/connection.c @@ -1014,16 +1014,22 @@ CloseDownConnection(ClientPtr client) } _X_EXPORT void -AddEnabledDevice(int fd) +AddGeneralSocket(int fd) { - FD_SET(fd, &EnabledDevices); FD_SET(fd, &AllSockets); if (GrabInProgress) FD_SET(fd, &SavedAllSockets); } _X_EXPORT void -RemoveEnabledDevice(int fd) +AddEnabledDevice(int fd) +{ + FD_SET(fd, &EnabledDevices); + AddGeneralSocket(fd); +} + +_X_EXPORT void +RemoveGeneralSocket(int fd) { FD_CLR(fd, &EnabledDevices); FD_CLR(fd, &AllSockets); @@ -1031,6 +1037,13 @@ RemoveEnabledDevice(int fd) FD_CLR(fd, &SavedAllSockets); } +_X_EXPORT void +RemoveEnabledDevice(int fd) +{ + FD_CLR(fd, &EnabledDevices); + RemoveGeneralSocket(fd); +} + /***************** * OnlyListenToOneClient: * Only accept requests from one client. Continue to handle new