summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2001-06-25 23:01:36 +0000
committerAlexander Larsson <alexl@src.gnome.org>2001-06-25 23:01:36 +0000
commit75fd7f09af9de7691ef46e12cad6ac243298c16e (patch)
tree1da19b6e074adcbbf53cbfdf4b88f803cc42a33f
parent4168b4780317921000f88d2e58f2b66ae6ce7038 (diff)
downloadgdk-pixbuf-75fd7f09af9de7691ef46e12cad6ac243298c16e.tar.gz
Added --enable-fbmanager. This is some experimental code that lets several
2001-06-25 Alexander Larsson <alexl@redhat.com> * configure.in: Added --enable-fbmanager. This is some experimental code that lets several GtkFB apps coordinate their access to the framebuffer. * acconfig.h: Added ENABLE_FB_MANAGER. * gdk/linux-fb/Makefile.am: Added gdkfbmanager and gdkfbswitch. * gdk/linux-fb/gdkkeyboard-fb.c: * gdk/linux-fb/gdkmouse-fb.c: * gdk/linux-fb/gdkprivate-fb.h: Split device init and open so that they can be opened and closed while switched away. * gdk/linux-fb/gdkmain-fb.c: Add the basic manager communication. * gdk/linux-fb/gdkrender-fb.c: Don't update to the shadow fb if we're blocked by the fb manager.
-rw-r--r--ChangeLog27
-rw-r--r--ChangeLog.pre-2-027
-rw-r--r--ChangeLog.pre-2-1027
-rw-r--r--ChangeLog.pre-2-227
-rw-r--r--ChangeLog.pre-2-427
-rw-r--r--ChangeLog.pre-2-627
-rw-r--r--ChangeLog.pre-2-827
-rw-r--r--acconfig.h3
-rw-r--r--configure.in10
-rw-r--r--gdk/linux-fb/Makefile.am15
-rw-r--r--gdk/linux-fb/gdkfbmanager.c406
-rw-r--r--gdk/linux-fb/gdkfbmanager.h37
-rw-r--r--gdk/linux-fb/gdkfbswitch.c75
-rw-r--r--gdk/linux-fb/gdkkeyboard-fb.c31
-rw-r--r--gdk/linux-fb/gdkmain-fb.c166
-rw-r--r--gdk/linux-fb/gdkmouse-fb.c73
-rw-r--r--gdk/linux-fb/gdkprivate-fb.h8
-rw-r--r--gdk/linux-fb/gdkrender-fb.c3
18 files changed, 977 insertions, 39 deletions
diff --git a/ChangeLog b/ChangeLog
index e94c717f1..a91bdb655 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index e94c717f1..a91bdb655 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,30 @@
+2001-06-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.in:
+ Added --enable-fbmanager. This is some experimental code
+ that lets several GtkFB apps coordinate their access to the
+ framebuffer.
+
+ * acconfig.h:
+ Added ENABLE_FB_MANAGER.
+
+ * gdk/linux-fb/Makefile.am:
+ Added gdkfbmanager and gdkfbswitch.
+
+ * gdk/linux-fb/gdkkeyboard-fb.c:
+ * gdk/linux-fb/gdkmouse-fb.c:
+ * gdk/linux-fb/gdkprivate-fb.h:
+ Split device init and open so that
+ they can be opened and closed while switched
+ away.
+
+ * gdk/linux-fb/gdkmain-fb.c:
+ Add the basic manager communication.
+
+ * gdk/linux-fb/gdkrender-fb.c:
+ Don't update to the shadow fb if we're
+ blocked by the fb manager.
+
Sun Jun 24 22:15:16 2001 Owen Taylor <otaylor@redhat.com>
* docs/Changes-2.0.txt: Add note about child property
diff --git a/acconfig.h b/acconfig.h
index f2f4b4a1e..37cd31587 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -50,6 +50,9 @@
/* Define to use shadowfb in the linux-fb port */
#undef ENABLE_SHADOW_FB
+/* Define to use a fb manager in the linux-fb port */
+#undef ENABLE_FB_MANAGER
+
#undef XINPUT_NONE
#undef XINPUT_GXI
#undef XINPUT_XFREE
diff --git a/configure.in b/configure.in
index 3b8eba5d7..1f7e1a942 100644
--- a/configure.in
+++ b/configure.in
@@ -135,6 +135,8 @@ case $gdktarget in
esac
AC_ARG_ENABLE(shadowfb, [ --disable-shadowfb disable shadowfb support for linux-fb],,enable_shadowfb=yes)
+
+AC_ARG_ENABLE(fbmanager, [ --enable-fbmanager enable framebuffer manager support (GtkFB)],enable_fbmanager=yes,enable_fbmanager=no)
if test "x$enable_debug" = "xyes"; then
test "$cflags_set" = set || CFLAGS="$CFLAGS -g"
@@ -852,6 +854,13 @@ if test "x$gdktarget" = "xlinux-fb"; then
if test x$enable_shadowfb = xyes ; then
AC_DEFINE(ENABLE_SHADOW_FB)
fi
+
+ if test x$enable_fbmanager = xyes ; then
+ AC_DEFINE(ENABLE_FB_MANAGER)
+ AM_CONDITIONAL(ENABLE_FB_MANAGER, true)
+ else
+ AM_CONDITIONAL(ENABLE_FB_MANAGER, false)
+ fi
GDK_EXTRA_CFLAGS="$FREETYPE_CFLAGS"
GDK_EXTRA_LIBS="$FREETYPE_LIBS $GDK_EXTRA_LIBS"
@@ -859,6 +868,7 @@ if test "x$gdktarget" = "xlinux-fb"; then
AM_CONDITIONAL(USE_LINUX_FB, true)
else
AM_CONDITIONAL(USE_LINUX_FB, false)
+ AM_CONDITIONAL(ENABLE_FB_MANAGER, false)
fi
AC_SUBST(gdktargetlib)
diff --git a/gdk/linux-fb/Makefile.am b/gdk/linux-fb/Makefile.am
index 795f15d9a..4e0f37eb2 100644
--- a/gdk/linux-fb/Makefile.am
+++ b/gdk/linux-fb/Makefile.am
@@ -1,5 +1,11 @@
## Process this file with automake to produce Makefile.in
+if ENABLE_FB_MANAGER
+bin_PROGRAMS = gdkfbmanager gdkfbswitch
+else
+bin_PROGRAMS =
+endif
+
libgdkincludedir = $(includedir)/gtk-2.0/gdk
libgdkfbincludedir = $(includedir)/gtk-2.0/gdk/linux-fb
@@ -61,14 +67,17 @@ libgdk_linux_fb_la_SOURCES = \
mipolyutil.c \
miscanfill.h \
mispans.h \
+ mispans.c \
mistruct.h \
mitypes.h \
miwideline.c \
miwideline.h \
mizerclip.c \
mizerline.c \
- mispans.c \
- gdkpango-fb.c
- mispans.c
+ gdkpango-fb.c \
+ gdkfbmanager.h
+
+gdkfbmanager_sources = gdkfbmanager.c
+gdkfbswitch_sources = gdkfbswitch.c
EXTRA_DIST=x-cursors.xbm
diff --git a/gdk/linux-fb/gdkfbmanager.c b/gdk/linux-fb/gdkfbmanager.c
new file mode 100644
index 000000000..23cc49501
--- /dev/null
+++ b/gdk/linux-fb/gdkfbmanager.c
@@ -0,0 +1,406 @@
+#include <glib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "gdkfbmanager.h"
+
+typedef struct {
+ int socket;
+ int pid; /* -1 if not initialized */
+} Client;
+
+GHashTable *clients = NULL;
+GHashTable *new_clients = NULL;
+Client *current_owner = NULL;
+
+int master_socket;
+
+int create_master_socket (void)
+{
+ int fd;
+ struct sockaddr_un addr;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+
+ if (fd < 0)
+ {
+ printf ("Error creating socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+ unlink ("/tmp/.fb.manager");
+
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, "/tmp/.fb.manager");
+
+ if (bind(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0)
+ {
+ printf ("Unable to bind socket: %s\n", strerror(errno));
+ close (fd);
+ return -1;
+ }
+
+
+ if (listen (fd, 10) < 0)
+ {
+ printf ("Unable to listen on socket: %s\n", strerror(errno));
+ close (fd);
+ return -1;
+ }
+
+ master_socket = fd;
+ return 0;
+}
+
+void
+handle_new_client (void)
+{
+ int fd;
+ Client *client;
+ int true_val;
+
+ fd = accept (master_socket, NULL, NULL);
+
+ client = g_new (Client, 1);
+ client->socket = fd;
+ client->pid = -1;
+
+ true_val = 1;
+ setsockopt (fd, SOL_SOCKET, SO_PASSCRED,
+ &true_val, sizeof (true_val));
+
+ g_print ("Handling new client %p conntecting, fd = %d\n", client, fd);
+
+ g_hash_table_insert (new_clients, client, client);
+}
+
+struct fd_data
+{
+ fd_set *read_fds;
+ fd_set *exception_fds;
+ int max_fd;
+};
+
+void
+send_message (Client *client, enum FBManagerMessageType type, int data)
+{
+ struct FBManagerMessage msg;
+
+ msg.msg_type = type;
+ msg.data = data;
+
+ send (client->socket, &msg, sizeof (msg), 0);
+}
+
+gboolean
+wait_for_ack (Client *client, int timeout_secs)
+{
+ struct FBManagerMessage msg;
+ int res;
+ fd_set rfds;
+ struct timeval tv;
+
+ while (1)
+ {
+ FD_ZERO(&rfds);
+ FD_SET(client->socket, &rfds);
+
+ tv.tv_sec = timeout_secs;
+ tv.tv_usec = 0;
+
+ res = select (client->socket+1, &rfds, NULL, NULL, &tv);
+
+ if (res == 0)
+ return FALSE;
+
+ res = recv (client->socket, &msg, sizeof (msg), 0);
+ if (res != sizeof (msg))
+ return FALSE;
+
+ if (msg.msg_type == FB_MANAGER_ACK)
+ return TRUE;
+ }
+}
+
+void
+find_another_client (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ Client **res;
+ Client *client;
+
+ res = user_data;
+
+ if (*res)
+ return;
+
+ client = value;
+ if (client != current_owner)
+ *res = client;
+}
+
+void
+switch_to_client (Client *client)
+{
+ g_print ("Switch_to_client, client=%p, current_owner=%p\n", client, current_owner);
+
+ if ((current_owner == client) && (client != NULL))
+ return;
+
+ if (current_owner)
+ {
+ g_print ("switching from client fd=%d\n", current_owner->socket);
+ send_message (current_owner, FB_MANAGER_SWITCH_FROM, 0);
+ wait_for_ack (current_owner, 3);
+ }
+
+ current_owner = client;
+
+ if (current_owner)
+ {
+ g_print ("switching to client fd=%d\n", current_owner->socket);
+ send_message (current_owner, FB_MANAGER_SWITCH_TO, 0);
+ }
+}
+
+void
+close_client (Client *client)
+{
+ Client *other_client;
+ g_print ("Closing client %p (fd=%d)\n",
+ client, client->socket);
+
+ if (current_owner == client)
+ {
+ other_client = NULL;
+ g_hash_table_foreach (clients,
+ find_another_client,
+ &other_client);
+ current_owner = NULL;
+ /* FIXME: This is a hack around the fact that the serial
+ mouse driver had problems with opening and closing
+ the device almost at the same time.
+ */
+ sleep (1);
+ switch_to_client (other_client);
+ }
+
+ close (client->socket);
+ g_free (client);
+}
+
+
+/* Returns TRUE if the client was closed */
+gboolean
+read_client_data (Client *client)
+{
+ struct FBManagerMessage fb_message;
+ struct msghdr msg;
+ struct iovec iov;
+ char control_buffer[256];
+ struct cmsghdr *cmsg;
+ int res;
+ struct ucred *creds;
+ Client *new_client;
+
+ iov.iov_base = &fb_message;
+ iov.iov_len = sizeof (fb_message);
+
+ cmsg = (struct cmsghdr *)control_buffer;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg;
+ msg.msg_controllen = 256;
+ msg.msg_flags = 0;
+
+ g_print ("Reading client data:");
+ res = recvmsg (client->socket, &msg, 0);
+ g_print ("%d bytes, (error: %s)\n", res,
+ strerror (errno));
+
+ if (res < 0)
+ return FALSE;
+
+ if (res == 0)
+ {
+ close_client (client);
+ return TRUE;
+ }
+
+ if (res != sizeof (fb_message))
+ {
+ g_warning ("Packet with wrong size %d recieved", res);
+ return FALSE;
+ }
+
+ switch (fb_message.msg_type) {
+ case FB_MANAGER_NEW_CLIENT:
+ if (client->pid != -1)
+ {
+ g_warning ("Got a NEW_CLIENT message from an old client");
+ return FALSE;
+ }
+ creds = NULL;
+ for (cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg,cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_CREDENTIALS)
+ {
+ creds = (struct ucred *) CMSG_DATA(cmsg);
+ break;
+ }
+ }
+ if (creds == NULL)
+ {
+ g_warning ("Got no credentials in NEW_CLIENT message");
+ close_client (client);
+ return TRUE;
+ }
+ client->pid = creds->pid;
+
+ g_hash_table_insert (clients, GINT_TO_POINTER (client->pid), client);
+
+ g_print ("New client connected. Pid=%d\n", (int)creds->pid);
+ return TRUE;
+ break;
+ case FB_MANAGER_REQUEST_SWITCH_TO_PID:
+ if (client->pid == -1)
+ {
+ g_warning ("Got a message from an uninitialized client");
+ return FALSE;
+ }
+
+ new_client = g_hash_table_lookup (clients, GINT_TO_POINTER (fb_message.data));
+ if (new_client)
+ switch_to_client (new_client);
+ else
+ g_warning ("Switchto unknown PID");
+ break;
+ case FB_MANAGER_ACK:
+ if (client->pid == -1)
+ {
+ g_warning ("Got a message from an uninitialized client");
+ return FALSE;
+ }
+ g_warning ("Got an unexpected ACK");
+ break;
+ default:
+ g_warning ("Got unknown package type %d", fb_message.msg_type);
+ break;
+ }
+ return FALSE;
+}
+
+/* Returns TRUE if the client was closed */
+gboolean
+handle_client_data (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ Client *client;
+ struct fd_data *data;
+
+ client = value;
+ data = user_data;
+
+ if (FD_ISSET (client->socket, data->exception_fds))
+ {
+ close_client (client);
+ return TRUE;
+ }
+ else if (FD_ISSET (client->socket, data->read_fds))
+ {
+ return read_client_data (client);
+ }
+
+ return FALSE;
+}
+
+void
+set_fds (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ struct fd_data *data;
+ Client *client;
+
+ client = value;
+ data = user_data;
+
+ FD_SET (client->socket, data->read_fds);
+ FD_SET (client->socket, data->exception_fds);
+ data->max_fd = MAX (data->max_fd,
+ client->socket);
+}
+
+void
+main_loop (void)
+{
+ fd_set read_fds;
+ fd_set exception_fds;
+ struct fd_data data;
+ int res;
+
+ while (1)
+ {
+ FD_ZERO (&read_fds);
+ FD_ZERO (&exception_fds);
+ FD_SET (master_socket, &read_fds);
+
+ data.read_fds = &read_fds;
+ data.exception_fds = &exception_fds;
+ data.max_fd = master_socket;
+
+ g_hash_table_foreach (clients,
+ set_fds,
+ &data);
+ g_hash_table_foreach (new_clients,
+ set_fds,
+ &data);
+
+
+ res = select (data.max_fd+1,
+ &read_fds, NULL, &exception_fds,
+ NULL);
+
+ if (FD_ISSET (master_socket, &read_fds))
+ handle_new_client ();
+
+ g_hash_table_foreach_remove (clients,
+ handle_client_data,
+ &data);
+ g_hash_table_foreach_remove (new_clients,
+ handle_client_data,
+ &data);
+ }
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ clients = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+ new_clients = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+
+ create_master_socket ();
+
+ main_loop ();
+
+ return 0;
+}
diff --git a/gdk/linux-fb/gdkfbmanager.h b/gdk/linux-fb/gdkfbmanager.h
new file mode 100644
index 000000000..653a1c69c
--- /dev/null
+++ b/gdk/linux-fb/gdkfbmanager.h
@@ -0,0 +1,37 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GDK_FB_MANAGER_H__
+#define __GDK_FB_MANAGER_H__
+
+enum FBManagerMessageType {
+ /* manager -> client */
+ FB_MANAGER_SWITCH_TO,
+ FB_MANAGER_SWITCH_FROM, /* requires ack */
+
+ /* client -> manager */
+ FB_MANAGER_NEW_CLIENT,
+ FB_MANAGER_REQUEST_SWITCH_TO_PID,
+ FB_MANAGER_ACK,
+};
+
+struct FBManagerMessage {
+ enum FBManagerMessageType msg_type;
+ int data;
+};
+#endif /* __GDK_FB_MANAGER_H__ */
diff --git a/gdk/linux-fb/gdkfbswitch.c b/gdk/linux-fb/gdkfbswitch.c
new file mode 100644
index 000000000..707325f8f
--- /dev/null
+++ b/gdk/linux-fb/gdkfbswitch.c
@@ -0,0 +1,75 @@
+#include <glib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "gdkfbmanager.h"
+
+int
+main (int argc, char *argv[])
+{
+ int fd;
+ struct sockaddr_un addr;
+ struct msghdr msg = {0};
+ struct cmsghdr *cmsg;
+ struct ucred credentials;
+ struct FBManagerMessage init_msg;
+ struct iovec iov;
+ char buf[CMSG_SPACE (sizeof (credentials))]; /* ancillary data buffer */
+ int *fdptr;
+ int res;
+
+ if (argc != 2)
+ {
+ g_print ("usage: fbswitch <pid>\n");
+ return 1;
+ }
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+
+ if (fd < 0)
+ return 1;
+
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, "/tmp/.fb.manager");
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0)
+ {
+ g_print ("connect failed\n");
+ close (fd);
+ return 1;
+ }
+
+ credentials.pid = getpid ();
+ credentials.uid = geteuid ();
+ credentials.gid = getegid ();
+
+ init_msg.msg_type = FB_MANAGER_NEW_CLIENT;
+ iov.iov_base = &init_msg;
+ iov.iov_len = sizeof (init_msg);
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof buf;
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_CREDENTIALS;
+ cmsg->cmsg_len = CMSG_LEN (sizeof (credentials));
+ /* Initialize the payload: */
+ fdptr = (int *)CMSG_DATA (cmsg);
+ memcpy (fdptr, &credentials, sizeof (credentials));
+ /* Sum of the length of all control messages in the buffer: */
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ res = sendmsg (fd, &msg, 0);
+
+ init_msg.msg_type = FB_MANAGER_REQUEST_SWITCH_TO_PID;
+ init_msg.data = atoi (argv[1]);
+ /* Request a switch-to */
+ send (fd, &init_msg, sizeof (init_msg), 0);
+ g_print ("requested a switch to pid %d\n", init_msg.data);
+}
diff --git a/gdk/linux-fb/gdkkeyboard-fb.c b/gdk/linux-fb/gdkkeyboard-fb.c
index c5c8993ca..2aebfff76 100644
--- a/gdk/linux-fb/gdkkeyboard-fb.c
+++ b/gdk/linux-fb/gdkkeyboard-fb.c
@@ -167,17 +167,18 @@ gdk_fb_keyboard_modifiers ()
}
gboolean
-gdk_fb_keyboard_open (void)
+gdk_fb_keyboard_init (gboolean open_dev)
{
GdkFBKeyboard *keyb;
- GdkFBKeyboardDevice *device;
char *keyb_type;
int i;
- keyb = g_new0 (GdkFBKeyboard, 1);
+ gdk_fb_keyboard = g_new0 (GdkFBKeyboard, 1);
+ keyb = gdk_fb_keyboard;
keyb->fd = -1;
keyb_type = getenv ("GDK_KEYBOARD_TYPE");
+
if (!keyb_type)
keyb_type = "xlate";
@@ -193,19 +194,29 @@ gdk_fb_keyboard_open (void)
return FALSE;
}
- device = &keyb_devs[i];
+ keyb->dev = &keyb_devs[i];
+
+ if (open_dev)
+ return gdk_fb_keyboard_open ();
+ else
+ return TRUE;
+}
+
+gboolean
+gdk_fb_keyboard_open (void)
+{
+ GdkFBKeyboard *keyb;
+ GdkFBKeyboardDevice *device;
+
+ keyb = gdk_fb_keyboard;
+ device = keyb->dev;
- keyb->dev = device;
-
if (!device->open(keyb))
{
g_warning ("Keyboard driver open failed");
- g_free (keyb);
return FALSE;
}
- gdk_fb_keyboard = keyb;
-
return TRUE;
}
@@ -213,7 +224,6 @@ void
gdk_fb_keyboard_close (void)
{
gdk_fb_keyboard->dev->close(gdk_fb_keyboard);
- g_free (gdk_fb_keyboard);
}
@@ -903,6 +913,7 @@ xlate_close (GdkFBKeyboard *kb)
g_source_remove (kb->io_tag);
g_io_channel_unref (kb->io);
+ kb->fd = -1;
/* don't close kb->fd, it is the tty from gdk_display */
}
diff --git a/gdk/linux-fb/gdkmain-fb.c b/gdk/linux-fb/gdkmain-fb.c
index 77318ddee..6f0357e40 100644
--- a/gdk/linux-fb/gdkmain-fb.c
+++ b/gdk/linux-fb/gdkmain-fb.c
@@ -39,10 +39,14 @@
#include <sys/kd.h>
#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
#include "gdk.h"
#include "gdkprivate-fb.h"
#include "gdkinternals.h"
+#include "gdkfbmanager.h"
/* Private variable declarations
*/
@@ -484,6 +488,159 @@ gdk_fb_set_mode (GdkFBDisplay *display)
return 0;
}
+#ifdef ENABLE_FB_MANAGER
+static void
+gdk_fb_switch_from (void)
+{
+ g_print ("Switch from\n");
+ gdk_shadow_fb_stop_updates ();
+ gdk_fb_mouse_close ();
+ gdk_fb_keyboard_close ();
+}
+
+static void
+gdk_fb_switch_to (void)
+{
+ g_print ("switch_to\n");
+ gdk_shadow_fb_update (0, 0,
+ gdk_display->fb_width,
+ gdk_display->fb_height);
+
+ if (!gdk_fb_keyboard_open ())
+ g_warning ("Failed to re-initialize keyboard");
+
+ if (!gdk_fb_mouse_open ())
+ g_warning ("Failed to re-initialize mouse");
+
+}
+
+
+static gboolean
+gdk_fb_manager_callback (GIOChannel *gioc,
+ GIOCondition cond,
+ gpointer data)
+{
+ struct FBManagerMessage msg;
+ GdkFBDisplay *display;
+ int res;
+
+ display = data;
+
+ res = recv (display->manager_fd, &msg, sizeof (msg), 0);
+
+ if (res==0)
+ {
+ g_source_remove (gdk_display->manager_tag);
+ /*g_io_channel_unref (kb->io);*/
+ close (gdk_display->manager_fd);
+
+ }
+
+ if (res != sizeof (msg))
+ {
+ g_warning ("Got wrong size message");
+ return TRUE;
+ }
+
+ switch (msg.msg_type)
+ {
+ case FB_MANAGER_SWITCH_FROM:
+ g_print ("Got switch from message\n");
+ display->manager_blocked = TRUE;
+ gdk_fb_switch_from ();
+ msg.msg_type = FB_MANAGER_ACK;
+ send (display->manager_fd, &msg, sizeof (msg), 0);
+ break;
+ case FB_MANAGER_SWITCH_TO:
+ g_print ("Got switch to message\n");
+ display->manager_blocked = FALSE;
+ gdk_fb_switch_to ();
+ break;
+ default:
+ g_warning ("Got unknown message");
+ }
+ return TRUE;
+}
+
+#endif /* ENABLE_FB_MANAGER */
+
+static void
+gdk_fb_manager_connect (GdkFBDisplay *display)
+{
+ int fd;
+ struct sockaddr_un addr;
+ struct msghdr msg = {0};
+ struct cmsghdr *cmsg;
+ struct ucred credentials;
+ struct FBManagerMessage init_msg;
+ struct iovec iov;
+ char buf[CMSG_SPACE (sizeof (credentials))]; /* ancillary data buffer */
+ int *fdptr;
+ int res;
+
+ display->manager_blocked = FALSE;
+ display->manager_fd = -1;
+
+#ifdef ENABLE_FB_MANAGER
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+
+ g_print ("socket: %d\n", fd);
+
+ if (fd < 0)
+ return;
+
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, "/tmp/.fb.manager");
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0)
+ {
+ g_print ("connect failed\n");
+ close (fd);
+ return;
+ }
+
+ credentials.pid = getpid ();
+ credentials.uid = geteuid ();
+ credentials.gid = getegid ();
+
+ init_msg.msg_type = FB_MANAGER_NEW_CLIENT;
+ iov.iov_base = &init_msg;
+ iov.iov_len = sizeof (init_msg);
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof buf;
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_CREDENTIALS;
+ cmsg->cmsg_len = CMSG_LEN (sizeof (credentials));
+ /* Initialize the payload: */
+ fdptr = (int *)CMSG_DATA (cmsg);
+ memcpy (fdptr, &credentials, sizeof (credentials));
+ /* Sum of the length of all control messages in the buffer: */
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ res = sendmsg (fd, &msg, 0);
+
+ display->manager_fd = fd;
+ display->manager_blocked = TRUE;
+
+ display->manager_tag = g_io_add_watch (g_io_channel_unix_new (fd),
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ gdk_fb_manager_callback,
+ display);
+
+ init_msg.msg_type = FB_MANAGER_REQUEST_SWITCH_TO_PID;
+ init_msg.data = getpid ();
+
+ /* Request a switch-to */
+ send (fd, &init_msg, sizeof (init_msg), 0);
+#endif
+}
+
static GdkFBDisplay *
gdk_fb_display_new ()
{
@@ -658,7 +815,9 @@ _gdk_windowing_init_check (int argc, char **argv)
gdk_shadow_fb_init ();
- if (!gdk_fb_keyboard_open ())
+ gdk_fb_manager_connect (gdk_display);
+
+ if (!gdk_fb_keyboard_init (!gdk_display->manager_blocked))
{
g_warning ("Failed to initialize keyboard");
gdk_fb_display_destroy (gdk_display);
@@ -666,7 +825,7 @@ _gdk_windowing_init_check (int argc, char **argv)
return FALSE;
}
- if (!gdk_fb_mouse_open ())
+ if (!gdk_fb_mouse_init (!gdk_display->manager_blocked))
{
g_warning ("Failed to initialize mouse");
gdk_fb_keyboard_close ();
@@ -678,6 +837,7 @@ _gdk_windowing_init_check (int argc, char **argv)
gdk_initialized = TRUE;
gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
+
return TRUE;
}
@@ -1041,8 +1201,10 @@ gdk_windowing_exit (void)
{
gdk_fb_mouse_close ();
+ /*leak g_free (gdk_fb_mouse);*/
gdk_fb_keyboard_close ();
+ /*leak g_free (gdk_fb_keyboard);*/
gdk_fb_display_destroy (gdk_display);
diff --git a/gdk/linux-fb/gdkmouse-fb.c b/gdk/linux-fb/gdkmouse-fb.c
index 5e6fc3de5..e89ab67b5 100644
--- a/gdk/linux-fb/gdkmouse-fb.c
+++ b/gdk/linux-fb/gdkmouse-fb.c
@@ -27,6 +27,8 @@
#include <sys/ioctl.h>
#include <string.h>
#include <math.h>
+#include <unistd.h>
+#include <errno.h>
typedef struct _GdkFBMouse GdkFBMouse;
typedef struct _GdkFBMouseDevice GdkFBMouseDevice;
@@ -275,21 +277,19 @@ static GdkFBMouseDevice mouse_devs[] =
}
};
-
gboolean
-gdk_fb_mouse_open (void)
+gdk_fb_mouse_init (gboolean open_dev)
{
- GdkFBMouse *mouse;
- GdkFBMouseDevice *device;
char *mouse_type;
int i;
- mouse = g_new0 (GdkFBMouse, 1);
- mouse->fd = -1;
+ gdk_fb_mouse = g_new0 (GdkFBMouse, 1);
+ gdk_fb_mouse->fd = -1;
+
mouse_type = getenv ("GDK_MOUSE_TYPE");
if (!mouse_type)
mouse_type = "ps2";
-
+
for (i=0;i<G_N_ELEMENTS(mouse_devs);i++)
{
if (g_strcasecmp(mouse_type, mouse_devs[i].name)==0)
@@ -302,34 +302,56 @@ gdk_fb_mouse_open (void)
return FALSE;
}
- device = &mouse_devs[i];
+ gdk_fb_mouse->dev = &mouse_devs[i];
- mouse->dev = device;
-
- mouse->x = gdk_display->fb_width / 2;
- mouse->y = gdk_display->fb_height / 2;
+ gdk_fb_mouse->x = gdk_display->fb_width / 2;
+ gdk_fb_mouse->y = gdk_display->fb_height / 2;
+
+ if (open_dev)
+ return gdk_fb_mouse_open ();
+ else
+ return TRUE;
+}
+
+gboolean
+gdk_fb_mouse_open (void)
+{
+ GdkFBMouseDevice *device;
+
+ device = gdk_fb_mouse->dev;
- if (!device->open(mouse))
+ if (!device->open(gdk_fb_mouse))
{
g_warning ("Mouse driver open failed");
- g_free (mouse);
return FALSE;
}
- mouse->io = g_io_channel_unix_new (mouse->fd);
- mouse->io_tag = g_io_add_watch (mouse->io, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_mouse_io, mouse);
+ gdk_fb_mouse->io =
+ g_io_channel_unix_new (gdk_fb_mouse->fd);
+ gdk_fb_mouse->io_tag =
+ g_io_add_watch (gdk_fb_mouse->io,
+ G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ handle_mouse_io, gdk_fb_mouse);
- gdk_fb_mouse = mouse;
return TRUE;
}
void
gdk_fb_mouse_close (void)
{
- g_source_remove (gdk_fb_mouse->io_tag);
- gdk_fb_mouse->dev->close(gdk_fb_mouse);
- g_io_channel_unref (gdk_fb_mouse->io);
- g_free (gdk_fb_mouse);
+ if (gdk_fb_mouse->io_tag)
+ {
+ g_source_remove (gdk_fb_mouse->io_tag);
+ gdk_fb_mouse->io_tag = 0;
+ }
+
+ gdk_fb_mouse->dev->close(gdk_fb_mouse);
+
+ if (gdk_fb_mouse->io)
+ {
+ g_io_channel_unref (gdk_fb_mouse->io);
+ gdk_fb_mouse->io = NULL;
+ }
}
static gboolean
@@ -427,6 +449,7 @@ static void
gdk_fb_mouse_ps2_close (GdkFBMouse *mouse)
{
close (mouse->fd);
+ mouse->fd = -1;
}
static gboolean
@@ -500,8 +523,11 @@ gdk_fb_mouse_ms_open (GdkFBMouse *mouse)
struct termios tty;
fd = gdk_fb_mouse_dev_open ("/dev/mouse", O_RDWR);
- if (fd < 0)
- return FALSE;
+ if (fd < 0)
+ {
+ g_print ("Error opening /dev/mouse: %s\n", strerror (errno));
+ return FALSE;
+ }
while ((i = read (fd, buf, sizeof(buf))) > 0)
g_print ("Got %d bytes of junk from /dev/mouse\n", i);
@@ -526,6 +552,7 @@ static void
gdk_fb_mouse_ms_close (GdkFBMouse *mouse)
{
close (mouse->fd);
+ mouse->fd = -1;
}
static gboolean
diff --git a/gdk/linux-fb/gdkprivate-fb.h b/gdk/linux-fb/gdkprivate-fb.h
index 672ba6053..c7b12f611 100644
--- a/gdk/linux-fb/gdkprivate-fb.h
+++ b/gdk/linux-fb/gdkprivate-fb.h
@@ -148,6 +148,11 @@ struct _GdkFBDisplay
struct fb_var_screeninfo modeinfo;
struct fb_var_screeninfo orig_modeinfo;
int red_byte, green_byte, blue_byte; /* For truecolor */
+
+ /* fb manager */
+ int manager_fd;
+ int manager_tag;
+ int manager_blocked;
};
typedef struct {
@@ -414,7 +419,6 @@ extern GdkEventMask _gdk_fb_keyboard_grab_events;
extern gboolean _gdk_fb_keyboard_grab_owner_events;
extern GdkFBDisplay *gdk_display;
-extern GdkDrawableClass _gdk_fb_drawable_class;
extern FILE *debug_out;
GdkEvent *gdk_event_make(GdkWindow *window,
GdkEventType type,
@@ -436,8 +440,10 @@ void gdk_fb_redraw_all(void);
void gdk_fb_cursor_move (gint x, gint y, GdkWindow *in_window);
guint gdk_fb_keyboard_modifiers (void);
+gboolean gdk_fb_keyboard_init (gboolean open_dev);
gboolean gdk_fb_keyboard_open (void);
void gdk_fb_keyboard_close (void);
+gboolean gdk_fb_mouse_init (gboolean open_dev);
gboolean gdk_fb_mouse_open (void);
void gdk_fb_mouse_close (void);
void gdk_fb_mouse_get_info (gint *x,
diff --git a/gdk/linux-fb/gdkrender-fb.c b/gdk/linux-fb/gdkrender-fb.c
index 8db3e53d9..d63d6732a 100644
--- a/gdk/linux-fb/gdkrender-fb.c
+++ b/gdk/linux-fb/gdkrender-fb.c
@@ -1405,6 +1405,9 @@ void
gdk_shadow_fb_update (gint minx, gint miny, gint maxx, gint maxy)
{
struct itimerval timeout;
+
+ if (gdk_display->manager_blocked)
+ return;
g_assert (minx <= maxx);
g_assert (miny <= maxy);