]> Pileus Git - ~andy/gtk/commitdiff
Added --enable-fbmanager. This is some experimental code that lets several
authorAlexander Larsson <alexl@redhat.com>
Mon, 25 Jun 2001 23:01:36 +0000 (23:01 +0000)
committerAlexander Larsson <alexl@src.gnome.org>
Mon, 25 Jun 2001 23:01:36 +0000 (23:01 +0000)
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.

18 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
acconfig.h
configure.in
gdk/linux-fb/Makefile.am
gdk/linux-fb/gdkfbmanager.c [new file with mode: 0644]
gdk/linux-fb/gdkfbmanager.h [new file with mode: 0644]
gdk/linux-fb/gdkfbswitch.c [new file with mode: 0644]
gdk/linux-fb/gdkkeyboard-fb.c
gdk/linux-fb/gdkmain-fb.c
gdk/linux-fb/gdkmouse-fb.c
gdk/linux-fb/gdkprivate-fb.h
gdk/linux-fb/gdkrender-fb.c

index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
--- 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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index e94c717f15991275e5fd35321e1368916f85f0f5..a91bdb65503eb4ca0d177cc3052d9fb1b493b9f4 100644 (file)
@@ -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
index f2f4b4a1ef00357f6e63e8e9e279863b70c76cb2..37cd315876ac8082f042ae1760059ec1816c0eeb 100644 (file)
@@ -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
index 3b8eba5d76c2e87a4c56ef30830e1f9898c038e2..1f7e1a9424bd76c764f1412e4cae044199678808 100644 (file)
@@ -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)
index 795f15d9a9cfe888c5225275fe25544c3ebd5664..4e0f37eb23402300383d91c9944c3d442692ff67 100644 (file)
@@ -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 (file)
index 0000000..23cc495
--- /dev/null
@@ -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 (file)
index 0000000..653a1c6
--- /dev/null
@@ -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 (file)
index 0000000..707325f
--- /dev/null
@@ -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);
+}
index c5c8993ca691b959f3b17cd8cb0986489c4a71b3..2aebfff7676d1201c025ad48772966673beb98dd 100644 (file)
@@ -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 */
 }
 
index 77318ddeebc0cf241ea3155b8d4f78619516afad..6f0357e4069b40b1599ef5d613b8f47d70d15cf4 100644 (file)
 #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);
   
index 5e6fc3de5c8173d03383c65c7a15bc08460a9402..e89ab67b5d57ea6de06a06af17706a4e955586d0 100644 (file)
@@ -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
index 672ba605304e4ac6060f1a995c394e3752570d04..c7b12f6116e20c16091512c5e1ed7a443ebd2251 100644 (file)
@@ -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,
index 8db3e53d964ee00ee3e16563fb8b8f595f2170d5..d63d6732addbdc88cad4e61f9ae281603a4eda8f 100644 (file)
@@ -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);