* config.in (HAVE_DBUS): Add.
* Makefile.in: (HAVE_DBUS): Add D-Bus definitions if defined. (ALL_CFLAGS): Add ${DBUS_CFLAGS}. (obj): Add $(DBUS_OBJ). (LIBES): Add $(DBUS_LIBS). (dbusbind.o): New target. * dbusbind.c: New file. * emacs.c (main): Call syms_of_dbusbind when HAVE_DBUS is defined. * keyboard.c: All D-Bus related code is wrapped by "#ifdef HAVE_DBUS". (Qdbus_event) New Lisp symbol. (kbd_buffer_get_event, make_lispy_event): Handle DBUS_EVENT. (gobble_input): Call xd_read_queued_messages, reading D-Bus messages. (keys_of_keyboard ): Define dbus-event. * termhooks.h (event_kind): Add DBUS_EVENT when HAVE_DBUS is defined.
This commit is contained in:
parent
131e41336f
commit
033b73e2e0
7 changed files with 946 additions and 48 deletions
|
@ -1,3 +1,26 @@
|
|||
2007-12-02 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
* config.in (HAVE_DBUS): Add.
|
||||
|
||||
* Makefile.in: (HAVE_DBUS): Add D-Bus definitions if defined.
|
||||
(ALL_CFLAGS): Add ${DBUS_CFLAGS}.
|
||||
(obj): Add $(DBUS_OBJ).
|
||||
(LIBES): Add $(DBUS_LIBS).
|
||||
(dbusbind.o): New target.
|
||||
|
||||
* dbusbind.c: New file.
|
||||
|
||||
* emacs.c (main): Call syms_of_dbusbind when HAVE_DBUS is defined.
|
||||
|
||||
* keyboard.c: All D-Bus related code is wrapped by "#ifdef HAVE_DBUS".
|
||||
(Qdbus_event) New Lisp symbol.
|
||||
(kbd_buffer_get_event, make_lispy_event): Handle DBUS_EVENT.
|
||||
(gobble_input): Call xd_read_queued_messages, reading D-Bus
|
||||
messages.
|
||||
(keys_of_keyboard ): Define dbus-event.
|
||||
|
||||
* termhooks.h (event_kind): Add DBUS_EVENT when HAVE_DBUS is defined.
|
||||
|
||||
2007-12-01 Richard Stallman <rms@gnu.org>
|
||||
|
||||
* search.c (syms_of_search) <inhibit-changing-match-data>: Doc fix.
|
||||
|
|
|
@ -262,6 +262,12 @@ TOOLKIT_DEFINES =
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
DBUS_CFLAGS = @DBUS_CFLAGS@
|
||||
DBUS_LIBS = @DBUS_LIBS@
|
||||
DBUS_OBJ = dbusbind.o
|
||||
#endif
|
||||
|
||||
/* DO NOT use -R. There is a special hack described in lastfile.c
|
||||
which is used instead. Some initialized data areas are modified
|
||||
at initial startup, then labeled as part of the text area when
|
||||
|
@ -275,7 +281,7 @@ TOOLKIT_DEFINES =
|
|||
|
||||
/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
|
||||
since it may have -I options that should override those two. */
|
||||
ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${CFLAGS}
|
||||
ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS}
|
||||
.c.o:
|
||||
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
|
||||
|
||||
|
@ -588,7 +594,7 @@ emacsappsrc = ${srcdir}/../mac/Emacs.app/
|
|||
whose initialized data areas should be dumped as pure by dump-emacs. */
|
||||
obj= dispnew.o frame.o scroll.o xdisp.o $(XMENU_OBJ) window.o \
|
||||
charset.o coding.o category.o ccl.o \
|
||||
cm.o term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ)\
|
||||
cm.o term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \
|
||||
emacs.o keyboard.o macros.o keymap.o sysdep.o \
|
||||
buffer.o filelock.o insdel.o marker.o \
|
||||
minibuf.o fileio.o dired.o filemode.o \
|
||||
|
@ -938,8 +944,8 @@ SOME_MACHINE_LISP = ${dotdot}/lisp/mouse.elc \
|
|||
Note that SunOS needs -lm to come before -lc; otherwise, you get
|
||||
duplicated symbols. If the standard libraries were compiled
|
||||
with GCC, we might need gnulib again after them. */
|
||||
LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) LIBGPM \
|
||||
LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
|
||||
LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
|
||||
LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
|
||||
LIBS_DEBUG $(GETLOADAVG_LIBS) $(GNULIB_VAR) LIB_MATH LIB_STANDARD \
|
||||
$(GNULIB_VAR)
|
||||
|
||||
|
@ -1228,9 +1234,10 @@ xselect.o: xselect.c process.h dispextern.h frame.h xterm.h blockinput.h \
|
|||
xrdb.o: xrdb.c $(config_h) epaths.h
|
||||
xsmfns.o: xsmfns.c $(config_h) systime.h sysselect.h termhooks.h xterm.h \
|
||||
lisp.h termopts.h
|
||||
gtkutil.o: gtkutil.c gtkutil.h xterm.h lisp.h frame.h $(config_h) \
|
||||
gtkutil.o: gtkutil.c gtkutil.h xterm.h lisp.h frame.h $(config_h) \
|
||||
blockinput.h window.h atimer.h systime.h termhooks.h keyboard.h \
|
||||
charset.h coding.h
|
||||
dbusbind.o: dbusbind.c termhooks.h $(config_h)
|
||||
|
||||
hftctl.o: hftctl.c $(config_h)
|
||||
sound.o: sound.c dispextern.h $(config_h)
|
||||
|
|
|
@ -238,6 +238,9 @@ Boston, MA 02110-1301, USA. */
|
|||
/* Define to 1 if you have the `grantpt' function. */
|
||||
#undef HAVE_GRANTPT
|
||||
|
||||
/* Define to 1 if using D-BUS. */
|
||||
#undef HAVE_DBUS
|
||||
|
||||
/* Define to 1 if using GTK. */
|
||||
#undef HAVE_GTK
|
||||
|
||||
|
|
824
src/dbusbind.c
Normal file
824
src/dbusbind.c
Normal file
|
@ -0,0 +1,824 @@
|
|||
/* Elisp bindings for D-Bus.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <stdlib.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include "lisp.h"
|
||||
#include "frame.h"
|
||||
#include "termhooks.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
|
||||
/* Subroutines. */
|
||||
Lisp_Object Qdbus_get_unique_name;
|
||||
Lisp_Object Qdbus_call_method;
|
||||
Lisp_Object Qdbus_send_signal;
|
||||
Lisp_Object Qdbus_register_signal;
|
||||
Lisp_Object Qdbus_unregister_signal;
|
||||
|
||||
/* D-Bus error symbol. */
|
||||
Lisp_Object Qdbus_error;
|
||||
|
||||
/* Lisp symbols of the system and session buses. */
|
||||
Lisp_Object Qdbus_system_bus, Qdbus_session_bus;
|
||||
|
||||
/* Obarray which keeps interned symbols. */
|
||||
Lisp_Object Vdbus_intern_symbols;
|
||||
|
||||
/* Whether to debug D-Bus. */
|
||||
Lisp_Object Vdbus_debug;
|
||||
|
||||
|
||||
/* We use "xd_" and "XD_" as prefix for all internal symbols, because
|
||||
we don't want to poison other namespaces with "dbus_". */
|
||||
|
||||
/* Create a new interned symbol which represents a function handler.
|
||||
bus is a Lisp symbol, either :system or :session. interface and
|
||||
member are both Lisp strings.
|
||||
|
||||
D-Bus sends messages, which are captured by Emacs in the main loop,
|
||||
converted into an event then. Emacs must identify a message from
|
||||
D-Bus, in order to call the right Lisp function when the event is
|
||||
handled in the event handler function of dbus.el.
|
||||
|
||||
A D-Bus message is determined at least by the D-Bus bus it is
|
||||
raised from (system bus or session bus), the interface and the
|
||||
method the message belongs to. There could be even more properties
|
||||
for determination, but that isn't implemented yet.
|
||||
|
||||
The approach is to create a new interned Lisp symbol once there is
|
||||
a registration request for a given signal, which is a special D-Bus
|
||||
message. The symbol's name is a concatenation of the bus name,
|
||||
interface name and method name of the signal; the function cell is
|
||||
the Lisp function to be called when such a signal arrives. Since
|
||||
this code runs in the main loop, receiving input, it must be
|
||||
performant. */
|
||||
#define XD_SYMBOL_INTERN_SYMBOL(symbol, bus, interface, member) \
|
||||
{ \
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (bus); \
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (interface); \
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (member); \
|
||||
char s[1024]; \
|
||||
strcpy (s, SDATA (SYMBOL_NAME (bus))); \
|
||||
strcat (s, "."); \
|
||||
strcat (s, SDATA (interface)); \
|
||||
strcat (s, "."); \
|
||||
strcat (s, SDATA (member)); \
|
||||
symbol = Fintern (build_string (s), Vdbus_intern_symbols); \
|
||||
}
|
||||
|
||||
/* Raise a Lisp error from a D-Bus error. */
|
||||
#define XD_ERROR(error) \
|
||||
{ \
|
||||
char s[1024]; \
|
||||
strcpy (s, error.message); \
|
||||
dbus_error_free (&error); \
|
||||
/* Remove the trailing newline. */ \
|
||||
if (strchr (s, '\n') != NULL) \
|
||||
s[strlen (s) - 1] = '\0'; \
|
||||
xsignal1 (Qdbus_error, build_string (s)); \
|
||||
}
|
||||
|
||||
/* Macros for debugging. In order to enable them, build with
|
||||
"make MYCPPFLAGS='-DDBUS_DEBUG'". */
|
||||
#ifdef DBUS_DEBUG
|
||||
#define XD_DEBUG_MESSAGE(...) \
|
||||
{ \
|
||||
char s[1024]; \
|
||||
sprintf (s, __VA_ARGS__); \
|
||||
printf ("%s: %s\n", __func__, s); \
|
||||
message ("%s: %s", __func__, s); \
|
||||
}
|
||||
#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
|
||||
if (!valid_lisp_object_p (object)) \
|
||||
{ \
|
||||
XD_DEBUG_MESSAGE ("%s Assertion failure", __LINE__); \
|
||||
xsignal1 (Qdbus_error, build_string ("Assertion failure")); \
|
||||
}
|
||||
|
||||
#else /* !DBUS_DEBUG */
|
||||
#define XD_DEBUG_MESSAGE(...) \
|
||||
if (!NILP (Vdbus_debug)) \
|
||||
{ \
|
||||
char s[1024]; \
|
||||
sprintf (s, __VA_ARGS__); \
|
||||
message ("%s: %s", __func__, s); \
|
||||
}
|
||||
#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
|
||||
#endif
|
||||
|
||||
/* Determine the DBusType of a given Lisp object. It is used to
|
||||
convert Lisp objects, being arguments of `dbus-call-method' or
|
||||
`dbus-send-signal', into corresponding C values appended as
|
||||
arguments to a D-Bus message. */
|
||||
#define XD_LISP_OBJECT_TO_DBUS_TYPE(object) \
|
||||
(EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN : \
|
||||
(NATNUMP (object)) ? DBUS_TYPE_UINT32 : \
|
||||
(INTEGERP (object)) ? DBUS_TYPE_INT32 : \
|
||||
(FLOATP (object)) ? DBUS_TYPE_DOUBLE : \
|
||||
(STRINGP (object)) ? DBUS_TYPE_STRING : \
|
||||
DBUS_TYPE_INVALID
|
||||
|
||||
/* Extract C value from Lisp OBJECT. DTYPE must be a valid DBusType,
|
||||
as detected by XD_LISP_OBJECT_TO_DBUS_TYPE. Compound types are not
|
||||
supported (yet). It is used to convert Lisp objects, being
|
||||
arguments of `dbus-call-method' or `dbus-send-signal', into
|
||||
corresponding C values appended as arguments to a D-Bus
|
||||
message. */
|
||||
char *
|
||||
xd_retrieve_value (dtype, object)
|
||||
uint dtype;
|
||||
Lisp_Object object;
|
||||
{
|
||||
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (object);
|
||||
switch (dtype)
|
||||
{
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
XD_DEBUG_MESSAGE ("%d %s", dtype, (NILP (object)) ? "false" : "true");
|
||||
return (NILP (object)) ? (char *) FALSE : (char *) TRUE;
|
||||
case DBUS_TYPE_UINT32:
|
||||
XD_DEBUG_MESSAGE ("%d %d", dtype, XUINT (object));
|
||||
return (char *) XUINT (object);
|
||||
case DBUS_TYPE_INT32:
|
||||
XD_DEBUG_MESSAGE ("%d %d", dtype, XINT (object));
|
||||
return (char *) XINT (object);
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
XD_DEBUG_MESSAGE ("%d %d", dtype, XFLOAT (object));
|
||||
return (char *) XFLOAT (object);
|
||||
case DBUS_TYPE_STRING:
|
||||
XD_DEBUG_MESSAGE ("%d %s", dtype, SDATA (object));
|
||||
return SDATA (object);
|
||||
default:
|
||||
XD_DEBUG_MESSAGE ("DBus-Type %d not supported", dtype);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Retrieve C value from a DBusMessageIter structure ITER, and return
|
||||
a converted Lisp object. The type DTYPE of the argument of the
|
||||
D-Bus message must be a valid DBusType. Compound D-Bus types are
|
||||
partly supported; they result always in a Lisp list. */
|
||||
Lisp_Object
|
||||
xd_retrieve_arg (dtype, iter)
|
||||
uint dtype;
|
||||
DBusMessageIter *iter;
|
||||
{
|
||||
|
||||
switch (dtype)
|
||||
{
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
{
|
||||
dbus_bool_t val;
|
||||
dbus_message_iter_get_basic (iter, &val);
|
||||
XD_DEBUG_MESSAGE ("%d %s", dtype, (val == FALSE) ? "false" : "true");
|
||||
return (val == FALSE) ? Qnil : Qt;
|
||||
}
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
{
|
||||
dbus_uint32_t val;
|
||||
dbus_message_iter_get_basic (iter, &val);
|
||||
XD_DEBUG_MESSAGE ("%d %d", dtype, val);
|
||||
return make_number (val);
|
||||
}
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
{
|
||||
char *val;
|
||||
dbus_message_iter_get_basic (iter, &val);
|
||||
XD_DEBUG_MESSAGE ("%d %s", dtype, val);
|
||||
return build_string (val);
|
||||
}
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
{
|
||||
Lisp_Object result;
|
||||
struct gcpro gcpro1;
|
||||
result = Qnil;
|
||||
GCPRO1 (result);
|
||||
DBusMessageIter subiter;
|
||||
int subtype;
|
||||
dbus_message_iter_recurse (iter, &subiter);
|
||||
while ((subtype = dbus_message_iter_get_arg_type (&subiter))
|
||||
!= DBUS_TYPE_INVALID)
|
||||
{
|
||||
result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
|
||||
dbus_message_iter_next (&subiter);
|
||||
}
|
||||
RETURN_UNGCPRO (Fnreverse (result));
|
||||
}
|
||||
default:
|
||||
XD_DEBUG_MESSAGE ("DBusType %d not supported", dtype);
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
|
||||
or :session. It tells which D-Bus to be initialized. */
|
||||
DBusConnection *
|
||||
xd_initialize (bus)
|
||||
Lisp_Object bus;
|
||||
{
|
||||
DBusConnection *connection;
|
||||
DBusError derror;
|
||||
|
||||
/* Parameter check. */
|
||||
CHECK_SYMBOL (bus);
|
||||
if (!((EQ (bus, Qdbus_system_bus)) || (EQ (bus, Qdbus_session_bus))))
|
||||
xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus);
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
dbus_error_init (&derror);
|
||||
|
||||
if (EQ (bus, Qdbus_system_bus))
|
||||
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
|
||||
else
|
||||
connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
|
||||
|
||||
if (dbus_error_is_set (&derror))
|
||||
XD_ERROR (derror);
|
||||
|
||||
if (connection == NULL)
|
||||
xsignal2 (Qdbus_error, build_string ("No connection"), bus);
|
||||
|
||||
/* Return the result. */
|
||||
return connection;
|
||||
}
|
||||
|
||||
DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
|
||||
1, 1, 0,
|
||||
doc: /* Return the unique name of Emacs registered at D-Bus BUS as string. */)
|
||||
(bus)
|
||||
Lisp_Object bus;
|
||||
{
|
||||
DBusConnection *connection;
|
||||
char name[1024];
|
||||
|
||||
/* Check parameters. */
|
||||
CHECK_SYMBOL (bus);
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
connection = xd_initialize (bus);
|
||||
|
||||
/* Request the name. */
|
||||
strcpy (name, dbus_bus_get_unique_name (connection));
|
||||
if (name == NULL)
|
||||
xsignal1 (Qdbus_error, build_string ("No unique name available"));
|
||||
|
||||
/* Return. */
|
||||
return build_string (name);
|
||||
}
|
||||
|
||||
DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
|
||||
doc: /* Call METHOD on the D-Bus BUS.
|
||||
|
||||
BUS is either the symbol `:system' or the symbol `:session'.
|
||||
|
||||
SERVICE is the D-Bus service name to be used. PATH is the D-Bus
|
||||
object path SERVICE is registered at. INTERFACE is an interface
|
||||
offered by SERVICE. It must provide METHOD.
|
||||
|
||||
All other arguments ARGS are passed to METHOD as arguments. They are
|
||||
converted into D-Bus types via the following rules:
|
||||
|
||||
t and nil => DBUS_TYPE_BOOLEAN
|
||||
number => DBUS_TYPE_UINT32
|
||||
integer => DBUS_TYPE_INT32
|
||||
float => DBUS_TYPE_DOUBLE
|
||||
string => DBUS_TYPE_STRING
|
||||
|
||||
Other Lisp objects are not supported as input arguments of METHOD.
|
||||
|
||||
`dbus-call-method' returns the resulting values of METHOD as a list of
|
||||
Lisp objects. The type conversion happens the other direction as for
|
||||
input arguments. Additionally to the types supported for input
|
||||
arguments, the D-Bus compound types DBUS_TYPE_ARRAY, DBUS_TYPE_VARIANT,
|
||||
DBUS_TYPE_STRUCT and DBUS_TYPE_DICT_ENTRY are accepted. All of them
|
||||
are converted into a list of Lisp objects which correspond to the
|
||||
elements of the D-Bus container. Example:
|
||||
|
||||
\(dbus-call-method
|
||||
:session "GetKeyField" "org.gnome.seahorse"
|
||||
"/org/gnome/seahorse/keys/openpgp" "org.gnome.seahorse.Keys"
|
||||
"openpgp:657984B8C7A966DD" "simple-name")
|
||||
|
||||
=> (t ("Philip R. Zimmermann"))
|
||||
|
||||
If the result of the METHOD call is just one value, the converted Lisp
|
||||
object is returned instead of a list containing this single Lisp object.
|
||||
|
||||
\(dbus-call-method
|
||||
:system "GetPropertyString" "org.freedesktop.Hal"
|
||||
"/org/freedesktop/Hal/devices/computer" "org.freedesktop.Hal.Device"
|
||||
"system.kernel.machine")
|
||||
|
||||
=> "i686"
|
||||
|
||||
usage: (dbus-call-method BUS METHOD SERVICE PATH INTERFACE &rest ARGS) */)
|
||||
(nargs, args)
|
||||
int nargs;
|
||||
register Lisp_Object *args;
|
||||
{
|
||||
Lisp_Object bus, method, service, path, interface;
|
||||
Lisp_Object result;
|
||||
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
|
||||
DBusConnection *connection;
|
||||
DBusMessage *dmessage;
|
||||
DBusMessage *reply;
|
||||
DBusMessageIter iter;
|
||||
DBusError derror;
|
||||
uint dtype;
|
||||
int i;
|
||||
char *value;
|
||||
|
||||
/* Check parameters. */
|
||||
bus = args[0];
|
||||
method = args[1];
|
||||
service = args[2];
|
||||
path = args[3];
|
||||
interface = args[4];
|
||||
|
||||
CHECK_SYMBOL (bus);
|
||||
CHECK_STRING (method);
|
||||
CHECK_STRING (service);
|
||||
CHECK_STRING (path);
|
||||
CHECK_STRING (interface);
|
||||
GCPRO5 (bus, method, service, path, interface);
|
||||
|
||||
XD_DEBUG_MESSAGE ("%s %s %s %s",
|
||||
SDATA (method),
|
||||
SDATA (service),
|
||||
SDATA (path),
|
||||
SDATA (interface));
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
connection = xd_initialize (bus);
|
||||
|
||||
/* Create the message. */
|
||||
dmessage = dbus_message_new_method_call (SDATA (service),
|
||||
SDATA (path),
|
||||
SDATA (interface),
|
||||
SDATA (method));
|
||||
if (dmessage == NULL)
|
||||
{
|
||||
UNGCPRO;
|
||||
xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
|
||||
}
|
||||
|
||||
UNGCPRO;
|
||||
|
||||
/* Append parameters to the message. */
|
||||
for (i = 5; i < nargs; ++i)
|
||||
{
|
||||
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
|
||||
XD_DEBUG_MESSAGE ("Parameter%d %s",
|
||||
i-4,
|
||||
SDATA (format2 ("%s", args[i], Qnil)));
|
||||
|
||||
dtype = XD_LISP_OBJECT_TO_DBUS_TYPE (args[i]);
|
||||
if (dtype == DBUS_TYPE_INVALID)
|
||||
xsignal2 (Qdbus_error, build_string ("Not a valid argument"), args[i]);
|
||||
|
||||
value = (char *) xd_retrieve_value (dtype, args[i]);
|
||||
|
||||
if (!dbus_message_append_args (dmessage,
|
||||
dtype,
|
||||
&value,
|
||||
DBUS_TYPE_INVALID))
|
||||
xsignal2 (Qdbus_error,
|
||||
build_string ("Unable to append argument"), args[i]);
|
||||
}
|
||||
|
||||
/* Send the message. */
|
||||
dbus_error_init (&derror);
|
||||
reply = dbus_connection_send_with_reply_and_block (connection,
|
||||
dmessage,
|
||||
-1,
|
||||
&derror);
|
||||
|
||||
if (dbus_error_is_set (&derror))
|
||||
XD_ERROR (derror);
|
||||
|
||||
if (reply == NULL)
|
||||
xsignal1 (Qdbus_error, build_string ("No reply"));
|
||||
|
||||
XD_DEBUG_MESSAGE ("Message sent");
|
||||
|
||||
/* Collect the results. */
|
||||
result = Qnil;
|
||||
GCPRO1 (result);
|
||||
|
||||
if (!dbus_message_iter_init (reply, &iter))
|
||||
{
|
||||
UNGCPRO;
|
||||
xsignal1 (Qdbus_error, build_string ("Cannot read reply"));
|
||||
}
|
||||
|
||||
/* Loop over the parameters of the D-Bus reply message. Construct a
|
||||
Lisp list, which is returned by `dbus-call-method'. */
|
||||
while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
result = Fcons (xd_retrieve_arg (dtype, &iter), result);
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
/* Cleanup. */
|
||||
dbus_message_unref (dmessage);
|
||||
dbus_message_unref (reply);
|
||||
|
||||
/* Return the result. If there is only one single Lisp object,
|
||||
return it as-it-is, otherwise return the reversed list. */
|
||||
if (XUINT (Flength (result)) == 1)
|
||||
RETURN_UNGCPRO (XCAR (result));
|
||||
else
|
||||
RETURN_UNGCPRO (Fnreverse (result));
|
||||
}
|
||||
|
||||
DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
|
||||
doc: /* Send signal SIGNAL on the D-Bus BUS.
|
||||
|
||||
BUS is either the symbol `:system' or the symbol `:session'.
|
||||
|
||||
SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
|
||||
D-Bus object path SERVICE is registered at. INTERFACE is an interface
|
||||
offered by SERVICE. It must provide signal SIGNAL.
|
||||
|
||||
All other arguments ARGS are passed to SIGNAL as arguments. They are
|
||||
converted into D-Bus types via the following rules:
|
||||
|
||||
t and nil => DBUS_TYPE_BOOLEAN
|
||||
number => DBUS_TYPE_UINT32
|
||||
integer => DBUS_TYPE_INT32
|
||||
float => DBUS_TYPE_DOUBLE
|
||||
string => DBUS_TYPE_STRING
|
||||
|
||||
Other Lisp objects are not supported as arguments of SIGNAL.
|
||||
|
||||
Example:
|
||||
|
||||
\(dbus-send-signal
|
||||
:session "Started" "org.gnu.emacs" "/org/gnu/emacs" "org.gnu.emacs")))
|
||||
|
||||
usage: (dbus-send-signal BUS SIGNAL SERVICE PATH INTERFACE &rest ARGS) */)
|
||||
(nargs, args)
|
||||
int nargs;
|
||||
register Lisp_Object *args;
|
||||
{
|
||||
Lisp_Object bus, signal, service, path, interface;
|
||||
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
|
||||
DBusConnection *connection;
|
||||
DBusMessage *dmessage;
|
||||
uint dtype;
|
||||
int i;
|
||||
char *value;
|
||||
|
||||
/* Check parameters. */
|
||||
bus = args[0];
|
||||
signal = args[1];
|
||||
service = args[2];
|
||||
path = args[3];
|
||||
interface = args[4];
|
||||
|
||||
CHECK_SYMBOL (bus);
|
||||
CHECK_STRING (signal);
|
||||
CHECK_STRING (service);
|
||||
CHECK_STRING (path);
|
||||
CHECK_STRING (interface);
|
||||
GCPRO5 (bus, signal, service, path, interface);
|
||||
|
||||
XD_DEBUG_MESSAGE ("%s %s %s %s",
|
||||
SDATA (signal),
|
||||
SDATA (service),
|
||||
SDATA (path),
|
||||
SDATA (interface));
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
connection = xd_initialize (bus);
|
||||
|
||||
/* Create the message. */
|
||||
dmessage = dbus_message_new_signal (SDATA (path),
|
||||
SDATA (interface),
|
||||
SDATA (signal));
|
||||
if (dmessage == NULL)
|
||||
{
|
||||
UNGCPRO;
|
||||
xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
|
||||
}
|
||||
|
||||
UNGCPRO;
|
||||
|
||||
/* Append parameters to the message. */
|
||||
for (i = 5; i < nargs; ++i)
|
||||
{
|
||||
XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
|
||||
XD_DEBUG_MESSAGE ("Parameter%d %s",
|
||||
i-4,
|
||||
SDATA (format2 ("%s", args[i], Qnil)));
|
||||
|
||||
dtype = XD_LISP_OBJECT_TO_DBUS_TYPE (args[i]);
|
||||
if (dtype == DBUS_TYPE_INVALID)
|
||||
xsignal2 (Qdbus_error, build_string ("Not a valid argument"), args[i]);
|
||||
|
||||
value = (char *) xd_retrieve_value (dtype, args[i]);
|
||||
|
||||
if (!dbus_message_append_args (dmessage,
|
||||
dtype,
|
||||
&value,
|
||||
DBUS_TYPE_INVALID))
|
||||
xsignal2 (Qdbus_error,
|
||||
build_string ("Unable to append argument"), args[i]);
|
||||
}
|
||||
|
||||
/* Send the message. The message is just added to the outgoing
|
||||
message queue. */
|
||||
if (!dbus_connection_send (connection, dmessage, NULL))
|
||||
xsignal1 (Qdbus_error, build_string ("Cannot send message"));
|
||||
|
||||
/* Flush connection to ensure the message is handled. */
|
||||
dbus_connection_flush (connection);
|
||||
|
||||
XD_DEBUG_MESSAGE ("Signal sent");
|
||||
|
||||
/* Cleanup. */
|
||||
dbus_message_unref (dmessage);
|
||||
|
||||
/* Return. */
|
||||
return Qt;
|
||||
}
|
||||
|
||||
/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
|
||||
symbol, either :system or :session. */
|
||||
void
|
||||
xd_read_message (bus)
|
||||
Lisp_Object bus;
|
||||
{
|
||||
Lisp_Object symbol;
|
||||
struct gcpro gcpro1;
|
||||
static struct input_event event;
|
||||
DBusConnection *connection;
|
||||
DBusMessage *dmessage;
|
||||
DBusMessageIter iter;
|
||||
uint dtype;
|
||||
char s1[1024], s2[1024];
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
connection = xd_initialize (bus);
|
||||
|
||||
/* Non blocking read of the next available message. */
|
||||
dbus_connection_read_write (connection, 0);
|
||||
dmessage = dbus_connection_pop_message (connection);
|
||||
|
||||
/* Return if there is no queued message. */
|
||||
if (dmessage == NULL)
|
||||
return;
|
||||
|
||||
/* There is a message in the queue. Construct the D-Bus event. */
|
||||
XD_DEBUG_MESSAGE ("Event received");
|
||||
EVENT_INIT (event);
|
||||
|
||||
event.kind = DBUS_EVENT;
|
||||
event.frame_or_window = Qnil;
|
||||
|
||||
/* Collect the parameters. */
|
||||
event.arg = Qnil;
|
||||
GCPRO1 (event.arg);
|
||||
|
||||
if (!dbus_message_iter_init (dmessage, &iter))
|
||||
{
|
||||
UNGCPRO;
|
||||
XD_DEBUG_MESSAGE ("Cannot read event");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Loop over the resulting parameters. Construct a list. */
|
||||
while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
event.arg = Fcons (xd_retrieve_arg (dtype, &iter), event.arg);
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
/* The arguments are stored in reverse order. Reorder them. */
|
||||
event.arg = Fnreverse (event.arg);
|
||||
|
||||
/* Add the object path of the sender of the message. */
|
||||
strcpy (s1, dbus_message_get_path (dmessage));
|
||||
event.arg = Fcons ((s1 == NULL ? Qnil : build_string (s1)), event.arg);
|
||||
|
||||
/* Add the unique name of the sender of the message. */
|
||||
strcpy (s2, dbus_message_get_sender (dmessage));
|
||||
event.arg = Fcons ((s2 == NULL ? Qnil : build_string (s2)), event.arg);
|
||||
|
||||
/* Add the interned symbol the message is raised from (signal) or
|
||||
for (method). */
|
||||
strcpy (s1, dbus_message_get_interface (dmessage));
|
||||
strcpy (s2, dbus_message_get_member (dmessage));
|
||||
XD_SYMBOL_INTERN_SYMBOL
|
||||
(symbol, bus,
|
||||
(s1 == NULL ? Qnil : build_string (s1)),
|
||||
(s2 == NULL ? Qnil : build_string (s2)));
|
||||
event.arg = Fcons (symbol, event.arg);
|
||||
|
||||
/* Store it into the input event queue. */
|
||||
kbd_buffer_store_event (&event);
|
||||
|
||||
/* Cleanup. */
|
||||
dbus_message_unref (dmessage);
|
||||
UNGCPRO;
|
||||
}
|
||||
|
||||
/* Read queued incoming messages from the system and session buses. */
|
||||
void
|
||||
xd_read_queued_messages ()
|
||||
{
|
||||
xd_read_message (Qdbus_system_bus);
|
||||
xd_read_message (Qdbus_session_bus);
|
||||
}
|
||||
|
||||
DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
|
||||
6, 6, 0,
|
||||
doc: /* Register for signal SIGNAL on the D-Bus BUS.
|
||||
|
||||
BUS is either the symbol `:system' or the symbol `:session'.
|
||||
|
||||
SERVICE is the D-Bus service name to be used. PATH is the D-Bus
|
||||
object path SERVICE is registered. INTERFACE is an interface offered
|
||||
by SERVICE. It must provide SIGNAL.
|
||||
|
||||
HANDLER is a Lisp function to be called when the signal is received.
|
||||
It must accept as arguments the values SIGNAL is sending.
|
||||
|
||||
Example:
|
||||
|
||||
\(defun my-signal-handler (device)
|
||||
(message "Device %s added" device))
|
||||
|
||||
\(dbus-register-signal
|
||||
:system "DeviceAdded" "org.freedesktop.Hal"
|
||||
"/org/freedesktop/Hal/Manager" "org.freedesktop.Hal.Manager"
|
||||
'my-signal-handler)
|
||||
|
||||
=> org.freedesktop.Hal.Manager.DeviceAdded
|
||||
|
||||
`dbus-register-signal' returns an object, which can be used in
|
||||
`dbus-unregister-signal' for removing the registration. */)
|
||||
(bus, signal, service, path, interface, handler)
|
||||
Lisp_Object bus, signal, service, path, interface, handler;
|
||||
{
|
||||
Lisp_Object name_owner, result;
|
||||
DBusConnection *connection;
|
||||
DBusError derror;
|
||||
char rule[1024];
|
||||
|
||||
/* Check parameters. */
|
||||
CHECK_SYMBOL (bus);
|
||||
CHECK_STRING (signal);
|
||||
CHECK_STRING (service);
|
||||
CHECK_STRING (path);
|
||||
CHECK_STRING (interface);
|
||||
CHECK_SYMBOL (handler);
|
||||
|
||||
/* Open a connection to the bus. */
|
||||
connection = xd_initialize (bus);
|
||||
|
||||
#if 0
|
||||
/* TODO: Get name owner. This is the sending service name. */
|
||||
name_owner = call2 (intern ("dbus-get-name-owner"), bus, service);
|
||||
#endif
|
||||
|
||||
/* Add a rule to the bus in order to receive related signals. */
|
||||
dbus_error_init (&derror);
|
||||
sprintf (rule,
|
||||
"type='signal',interface='%s',member=%s%",
|
||||
SDATA (interface),
|
||||
SDATA (signal));
|
||||
#if 0
|
||||
/* TODO: We need better checks when we want use sender and path. */
|
||||
sprintf (rule,
|
||||
"type='signal',sender='%s',path='%s',interface='%s',member=%s%",
|
||||
SDATA (name_owner),
|
||||
SDATA (path),
|
||||
SDATA (interface),
|
||||
SDATA (signal));
|
||||
#endif
|
||||
dbus_bus_add_match (connection, rule, &derror);
|
||||
|
||||
if (dbus_error_is_set (&derror))
|
||||
XD_ERROR (derror);
|
||||
|
||||
XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
|
||||
|
||||
/* Create a new protected symbol, which has the complete name of the
|
||||
signal. The function cell is taken from the handler. */
|
||||
result = Qnil;
|
||||
|
||||
XD_SYMBOL_INTERN_SYMBOL (result, bus, interface, signal);
|
||||
Ffset (result, Fsymbol_function (handler));
|
||||
XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"",
|
||||
SDATA (format2 ("%s", result, Qnil)),
|
||||
SDATA (format2 ("%s", Fsymbol_function (result), Qnil)));
|
||||
|
||||
/* Return. */
|
||||
return result;
|
||||
}
|
||||
|
||||
DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal,
|
||||
1, 1, 0,
|
||||
doc: /* Unregister OBJECT from the D-Bus.
|
||||
OBJECT must be the result of a preceding `dbus-register-signal' call. */)
|
||||
(object)
|
||||
Lisp_Object object;
|
||||
{
|
||||
|
||||
/* Check parameters. */
|
||||
CHECK_SYMBOL (object);
|
||||
|
||||
XD_DEBUG_MESSAGE ("\"%s\" unregistered with handler \"%s\"",
|
||||
SDATA (format2 ("%s", object, Qnil)),
|
||||
SDATA (format2 ("%s", Fsymbol_function (object), Qnil)));
|
||||
|
||||
/* Unintern the signal symbol. */
|
||||
Funintern (object, Vdbus_intern_symbols);
|
||||
|
||||
/* Return. */
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
syms_of_dbusbind ()
|
||||
{
|
||||
|
||||
Qdbus_get_unique_name = intern ("dbus-get-unique-name");
|
||||
staticpro (&Qdbus_get_unique_name);
|
||||
defsubr (&Sdbus_get_unique_name);
|
||||
|
||||
Qdbus_call_method = intern ("dbus-call-method");
|
||||
staticpro (&Qdbus_call_method);
|
||||
defsubr (&Sdbus_call_method);
|
||||
|
||||
Qdbus_send_signal = intern ("dbus-send-signal");
|
||||
staticpro (&Qdbus_send_signal);
|
||||
defsubr (&Sdbus_send_signal);
|
||||
|
||||
Qdbus_register_signal = intern ("dbus-register-signal");
|
||||
staticpro (&Qdbus_register_signal);
|
||||
defsubr (&Sdbus_register_signal);
|
||||
|
||||
Qdbus_unregister_signal = intern ("dbus-unregister-signal");
|
||||
staticpro (&Qdbus_unregister_signal);
|
||||
defsubr (&Sdbus_unregister_signal);
|
||||
|
||||
Qdbus_error = intern ("dbus-error");
|
||||
staticpro (&Qdbus_error);
|
||||
Fput (Qdbus_error, Qerror_conditions,
|
||||
list2 (Qdbus_error, Qerror));
|
||||
Fput (Qdbus_error, Qerror_message,
|
||||
build_string ("D-Bus error"));
|
||||
|
||||
Qdbus_system_bus = intern (":system");
|
||||
staticpro (&Qdbus_system_bus);
|
||||
|
||||
Qdbus_session_bus = intern (":session");
|
||||
staticpro (&Qdbus_session_bus);
|
||||
|
||||
Vdbus_intern_symbols = Fmake_vector (make_number (64), 0);
|
||||
staticpro (&Vdbus_intern_symbols);
|
||||
|
||||
DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
|
||||
doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
|
||||
#ifdef DBUS_DEBUG
|
||||
Vdbus_debug = Qt;
|
||||
#else
|
||||
Vdbus_debug = Qnil;
|
||||
#endif
|
||||
|
||||
Fprovide (intern ("dbusbind"), Qnil);
|
||||
|
||||
}
|
||||
|
||||
#endif /* HAVE_DBUS */
|
|
@ -353,7 +353,7 @@ int fatal_error_in_progress;
|
|||
void (*fatal_error_signal_hook) P_ ((void));
|
||||
|
||||
#ifdef HAVE_GTK_AND_PTHREAD
|
||||
/* When compiled with GTK and running under Gnome, multiple threads meay be
|
||||
/* When compiled with GTK and running under Gnome, multiple threads may be
|
||||
created. Keep track of our main thread to make sure signals are delivered
|
||||
to it (see syssignal.h). */
|
||||
|
||||
|
@ -1639,6 +1639,10 @@ main (argc, argv
|
|||
syms_of_fontset ();
|
||||
#endif /* MAC_OSX && HAVE_CARBON */
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
syms_of_dbusbind ();
|
||||
#endif /* HAVE_DBUS */
|
||||
|
||||
#ifdef SYMS_SYSTEM
|
||||
SYMS_SYSTEM;
|
||||
#endif
|
||||
|
|
|
@ -514,7 +514,9 @@ Lisp_Object Qsave_session;
|
|||
#ifdef MAC_OS
|
||||
Lisp_Object Qmac_apple_event;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
Lisp_Object Qdbus_event;
|
||||
#endif
|
||||
/* Lisp_Object Qmouse_movement; - also an event header */
|
||||
|
||||
/* Properties of event headers. */
|
||||
|
@ -1570,7 +1572,7 @@ command_loop_1 ()
|
|||
#ifdef MULTI_KBOARD
|
||||
int was_locked = single_kboard;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
int already_adjusted = 0;
|
||||
|
||||
current_kboard->Vprefix_arg = Qnil;
|
||||
|
@ -2566,7 +2568,7 @@ do { if (polling_stopped_here) start_polling (); \
|
|||
USED_MOUSE_MENU is null, we don't dereference it.
|
||||
|
||||
Value is -2 when we find input on another keyboard. A second call
|
||||
to read_char will read it.
|
||||
to read_char will read it.
|
||||
|
||||
If END_TIME is non-null, it is a pointer to an EMACS_TIME
|
||||
specifying the maximum time to wait until. If no input arrives by
|
||||
|
@ -3181,7 +3183,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
|
|||
int count = SPECPDL_INDEX ();
|
||||
record_single_kboard_state ();
|
||||
#endif
|
||||
|
||||
|
||||
last_input_char = c;
|
||||
Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
|
||||
|
||||
|
@ -4097,7 +4099,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
|
|||
events. */
|
||||
if (CONSP (Vunread_command_events))
|
||||
break;
|
||||
|
||||
|
||||
if (kbd_fetch_ptr != kbd_store_ptr)
|
||||
break;
|
||||
#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
|
||||
|
@ -4309,6 +4311,13 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
|
|||
internal_last_event_frame = frame;
|
||||
kbd_fetch_ptr = event + 1;
|
||||
}
|
||||
#ifdef HAVE_DBUS
|
||||
else if (event->kind == DBUS_EVENT)
|
||||
{
|
||||
obj = make_lispy_event (event);
|
||||
kbd_fetch_ptr = event + 1;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* If this event is on a different frame, return a switch-frame this
|
||||
|
@ -6187,6 +6196,13 @@ make_lispy_event (event)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
case DBUS_EVENT:
|
||||
{
|
||||
return Fcons (Qdbus_event, event->arg);
|
||||
}
|
||||
#endif /* HAVE_DBUS */
|
||||
|
||||
#ifdef HAVE_GPM
|
||||
case GPM_CLICK_EVENT:
|
||||
{
|
||||
|
@ -7001,6 +7017,11 @@ void
|
|||
gobble_input (expected)
|
||||
int expected;
|
||||
{
|
||||
#ifdef HAVE_DBUS
|
||||
/* Check whether a D-Bus message has arrived. */
|
||||
xd_read_queued_messages ();
|
||||
#endif /* HAVE_DBUS */
|
||||
|
||||
#ifndef VMS
|
||||
#ifdef SIGIO
|
||||
if (interrupt_input)
|
||||
|
@ -7120,7 +7141,7 @@ read_avail_input (expected)
|
|||
nread += nr;
|
||||
expected = 0;
|
||||
}
|
||||
|
||||
|
||||
if (nr == -1) /* Not OK to read input now. */
|
||||
{
|
||||
err = 1;
|
||||
|
@ -7128,7 +7149,7 @@ read_avail_input (expected)
|
|||
else if (nr == -2) /* Non-transient error. */
|
||||
{
|
||||
/* The terminal device terminated; it should be closed. */
|
||||
|
||||
|
||||
/* Kill Emacs if this was our last terminal. */
|
||||
if (!terminal_list->next_terminal)
|
||||
/* Formerly simply reported no input, but that
|
||||
|
@ -7140,7 +7161,7 @@ read_avail_input (expected)
|
|||
group? Perhaps on systems with FIONREAD Emacs is
|
||||
alone in its group. */
|
||||
kill (getpid (), SIGHUP);
|
||||
|
||||
|
||||
/* XXX Is calling delete_terminal safe here? It calls Fdelete_frame. */
|
||||
if (t->delete_terminal_hook)
|
||||
(*t->delete_terminal_hook) (t);
|
||||
|
@ -7313,14 +7334,14 @@ tty_read_avail_input (struct terminal *terminal,
|
|||
buf.modifiers = meta_modifier;
|
||||
if (tty->meta_key != 2)
|
||||
cbuf[i] &= ~0x80;
|
||||
|
||||
|
||||
buf.code = cbuf[i];
|
||||
/* Set the frame corresponding to the active tty. Note that the
|
||||
value of selected_frame is not reliable here, redisplay tends
|
||||
to temporarily change it. */
|
||||
buf.frame_or_window = tty->top_frame;
|
||||
buf.arg = Qnil;
|
||||
|
||||
|
||||
kbd_buffer_store_event (&buf);
|
||||
/* Don't look at input that follows a C-g too closely.
|
||||
This reduces lossage due to autorepeat on C-g. */
|
||||
|
@ -9236,7 +9257,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
|
|||
last_nonmenu_event = Qnil;
|
||||
|
||||
delayed_switch_frame = Qnil;
|
||||
|
||||
|
||||
if (INTERACTIVE)
|
||||
{
|
||||
if (!NILP (prompt))
|
||||
|
@ -11252,7 +11273,7 @@ See also `current-input-mode'. */)
|
|||
new_interrupt_input = 1;
|
||||
#endif
|
||||
|
||||
if (new_interrupt_input != interrupt_input)
|
||||
if (new_interrupt_input != interrupt_input)
|
||||
{
|
||||
#ifdef POLL_FOR_INPUT
|
||||
stop_polling ();
|
||||
|
@ -11332,7 +11353,7 @@ See also `current-input-mode'. */)
|
|||
struct terminal *t = get_terminal (terminal, 1);
|
||||
struct tty_display_info *tty;
|
||||
int new_meta;
|
||||
|
||||
|
||||
if (t == NULL || t->type != output_termcap)
|
||||
return Qnil;
|
||||
tty = t->display_info.tty;
|
||||
|
@ -11344,7 +11365,7 @@ See also `current-input-mode'. */)
|
|||
else
|
||||
new_meta = 2;
|
||||
|
||||
if (tty->meta_key != new_meta)
|
||||
if (tty->meta_key != new_meta)
|
||||
{
|
||||
#ifndef DOS_NT
|
||||
/* this causes startup screen to be restored and messes with the mouse */
|
||||
|
@ -11352,7 +11373,7 @@ See also `current-input-mode'. */)
|
|||
#endif
|
||||
|
||||
tty->meta_key = new_meta;
|
||||
|
||||
|
||||
#ifndef DOS_NT
|
||||
init_sys_modes (tty);
|
||||
#endif
|
||||
|
@ -11384,7 +11405,7 @@ See also `current-input-mode'. */)
|
|||
/* this causes startup screen to be restored and messes with the mouse */
|
||||
reset_sys_modes (tty);
|
||||
#endif
|
||||
|
||||
|
||||
/* Don't let this value be out of range. */
|
||||
quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377);
|
||||
|
||||
|
@ -11394,7 +11415,7 @@ See also `current-input-mode'. */)
|
|||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
|
||||
doc: /* Set mode of reading keyboard input.
|
||||
First arg INTERRUPT non-nil means use input interrupts;
|
||||
|
@ -11793,6 +11814,11 @@ syms_of_keyboard ()
|
|||
staticpro (&Qmac_apple_event);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
Qdbus_event = intern ("dbus-event");
|
||||
staticpro (&Qdbus_event);
|
||||
#endif
|
||||
|
||||
Qmenu_enable = intern ("menu-enable");
|
||||
staticpro (&Qmenu_enable);
|
||||
Qmenu_alias = intern ("menu-alias");
|
||||
|
@ -12355,7 +12381,7 @@ here. If a mapping is defined in both the current
|
|||
`local-function-key-map' binding and this variable, then the local
|
||||
definition will take precendence. */);
|
||||
Vfunction_key_map = Fmake_sparse_keymap (Qnil);
|
||||
|
||||
|
||||
DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
|
||||
doc: /* Keymap of key translations that can override keymaps.
|
||||
This keymap works like `function-key-map', but comes after that,
|
||||
|
@ -12477,7 +12503,7 @@ and tool-bar buttons. */);
|
|||
/* Vwindow_system is left at t for now. */
|
||||
initial_kboard->next_kboard = all_kboards;
|
||||
all_kboards = initial_kboard;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12522,6 +12548,13 @@ keys_of_keyboard ()
|
|||
* "handle-select-window"); */
|
||||
initial_define_lispy_key (Vspecial_event_map, "save-session",
|
||||
"handle-save-session");
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
/* Define a special event which is raised for dbus callback
|
||||
functions. */
|
||||
initial_define_lispy_key (Vspecial_event_map, "dbus-event",
|
||||
"dbus-handle-event");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Mark the pointers in the kboard objects.
|
||||
|
|
|
@ -197,6 +197,10 @@ enum event_kind
|
|||
, GPM_CLICK_EVENT
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
, DBUS_EVENT
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
/* Generated when an APPCOMMAND event is received, in response to
|
||||
Multimedia or Internet buttons on some keyboards.
|
||||
|
@ -336,7 +340,7 @@ struct terminal
|
|||
|
||||
/* All fields before `next_terminal' should be Lisp_Object and are traced
|
||||
by the GC. All fields afterwards are ignored by the GC. */
|
||||
|
||||
|
||||
/* Chain of all terminal devices. */
|
||||
struct terminal *next_terminal;
|
||||
|
||||
|
@ -382,12 +386,12 @@ struct terminal
|
|||
|
||||
/* Terminal characteristics. */
|
||||
/* XXX Are these really used on non-termcap displays? */
|
||||
|
||||
|
||||
int must_write_spaces; /* Nonzero means spaces in the text must
|
||||
actually be output; can't just skip over
|
||||
some columns to leave them blank. */
|
||||
int fast_clear_end_of_line; /* Nonzero means terminal has a `ce' string */
|
||||
|
||||
|
||||
int line_ins_del_ok; /* Terminal can insert and delete lines */
|
||||
int char_ins_del_ok; /* Terminal can insert and delete chars */
|
||||
int scroll_region_ok; /* Terminal supports setting the scroll
|
||||
|
@ -410,24 +414,24 @@ struct terminal
|
|||
struct redisplay_interface *rif;
|
||||
|
||||
/* Frame-based redisplay interface. */
|
||||
|
||||
|
||||
/* Text display hooks. */
|
||||
|
||||
void (*cursor_to_hook) P_ ((struct frame *f, int vpos, int hpos));
|
||||
void (*raw_cursor_to_hook) P_ ((struct frame *, int, int));
|
||||
|
||||
|
||||
void (*clear_to_end_hook) P_ ((struct frame *));
|
||||
void (*clear_frame_hook) P_ ((struct frame *));
|
||||
void (*clear_end_of_line_hook) P_ ((struct frame *, int));
|
||||
|
||||
|
||||
void (*ins_del_lines_hook) P_ ((struct frame *f, int, int));
|
||||
|
||||
|
||||
void (*insert_glyphs_hook) P_ ((struct frame *f, struct glyph *s, int n));
|
||||
void (*write_glyphs_hook) P_ ((struct frame *f, struct glyph *s, int n));
|
||||
void (*delete_glyphs_hook) P_ ((struct frame *, int));
|
||||
|
||||
|
||||
void (*ring_bell_hook) P_ ((struct frame *f));
|
||||
|
||||
|
||||
void (*reset_terminal_modes_hook) P_ ((struct terminal *));
|
||||
void (*set_terminal_modes_hook) P_ ((struct terminal *));
|
||||
|
||||
|
@ -442,7 +446,7 @@ struct terminal
|
|||
Set *f to the frame the mouse is in, or zero if the mouse is in no
|
||||
Emacs frame. If it is set to zero, all the other arguments are
|
||||
garbage.
|
||||
|
||||
|
||||
If the motion started in a scroll bar, set *bar_window to the
|
||||
scroll bar's window, *part to the part the mouse is currently over,
|
||||
*x to the position of the mouse along the scroll bar, and *y to the
|
||||
|
@ -452,7 +456,7 @@ struct terminal
|
|||
row of the character cell the mouse is over.
|
||||
|
||||
Set *time to the time the mouse was at the returned position.
|
||||
|
||||
|
||||
This should clear mouse_moved until the next motion
|
||||
event arrives. */
|
||||
void (*mouse_position_hook) P_ ((struct frame **f, int,
|
||||
|
@ -478,7 +482,7 @@ struct terminal
|
|||
hook is zero, that means the terminal we're displaying on doesn't
|
||||
support overlapping frames, so there's no need to raise or lower
|
||||
anything.
|
||||
|
||||
|
||||
If RAISE is non-zero, F is brought to the front, before all other
|
||||
windows. If RAISE is zero, F is sent to the back, behind all other
|
||||
windows. */
|
||||
|
@ -488,7 +492,7 @@ struct terminal
|
|||
For example, if going from fullscreen to not fullscreen this hook
|
||||
may do something OS dependent, like extended window manager hints on X11. */
|
||||
void (*fullscreen_hook) P_ ((struct frame *f));
|
||||
|
||||
|
||||
|
||||
/* Scroll bar hooks. */
|
||||
|
||||
|
@ -497,21 +501,21 @@ struct terminal
|
|||
lisp objects. This allows us to place references to them in
|
||||
Lisp_Windows without worrying about those references becoming
|
||||
dangling references when the scroll bar is destroyed.
|
||||
|
||||
|
||||
The window-system-independent portion of Emacs just refers to
|
||||
scroll bars via their windows, and never looks inside the scroll bar
|
||||
representation; it always uses hook functions to do all the
|
||||
scroll bar manipulation it needs.
|
||||
|
||||
|
||||
The `vertical_scroll_bar' field of a Lisp_Window refers to that
|
||||
window's scroll bar, or is nil if the window doesn't have a
|
||||
scroll bar.
|
||||
|
||||
|
||||
The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame
|
||||
are free for use by the scroll bar implementation in any way it sees
|
||||
fit. They are marked by the garbage collector. */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Set the vertical scroll bar for WINDOW to have its upper left corner
|
||||
at (TOP, LEFT), and be LENGTH rows high. Set its handle to
|
||||
indicate that we are displaying PORTION characters out of a total
|
||||
|
@ -529,16 +533,16 @@ struct terminal
|
|||
Instead, we just assert at the beginning of redisplay that *all*
|
||||
scroll bars are to be removed, and then save scroll bars from the
|
||||
fiery pit when we actually redisplay their window. */
|
||||
|
||||
|
||||
/* Arrange for all scroll bars on FRAME to be removed at the next call
|
||||
to `*judge_scroll_bars_hook'. A scroll bar may be spared if
|
||||
`*redeem_scroll_bar_hook' is applied to its window before the judgement.
|
||||
|
||||
|
||||
This should be applied to each frame each time its window tree is
|
||||
redisplayed, even if it is not displaying scroll bars at the moment;
|
||||
if the HAS_SCROLL_BARS flag has just been turned off, only calling
|
||||
this and the judge_scroll_bars_hook will get rid of them.
|
||||
|
||||
|
||||
If non-zero, this hook should be safe to apply to any frame,
|
||||
whether or not it can support scroll bars, and whether or not it is
|
||||
currently displaying them. */
|
||||
|
@ -555,7 +559,7 @@ struct terminal
|
|||
tree is redisplayed, even if it is not displaying scroll bars at the
|
||||
moment; if the HAS_SCROLL_BARS flag has just been turned off, only
|
||||
calling this and condemn_scroll_bars_hook will get rid of them.
|
||||
|
||||
|
||||
If non-zero, this hook should be safe to apply to any frame,
|
||||
whether or not it can support scroll bars, and whether or not it is
|
||||
currently displaying them. */
|
||||
|
@ -595,7 +599,7 @@ struct terminal
|
|||
|
||||
/* Called after the last frame on this terminal is deleted, or when
|
||||
the display device was closed (hangup).
|
||||
|
||||
|
||||
If this is NULL, then the generic delete_terminal is called
|
||||
instead. Otherwise the hook must call delete_terminal itself.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue