Commit 75fd7f09 authored by Alexander Larsson's avatar Alexander Larsson Committed by Alexander Larsson

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.
parent 4168b478
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
......
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
......
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
......
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
......
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
......
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
......
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
......
......@@ -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
......
......@@ -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)
......
## 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
#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);</